Създаване на CI/CD верига и автоматизация на работа с Docker

Написах първите си сайтове в края на 90-те години. Тогава беше много лесно да ги приведеш в работно състояние. Имаше Apache-сервер на някакъв общ хостинг, към който можеше да се свържеш по FTP, като напишеш в адресната лента на браузъра нещо подобно на ftp://ftp.example.com. След това трябваше да въведеш име и парола и да качиш файловете на сървера. Бяха различни времена, всичко беше по-просто, отколкото сега.

Създаване на CI/CD верига и автоматизация на работа с Docker

През последните две десетилетия всичко се е променило значително. Сайтовете станаха по-сложни, и преди да бъдат пуснати в продукция, трябва да се компилират. Един единствен сървър стана множество сървъри, работещи с балансировачи на натоварването, и стана обичайно да се използват системи за контрол на версиите.

За моя личен проект имах специална конфигурация. И знаех, че ми е нужна възможност да разгръщам сайта в продукция, с едно единствено действие: запис на кода в клон master в GitHub. Освен това, знаех, че не искам да се занимавам с управление на огромен кластер Kubernetes, или да използвам технологията Docker Swarm, или да поддържам парк от сървъри с подове, агенти и всякакви други сложности, за да осигуря работата на моето малко уеб приложение. За да постигна целта да улесня максимално работата, ми се наложи да се запозная с CI/CD.

Ако имате малък проект (в нашия случай става дума за Node.js проект) и искате да разберете как да автоматизирате разгръщането му, така че това, което се съхранява в репозитория, да съответства на това, което работи в продукция, то предполагам, че статията може да ви заинтересува.

Предварителни изисквания

Очаква се читателят на тази статия да има основни познания в работата с команден ред и написването на Bash скриптове. Освен това ще му трябват акаунти Travis CI и Docker Hub.

Цели

Не бих казала, че тази статия може да бъде наречена безусловно "учебно ръководство". Това е по-скоро документ, в който разказвам какво съм научила и описвам удовлетворителния за мен процес на тестване и разгръщане на кода в продукция, извършван с едно автоматизирано преминаване.

Ето какъв е в крайна сметка моя работен процес.

За кода, изпратен в който и да е клон на репозитория, с изключение на master, се извършват следните действия:

  • Стартира се изграждането на проекта в Travis CI.
  • Изпълняват се всички модулни, интеграционни и крайни тестове.

Само за кода, който попада в master, се извършва следното:

  • Всичко, което беше казано по-горе, плюс…
  • Създаване на Docker образ на основата на текущия код, настройки и окружение.
  • Поставяне на образа в Docker Hub.
  • Свързване с производствения сървър.
  • Изтегляне на образа от Docker Hub на сървъра.
  • Спиране на текущия контейнер и стартиране на нов, базиран на новия образ.

Ако не знаете абсолютно нищо за Docker, образи и контейнери — не се притеснявайте. Ще ви разкажа за всичко това.

Какво е CI/CD?

Съкращението CI/CD се разшифрова като „непрекъсната интеграция/непрекъснато разпределение“.

▍Непрекъсната интеграция

Непрекъснатата интеграция е процес, при който разработчиците правят комити в основното хранилище на изходния код на проекта (обикновено в клон master). Качеството на кода се осигурява чрез автоматизирано тестване.

▍Непрекъснато разпределение

Непрекъснатото разпределение е често автоматизирано разпределение на код в производството. Втората част на съкращението CI/CD понякога се разглежда като „непрекъсната доставка“. Това, по принцип, е същото като „непрекъснато разпределение“, но „непрекъснатата доставка“ предполага необходимост от ръчно потвърждение на промените преди стартиране на процеса на разпределение на проекта.

Започване на работа

Приложението, в което аз усъществявах всичко това, се нарича TakeNote. Това е уеб проект, над който работя, предназначен за вземане на бележки. Първоначално се опитах да направя JAMStack-проект, или просто фронтенд приложение без сървър, за да се възползвам от стандартните възможности за хостинг и разпределение на проекти, които предлага Netlify. С нарастваща сложност на приложението, се нуждаех от създаването на неговата сървърна част, което означаваше, че трябваше да формулирам собствена стратегия за автоматизирана интеграция и автоматизирано разпределение на проекта.

