Створення CI/CD-ланцюжка та автоматизація роботи з Docker

Я написала мої перші сайти наприкінці 90-х. Тоді наводити їх у робочий стан було дуже просто. Був Apache-сервер на якомусь спільному хостингу, на цей сервер можна було увійти по FTP, написавши в браузерному рядку щось на зразок ftp://ftp.example.com. Потім треба було ввести ім'я та пароль та вивантажити файли на сервер. Інші були часи, все тоді було простіше, ніж зараз.

Створення CI/CD-ланцюжка та автоматизація роботи з Docker

За минулі з того часу два десятиліття все значно змінилося. Сайти стали складнішими, їх перед випуском у продакшн треба збирати. Один єдиний сервер став безліччю серверів, які працюють за балансувальниками навантаження, звичайною справою стало використання систем контролю версій.

Для мого персонального проекту я мала особливу конфігурацію. І я знала, що мені потрібна можливість розгортати сайт у продакшні, виконуючи лише одну дію: запис коду у гілку master на GitHub. Я, крім того, знала, що мені, для забезпечення роботи мого маленького веб-додатку, не хочеться займатися управлінням величезним кластером Kubernetes, або користуватися технологією Docker Swarm, або підтримувати парк серверів з подами, агентами та іншими труднощами. Для того, щоб досягти мети максимального спрощення роботи, мені знадобилося познайомитися з CI/CD.

Якщо у вас є маленький проект (у нашому випадку йдеться про Node.js-проект) і вам хотілося б дізнатися про те, як автоматизувати розгортання цього проекту, зробивши при цьому так, щоб те, що зберігається в репозиторії, точно відповідало б тому, що працює у продакшні, то, гадаю, вас може зацікавити ця стаття.

попередні вимоги

Очікується, що читач цієї статті має базові знання в галузі роботи з командним рядком та написання Bash-скриптів. Крім того, йому знадобляться облікові записи Тревіс К.І. и Докер-концентратор.

Цілі

Не скажу, що ця стаття може беззастережно називатись «навчальним керівництвом». Це — скоріше документ, в якому я розповідаю про те, що дізналася, і описую процес тестування і розгортання коду в продакшні, що влаштовує мене, виконуваний за один автоматизований прохід.

Ось яким у результаті вийшов мій робочий процес.

Для коду, відправленого в будь-яку гілку репозиторію, крім master, Виробляються такі дії:

  • Запускається складання проекту на Travis CI.
  • Виконуються всі модульні, інтеграційні та наскрізні тести.

Тільки для коду, який потрапляє у master, виконується наступне:

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

Якщо ви абсолютно нічого не знаєте про Docker, образи і контейнери - не турбуйтеся. Я про це вам розповім.

Що таке CI/CD?

Абревіатура CI/CD розшифровується як "continuous integration/continuous deployment" - "безперервна інтеграція/безперервне розгортання".

▍ Безперервна інтеграція

Безперервна інтеграція - це процес, в ході якого розробники роблять коміти в головне сховище вихідного коду проекту (зазвичай у гілку master). При цьому якість коду забезпечується шляхом автоматизованого тестування.

▍ Безперервне розгортання

Безперервне розгортання - це часто автоматизоване розгортання коду в продакшні. Друга частина абревіатури CI/CD іноді розкривається як "continuous delivery" ("безперервна доставка"). Це, загалом, те саме, що й «безперервне розгортання», але «безперервна доставка» має на увазі необхідність ручного підтвердження змін перед запуском процесу розгортання проекту.

Початок роботи

Додаток, на якому я це все освоювала, називається Брати до відома. Це веб-проект, над яким я працюю, призначений для того, щоб робити нотатки. Спочатку я спробувала зробити JAMStack-проект, або тільки фронтенд-додаток без сервера, для того, щоб скористатися стандартними можливостями з хостингу та розгортання проектів, які пропонує netlify. У міру того, як зростала складність програми, мені знадобилося створити і його серверну частину, а це означало, що мені треба було б сформувати власну стратегію автоматизованої інтеграції та автоматизованого розгортання проекту.

У моєму випадку програма є Express-сервером, що працює в середовищі Node.js, обслуговує односторінкову React-додаток і підтримує захищений серверний API. Ця архітектура слідує стратегії, яку можна знайти в даному посібник з фуллстек-аутентифікації.

Я порадилася з другом, Який є експертом з автоматизації, і запитала його про те, що мені треба зробити для того, щоб все це працювало так, як мені потрібно. Він підкинув мені ідею про те, як має виглядати автоматизований робочий процес, викладений у розділі Цілі цієї статті. Те, що я поставила перед собою подібну мету, означало, що мені потрібно розібратися в тому, як користуватися Docker.