В моя случай приложението представлява Express-сървър, работещ в среда Node.js, обслужващ едностранично React приложение и поддържащ защитен сървърен API. Тази архитектура следва стратегия, която може да бъде намерена в този ръководство за фуллстек автентикация.

Консултирах се с друг, който е експерт в автоматизацията, и го попитах какво трябва да направя, за да всичко да работи така, както ми е нужно. Той ми предложи идея как трябва да изглежда автоматизираният работен процес, описан в раздела „Цели“ на тази статия. Фактът, че си поставих подобни цели, означаваше, че трябва да разбера как да използвам Docker.

Docker

Docker е инструмент, който, благодарение на технологията за контейнеризация, позволява лесното разпространение на приложения, както и изпълнението им на една и съща среда, дори когато самата платформата Docker работи в различни среди. Първо, трябваше да си набавя инструментите за команден ред (CLI) на Docker. Инструкцията за инсталиране на Docker не може да се нарече много ясна и разбираема, но от нея може да се научи, че за да направите първата стъпка в инсталацията, трябва да изтеглите Docker Desktop (за Mac или Windows).

Docker Hub е нещо като GitHub за git хранилища, или регистър npm за JavaScript пакети. Това е онлайн хранилище за Docker изображения. Именно към него се свързва Docker Desktop.

И така, за да започнете работа с Docker, трябва да направите две неща:

След това можете да проверите работоспособността на Docker CLI, като изпълните следната команда за проверка на версията на Docker:

docker -v

След това влезте в Docker Hub, като въведете, когато ви попитат, вашето потребителско име и парола:

docker login

За да използвате Docker, трябва да разбирате концепциите за изображения и контейнери.

▍Изображения

Изображението е нещо като план, съдържащ инструкции за изграждане на контейнер. Това е неизменяем моментен снимка на файловата система и настройките на приложението. Разработчиците могат лесно да обменят изображения.

# Вывод сведений обо всех образах
docker images

Тази команда ще изведе таблица с следния заглавие:

РЕПОЗИТОРИЙ    ТАГ    ID НА ИЗОБРАЖЕНИЕ    СЪЗДАДЕНО    РАЗМЕР
---

По-нататък ще разгледаме някои примери на команди в същия формат — първо идва командата с коментар, а след това — пример за това, което тя може да изведе.

▍Контейнери

Контейнерът е изпълним пакет, който съдържа всичко необходимо за изпълнение на приложението. При такъв подход приложението ще работи по един и същи начин, независимо от инфраструктурата: в изолирана среда и в една и съща среда. Става въпрос за това, че в различни среди се стартират екземпляри на един и същи образ.

# Перечисление всех контейнеров
docker ps -a
CONTAINER ID     IMAGE     COMMAND     CREATED     STATUS     PORTS     NAMES
---

▍Тагове

Тагът е указание за конкретна версия на образа.

▍Кратко ръководство по командите на Docker

Ето преглед на някои от често използваните команди на Docker.

Команда

Контекст

Действие

docker build

Образ

Създаване на образ от Dockerfile

docker tag

Образ

Тагиране на образа

docker images

Образ

Извеждане на списък с образи

docker run

Контейнер

Стартиране на контейнер на базата на образа

docker push

Образ

Изпращане на образа в регистър

docker pull

Образ

Изтегляне на образа от регистра

docker ps

Контейнер

Извеждане на списък с контейнери

docker system prune

Образ/Контейнер

Премахване на неизползвани контейнери и образи

▍Файл Dockerfile

Знам как локално да стартирам приложението за продукция. Имам Webpack конфигурация, предназначена за компилиране на готово React приложение. След това имам команда, която стартира сървър, базиран на Node.js, на порт 5000. Изглежда ето така:

npm i          # инсталиране на зависимости
npm run build  # компилиране на React приложението
npm run start  # стартиране на Node сървъра

Трябва да отбележа, че нямам демонстрационно приложение за този материал. Но за експерименти подхожда всяко просто Node приложение.

За да ползвате контейнера, ще трябва да дадете инструкции на Docker. Това става чрез файл, наречен Dockerfile, който се намира в кореновата директория на проекта. Този файл на пръв поглед изглежда доста неразбираем.