Docker

Docker — це інструмент, який, завдяки технології контейнеризації, дозволяє легко розповсюджувати програми, а також виконувати їх розгортання та запуск в тому самому оточенні навіть у тому випадку, якщо сама платформа Docker працює в різних середовищах. Для початку мені потрібно було отримати у своє розпорядження інструменти командного рядка (CLI) Docker. інструкцію по установці Docker не можна назвати дуже чіткою та зрозумілою, але з неї можна дізнатися про те, що для того, щоб зробити перший крок установки, треба завантажити Docker Desktop (для Mac або Windows).

Docker Hub — це приблизно те саме, що GitHub для git-репозиторіїв, або реєстр нмм для JavaScript-пакетів. Це онлайн-репозиторій для образів Docker. До нього підключається Docker Desktop.

Отже, для того, щоб приступити до роботи з Docker, потрібно зробити дві речі:

Після цього можете перевірити працездатність Docker CLI, виконавши наступну команду для перевірки версії Docker:

docker -v

Далі, увійдіть в Docker Hub, ввівши, коли вас про це запитають, своє ім'я користувача та пароль:

docker login

Для того, щоб користуватися Docker, ви повинні розуміти концепції образів та контейнерів.

▍Образи

Образ — це щось подібне до плану, що містить інструкції зі збирання контейнера. Це незмінний знімок файлової системи та налаштувань програми. Розробники можуть легко обмінюватися образами.

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

Ця команда виведе таблицю з наступним заголовком:

REPOSITORY     TAG     IMAGE ID     CREATED     SIZE
---

Далі ми розглядатимемо деякі приклади команд у такому ж форматі — спочатку йде команда з коментарем, а потім — приклад того, що вона може вивести.

▍Контейнери

Контейнер — це пакет, що виконується, який містить все, що потрібно для виконання програми. Додаток при такому підході завжди працюватиме однаково, незалежно від інфраструктури: в ізольованому оточенні та в тому самому середовищі. Йдеться у тому, що у різних оточеннях запускаються екземпляри однієї й тієї образу.

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

▍Теги

Тег – це вказівка ​​на конкретну версію образу.

▍Коротка довідка по командам Docker

Ось огляд деяких часто використовуваних команд Docker.

Команда

Контекст

Дія

збірка докера

образ

Складання образу з Dockerfile

docker tag

образ

Тегування образу

Докер зображення

образ

Виведення списку образів

докер-біг

контейнер

Запуск контейнера на основі образу

docker push

образ

Надсилання образу до реєстру

докер тягнути

образ

Завантаження образу з реєстру

Докер ПС

контейнер

Виведення списку контейнерів

docker system prune

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

Видалення контейнерів та образів, що не використовуються.

▍Файл Dockerfile

Я знаю, як локально запустити програму для продакшну. У мене є Webpack-конфігурація, призначена для складання готової програми React. Далі, я маю команду, яка запускає сервер, заснований на Node.js, на порті 5000. Виглядає так:

npm i         # установка зависимостей
npm run build # сборка React-приложения
npm run start # запуск Node-сервера

Треба зазначити, що я не маю програми-прикладу для цього матеріалу. Але тут, для експериментів, підійде будь-яка проста Node-додаток.

Для того, щоб скористатися контейнером, вам доведеться дати інструкції Docker. Робиться це за допомогою файлу, званого Dockerfile, що знаходиться в кореневій директорії проекту. Цей файл, спочатку, здається досить незрозумілим.

Але те, що в ньому міститься, лише описує, особливими командами, щось подібне до налаштування робочого оточення. Ось деякі з цих команд:

  • З - Ця команда починає файл. У ньому вказується базовий образ, основі якого будується контейнер.
  • КОПІЯ — Копіювання файлів із локального джерела в контейнер.
  • РОБОЧИЙ DIR - Встановлення робочої директорії для наступних команд.
  • RUN - Запуск команд.
  • ВИКРИТИ - Налаштування порту.
  • ТОЧКА ВХОДУ - Вказівка ​​виконуваної команди.

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 виконує збирання образу.

Sending build context to Docker daemon   2.88MB
Step 1/9 : FROM node:12-alpine
 ---> ...выполнение этапов сборки...
Successfully built 123456789123
Successfully tagged <image>:<tag>

Складання може зайняти кілька хвилин - тут все залежить від того, скільки у вас є залежностей. Після завершення збирання можна виконати команду docker images і подивитись опис свого нового образу.