Но това, което съдържа, всъщност описва, със специфични команди, нещо подобно на настройка на работна среда. Ето някои от тези команди:

  • OT — Тази команда стартира файла. В нея е указан базовият образ, на базата на който се изгражда контейнерът.
  • COPY — Копиране на файлове от локален източник в контейнера.
  • WORKDIR — Настройка на работната директория за следващите команди.
  • RUN — Изпълняване на команди.
  • EXPOSE — Настройка на порта.
  • ENTRYPOINT — Указание на изпълняваната команда.

Dockerfile може да изглежда приблизително така:

# Загрузить базовый образ
FROM node:12-alpine

# Скопировать файлы из текущей директории в директорию app/
COPY . app/

# Использовать app/ в роли рабочей директории
WORKDIR app/

# Установить зависимости (команда npm ci похожа npm i, но используется для автоматизированных сборок)
RUN npm ci --only-production

# Собрать клиентское React-приложение для продакшна
RUN npm run build

# Прослушивать указанный порт
EXPOSE 5000

# Запустить Node-сервер
ENTRYPOINT npm run start

В зависимост от избрания базов образ, може да е необходимо да инсталирате допълнителни зависимости. Факт е, че някои базови образи (като Node Alpine Linux) са създадени с цел да бъдат колкото се може по-компактни. В резултат на това в тях може да липсват някои програми, на които разчитате.

▍Сглобяване, тагиране и стартиране на контейнера

Локалното сглобяване и стартиране на контейнера - това е, след като имаме Dockerfile, задачите са доста прости. Преди да изпратите образа в Docker Hub, трябва да го тествате локално.

▍Сглобяване

На първо място, трябва да сглобите образа, посочвайки име и, което не е задължително, таг (ако тагът не е зададен, системата автоматично ще назначи таг на образа latest).

# Сборка образа
docker build -t <image>:<tag> .

След изпълнението на тази команда можете да наблюдавате как Docker изпълнява сглобяването на образа.

Изпращане на контекста на сглобяване към Docker демон   2.88MB
Стъпка 1/9 : ОТ node:12-alpine
 ---> ...изпълнение на етапите на сглобяване...
Успешно сглобен 123456789123
Успешно тагиран <image>:<tag>

Сглобяването може да отнеме няколко минути — всичко зависи от това колко зависимости имате. След завършване на сглобяването можете да изпълните командата docker images и да погледнете описанието на новия си образ.

РЕПОЗИТОРИЙ           TAG             IMAGE ID            СЪЗДАДЕН             РАЗМЕР
<image>             latest           123456789123        Преди около минута    x.xxGB

▍Стартиране

Образът е създаден. А това означава, че на негова основа може да се стартира контейнер. Понеже искам да имам възможност да се свържа с приложението, работещо в контейнера, на адрес localhost:5000, в лявата част на двойката 5000:5000 в следната команда зададох 5000. В дясната част се намира портът на контейнера.

# Запуск с использованием локального порта 5000 и порта контейнера 5000
docker run -p 5000:5000 <image>:<tag>

Сега, когато контейнерът е създаден и стартиран, можете да използвате командата docker ps за да погледнете информацията за този контейнер (или можете да използвате командата docker ps -a, която извежда информация за всички контейнери, а не само за работещите).

CONTAINER ID       IMAGE             COMMAND                  СЪЗДАДЕН             СТАТУС                PORTS                  NAMES
987654321234        <image>       "\/bin\/sh -c 'npm run…"   6 секунди назад       Up 6 секунди           0.0.0.0:5000->5000\/tcp   stoic_darwin

Ако сега отидете на адрес localhost:5000 , можете да видите страницата на работещото приложение, която изглежда точно така, както страницата на приложението, работещо в продукционна среда.

▍Назначаване на таг и публикуване

За да се възползвате от един от създадените образи на продукционния сървър, е необходимо да имате възможност да качите този образ от Docker Hub. Това означава, че първо трябва да създадете хранилище на Docker Hub за проекта. След това ще имате място, където да изпратите образа. Образът трябва да бъде преименуван така, че името му да започва с вашето потребителско име на Docker Hub. След това трябва да идва името на хранилището. В края на името може да има произволен таг. По-долу е показан пример за именуване на образи според тази схема.

Сега можете да съберете образа с новото му име и да изпълните командата docker push за изпращането му в хранилището на Docker Hub.

docker build -t /: .
docker tag /: /:latest
docker push /:

# На практика това може да изглежда, например, така:
docker build -t user/app:v1.0.0 .
docker tag user/app:v1.0.0 user/app:latest
docker push user/app:v1.0.0

Ако всичко мине както трябва, образът ще бъде наличен на Docker Hub и ще може да бъде лесно качен на сървъра или предаден на други разработчици.

Следващи стъпки

Към този момент сме се уверили, че приложението, под формата на Docker контейнер, работи локално. Качихме контейнера на Docker Hub. Всичко това означава, че вече сме напреднали доста към целта. Сега трябва да решим още два въпроса:

  • Настройка на CI инструмента за тестване и разгръщане на кода.
  • Настройка на продукционния сървър така, че да може да зарежда и стартира нашия код.

В нашия случай като CI/CD решение се използва Travis CI. Като сървър — DigitalOcean.

Трябва да отбележа, че тук можете да използвате и друга комбинация от услуги. Например, вместо Travis CI можете да използвате CircleCI или Github Actions. А вместо DigitalOcean — AWS или Linode.

Решихме да работим с Travis CI и в този сервис вече имам настроено нещо. Затова сега накратко ще разкажа как да го подготвите за работа.

Travis CI

Travis CI е инструмент за тестване и разгръщане на кода. Не бих искал да влизам в детайлите на настройката на Travis CI, тъй като всеки проект е уникален и това не би било особено полезно. Но ще разкажа за основите, които ще ви позволят да започнете работа в случай, че решите да ползвате Travis CI. Каквото и да изберете — Travis CI, CircleCI, Jenkins или нещо друго, навсякъде ще се прилагат подобни методи за настройка.

За да започнете работа с Travis CI, посетете уебсайта на проекта и създайте профил. След това интегрирайте Travis CI с вашия GitHub акаунт. По време на настройката на системата ще трябва да посочите репозиторий, с който искате да автоматизирате работата и да осигурите достъп до него. (Използвам GitHub, но съм сигурна, че Travis CI може да се интегрира и с BitBucket, и с GitLab, и с други подобни услуги).

Всеки път, когато Travis CI започва работа, се стартира сървър, който изпълнява командите, посочени в конфигурационния файл, включително разгръщане на съответните клонове на репозитория.

▍Жизнен цикъл на задачата

Конфигурационният файл на Travis CI, наречен .travis.yml и съхраняван в кореновата директория на проекта, поддържа концепцията за събития жизнен цикъл на задачата. Ето тези събития, представени в реда, в който се случват:

  • apt addons
  • cache components
  • before_install
  • install
  • before_script
  • script
  • before_cache
  • after_success или after_failure
  • before_deploy
  • deploy
  • after_deploy
  • after_script

▍Тестиране

В конфигурационния файл възнамерявам да настроя локален сървър на Travis CI. За език съм избрала Node версия 12 и указах на системата да инсталира зависимостите, необходими за използване на Docker.

Всичко, изброено в .travis.yml, ще се изпълнява при всеки pull request за всички клонове на репозитория, освен ако не е указано друго. Това е полезна характеристика, тъй като означава, че можем да тестваме целия код, който постъпва в репозитория. Това позволява да знаем дали кодът е готов за запис в клона master, и няма ли да наруши процеса на компилиране на проекта. В тази глобална конфигурация инсталирам всичко локално, стартирам сървъра за разработчици Webpack на заден план (това е част от моя работен процес) и изпълнявам тестовете.

Ако искате да се показват значки с информация за покритието на кода с тестове във вашия репозиторий, тук можете да намерите кратко ръководство за използване на Jest, Travis CI и Coveralls за събиране и показване на тези данни.

И така, ето съдържанието на файла .travis.yml:

# Установить язык
language: node_js

# Установить версию Node.js
node_js:
  - '12'

services:
  # Использовать командную строку Docker
  - docker

install:
  # Установить зависимости для тестов
  - npm ci

before_script:
  # Запустить сервер и клиент для тестов
  - npm run dev &

script:
  # Запустить тесты
  - npm run test