REPOSITORY          TAG               IMAGE ID            CREATED              SIZE
<image>             latest            123456789123        About a minute ago   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                  CREATED              STATUS                      PORTS                    NAMES
987654321234        <image>             "/bin/sh -c 'npm run…"   6 seconds ago        Up 6 seconds                0.0.0.0:5000->5000/tcp   stoic_darwin

Якщо перейти тепер на адресу localhost:5000 — можна побачити сторінку працюючого додатка, яка виглядає так само, як сторінка додатка, що працює в продакшн-оточенні.

▍Призначення тега та публікація

Для того, щоб скористатися одним із створених образів на продакшн-сервері, потрібно, щоб у нас була можливість завантажити цей образ з Docker Hub. Це означає, що спочатку потрібно створити на Docker Hub репозиторій для проекту. Після цього у нашому розпорядженні опиниться місце, куди можна оправити образ. Образ треба перейменувати так, щоб його ім'я починалося з нашого імені користувача Docker Hub. Після цього має йти назва репозиторію. Наприкінці імені може розташовуватися будь-який тег. Нижче наведено приклад іменування образів за цією схемою.

Тепер можна зібрати образ із призначенням йому нового імені та виконати команду docker push для відправки його до репозиторію Docker Hub.

docker build -t <username>/<repository>:<tag> .
docker tag <username>/<repository>:<tag> <username>/<repository>:latest
docker push <username>/<repository>:<tag>

# На практике это может выглядеть, например, так:
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-рішення використовується Тревіс К.І.. Як сервер — DitigalOcean.

Слід зазначити, що тут можна скористатися й іншою комбінацією сервісів. Наприклад, замість Travis CI можна скористатися CircleCI або Github Actions. А замість DigitalOcean - AWS або Linode.

Ми вирішили працювати з 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-запитів у всі гілки репозиторію, якщо не зазначено інше. Це корисна особливість, тому що вона означає, що ми можемо тестувати весь код, що надходить до репозиторію. Це дозволяє знати, чи готовий код до запису у гілку. 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-запросов.

▍Розгортання

Виходячи з припущення, що всі автоматизовані тести завершилися успішно, ми, що робити необов'язково, можемо розгорнути код на продакшн-сервері. Тому що ми хочемо робити це лише для коду з гілки 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, ви побачите попередження, яке не дозволить продовжити установку, оскільки система чекатиме реакції користувача.

The authenticity of host '<hostname> (<IP address>)' can't be established.
RSA key fingerprint is <key fingerprint>.
Are you sure you want to continue connecting (yes/no)?

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

echo <public key> | base64 # выводит <публичный ключ, закодированный в 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== [email protected]" | base64

А ось як виглядає те, що вона видає - рядок у кодуванні base64:

MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==

Ось команда, про яку йшлося вище

install:
  - echo < публичный ключ, закодированный в base64> | base64 -d >> $HOME/.ssh/known_hosts

Той самий підхід можна використовувати з приватним ключем при встановленні з'єднання, тому що вам, для доступу до сервера, цілком може знадобитися приватний ключ. При роботі з ключем вам лише потрібно забезпечити його безпечне зберігання у змінній оточенні Travis CI, і те, щоб він ніде не виводився б.

Ще одна річ, на яку варто звернути увагу, це те, що вам може знадобитися запустити весь скрипт розгортання, представлений у вигляді одного рядка, наприклад, за допомогою doctl. Це може вимагати додаткових зусиль.

doctl compute ssh <droplet> --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-ланцюжків. Я змогла налаштувати ланцюжок безперервної інтеграції, під час виконання якого проводиться тестування коду до потрапляння його в продакшн та автоматичне розгортання коду на сервері. Все це для мене поки що відносно нове, і я впевнена, що є способи покращити мій автоматизований робочий процес і зробити його ефективнішим. Тому якщо у вас є ідеї щодо цього — дайте мені знати. Сподіваюся, що ця стаття допомогла вам у ваших справах. Мені хочеться вірити, що прочитавши її, ви дізналися стільки ж, скільки я дізналася, поки розбиралася з усім тим, про що в ній розповіла.

PS У нашому маркетплейсе є образ Dockerякий встановлюється в один клік. Ви можете перевірити роботу контейнерів на VPS. Всім новим клієнтам надаються безкоштовно 3 дні для тестування.

Шановні читачі! Чи користуєтеся технологіями CI/CD у своїх проектах?

Створення CI/CD-ланцюжка та автоматизація роботи з Docker

Джерело: habr.com

Додати коментар або відгук