Тук приключват действията, които се извършват за всички клони на репозитория и за pull requests.

▍Разгръщане

Предполагайки, че всички автоматизирани тестове са завършили успешно, можем, без да е задължително, да разположим кода на производствения сървър. Тъй като искаме да правим това само за кода от клона master, ние даваме на системата съответни инструкции в настройките за разгръщане. Преди да опитате да използвате кода в проекта си, който ще разгледаме по-нататък, искам да ви предупредя, че трябва да имате реален скрипт, който да се извиква за разгръщането.

deploy:
  # Събиране на Docker контейнер и изпращането му в Docker Hub
  provider: script
  script: bash deploy.sh
  on:
    branch: master

Скриптът за разгръщане решава две задачи:

  • Събиране, тагиране и изпращане на изображение в Docker Hub с помощта на CI инструмент (в нашия случай Travis CI).
  • Изтегляне на изображението на сървъра, спиране на стария контейнер и стартиране на новия (в нашия случай сървърът работи на платформата DigitalOcean).

Първо, трябва да настроите автоматичния процес за събиране, тагиране и изпращане на изображение в Docker Hub. Всичко това е доста похоже на това, което вече правихме ръчно, с изключение на това, че тук ни е необходима стратегия за задаване на уникални тагове на изображенията и автоматизация на входа в системата. Имах трудности с някои детайли на скрипта за разгръщане, като стратегията за тагиране, входа в системата, кодировката на SSH ключовете и установяването на SSH връзката. Но, за щастие, моят приятел се справя много добре с bash, както и с много други неща. Той ми помогна да напиша този скрипт.

И така, първата част на скрипта е изпращането на изображение в Docker Hub. Да го направите е доста просто. Използваната от мен схема за тагиране предвижда комбиниране на git хеш и git таг, ако съществува. Това позволява да се създаде уникален таг и улеснява идентификацията на сборката, на която той се основава. DOCKER_USERNAME и DOCKER_PASSWORD — това са потребителски променливи на средата, които могат да бъдат зададени чрез интерфейса на Travis CI. Travis CI автоматично ще обработи секретните данни, така че да не попаднат в грешни ръце.

Ето първата част на скрипта deploy.sh.

#!/bin/sh
set -e # Остановить скрипт при наличии ошибок

IMAGE="<username>/<repository>"                             # Образ Docker
GIT_VERSION=$(git describe --always --abbrev --tags --long) # Git-хэш и теги

# Сборка и тегирование образа
docker build -t ${IMAGE}:${GIT_VERSION} .
docker tag ${IMAGE}:${GIT_VERSION} ${IMAGE}:latest

# Вход в Docker Hub и выгрузка образа
echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
docker push ${IMAGE}:${GIT_VERSION}

Каква ще бъде втората част на скрипта, изцяло зависи от това кой хост използвате и как е организирано свързването с него. В моя случай, тъй като ползвам Digital Ocean, за свързване със сървера се използват команди doctl. При работа с Aws ще се използва инструментът aws, и така нататък.

Настройването на работата на сървъра не беше особено трудно. Така, аз настроих дроплет, базиран на основен образ. Трябва да се отбележи, че избраната от мен система изисква извършването на еднократна ръчна инсталация на Docker и еднократно ръчно стартиране на Docker. Аз, за инсталирането на Docker, използвах Ubuntu 18.04, затова вие, ако също използвате Ubuntu, за да направите същото, можете просто да следвате това простичко ръководство.

Не говоря конкретно за командите за услугата, тъй като този аспект може да варира значително в различни случаи. Просто ще предоставя общ план на действията, изпълнявани след свързването по SSH към сървъра, на който ще бъде разположен проектът:

  • Трябва да намерите контейнера, който в момента работи, и да го спрете.
  • След това трябва да стартирате нов контейнер на заден план.
  • Нужно е да зададете локалния порт на сървъра на стойност 80 — това ще позволи достъп до сайта на адрес от вида example.com, без да се посочва порта, а не да се използва адрес от вида example.com:5000.
  • И накрая, трябва да изтриете всички стари контейнери и образи.

Ето продължението на скрипта.

# Найти ID работающего контейнера
CONTAINER_ID=$(docker ps | grep takenote | cut -d" " -f1)

# Остановить старый контейнер, запустить новый, очистить систему
docker stop ${CONTAINER_ID}
docker run --restart unless-stopped -d -p 80:5000 ${IMAGE}:${GIT_VERSION}
docker system prune -a -f

Някои неща, на които трябва да се обърне внимание

Възможно е, когато се свържете към сървера по SSH от Travis CI, да видите предупреждение, което няма да позволи продължаването на инсталацията, тъй като системата ще чака реакция от потребителя.

Автентичността на хоста ' ()' не може да бъде установена.
RSA ключовият отпечатък е .
Сигурни ли сте, че искате да продължите свързването (да/не)?

Научих, че стринг ключът може да бъде кодиране в base64, за да се запази в такъв вид, в който с него може да се работи удобно и надеждно. На етапа на инсталацията можете да декодирате публичния ключ и да го запишете в файл known_hosts за да се отървете от гореспоменатата грешка.

echo  | base64 # извежда

На практика тази команда може да изглежда така:

echo "123.45.67.89 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== you@example.com" | base64

А ето как изглежда това, което тя извежда — стринг в кодировката base64:

MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==

Ето командата, за която се спомена по-горе

install:
  - echo  | base64 -d >> $HOME/.ssh/known_hosts

Същият подход може да се използва и с личния ключ при установяване на връзка, тъй като за достъп до сървера може да ви бъде необходим личен ключ. При работа с ключа трябва само да осигурите безопасното му съхранение в променлива на околната среда на Travis CI и да се уверите, че не се извежда никъде.

Още едно нещо, на което си струва да обърнете внимание, е че може да се наложи да стартирате целия скрипт за разгръщане, представен в един ред, например — с помощта на doctl. Това може да изисква известни допълнителни усилия.

doctl compute ssh  --ssh-command "всички команди ще бъдат тук && тук"

TLS/SSL и натоварващ баланс

След като направих всичко, за което се говореше по-горе, последната проява на проблемите пред мен беше, че сървърът нямаше SSL. Тъй като използвам сървър на Node.js, за да накарам да работи обратния прокси Nginx и Let’s Encrypt, трябваше да се потрудя малко.

Въобще не ми се искаше да извършвам всичките тези настройки на SSL ръчно, затова просто създадох балансировчик на натоварването и записах неговите данни в DNS. В случая с DigitalOcean, например, създаването на автопрезаписващ самоподписан сертификат на балансировчика на натоварването е проста, безплатна и бърза процедура. Този подход има и допълнително предимство — ако е необходимо, позволява много лесно да се настрои SSL на множество сървъри, работещи зад балансировчика на натоварването. Той позволява самите сървъри да не се „замислят“ за SSL, но все пак да използват, както обикновено, порт 80. Така че настройването на SSL на балансировчика на натоварването е значително по-лесно и удобно, отколкото алтернативните методи за настройване на SSL.

Сега можете да затворите на сървъра всички портове, приемащи входящи връзки — освен порта 80, използван за свързване с балансировчика на натоварването, и порта 22 за SSH. В резултат на това опитът за директен достъп до сървъра при всякакви портове, с изключение на тези два, ще бъде неуспешен.

Резюме

След като направих всичко, което споменах в този материал, вече не ме плашеха нито платформата Docker, нито концепцията за автоматизирани CI/CD вериги. Успях да настроя веригата за непрекъсната интеграция, по време на която се извършва тестване на кода преди да влезе в продукция и автоматично разгръщане на кода на сървъра. Всичко това ми е все още относително ново, и съм сигурна, че има начини да подобря автоматизирания си работен процес и да го направя по-ефективен. Затова, ако имате идеи по този въпрос — дайте ми знак. ми Надявам се, че тази статия ви е помогнала в работата. Искам да вярвам, че като я прочетете, сте научили толкова, колкото аз, докато се справях с всичко, за което пиша тук.

P.S. В нашия маркетплейс има образ Docker, който се инсталира с едно кликване. Можете да проверите работата на контейнерите на VPS. На всички нови клиенти се предоставят безплатно 3 дни за тестване.

Уважаеми читатели! Използвате ли технологии CI/CD в проектите си?

Създаване на CI/CD верига и автоматизация на работа с Docker

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster