Docker Compose: від розробки до продакшену

Переклад транскрипції подкасту підготовлений напередодні старту курсу «Адміністратор Linux»

Docker Compose: від розробки до продакшену

Docker Compose – це дивовижний інструмент для створення робітника
оточення для стека, який використовується у вашому додатку. Він дозволяє вам визначати
кожен компонент вашої програми, слідуючи чіткому та простому синтаксису в YAML-
файлах
.

З появою docker compose v3 ці YAML-файли можуть використовуватися безпосередньо в робочому середовищі, при роботі з
кластером Докер-рій.

Але це означає, що ви можете використовувати один і той же docker-compose файл в
процесі розробки та у продакшен середовищі? Або використовувати цей же файл для
стейджингу? Ну, загалом — так, але для такого функціоналу нам потрібне таке:

  • Інтерполяція змінних: використання змінних середовища для деяких
    значень, які змінюються у кожному середовищі.
  • Перевизначення конфігурації: можливість визначити другий (або будь-який
    інший наступний) docker-compose файл, який щось змінить щодо
    Перше, і docker compose подбає про злиття обох файлів.

Відмінності між файлами для розробки та продакшену

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

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

Натомість ми, зазвичай, хочемо створити образ із конкретною версією вашого коду.
Його прийнято позначати відповідним тегом (можна використовувати семантичне
версіонування або іншу систему на ваш розсуд).

Перевизначення конфігурації

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

Docker compose підтримує об'єднання різних compose-файлів для
одержання остаточної конфігурації. Як це працює, можна побачити на прикладі:

$ cat docker-compose.yml
version: "3.2"

services:
  whale:
    image: docker/whalesay
    command: ["cowsay", "hello!"]
$ docker-compose up
Creating network "composeconfigs_default" with the default driver
Starting composeconfigs_whale_1
Attaching to composeconfigs_whale_1
whale_1  |  ________
whale_1  | < hello! >
whale_1  |  --------
whale_1  |     
whale_1  |      
whale_1  |       
whale_1  |                     ##        .
whale_1  |               ## ## ##       ==
whale_1  |            ## ## ## ##      ===
whale_1  |        /""""""""""""""""___/ ===
whale_1  |   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
whale_1  |        ______ o          __/
whale_1  |                     __/
whale_1  |           __________/
composeconfigs_whale_1 exited with code 0

Як було сказано, docker compose підтримує об'єднання кількох compose-
Це дозволяє перевизначати різні параметри в другому файлі. Наприклад:

$ cat docker-compose.second.yml
version: "3.2"
services:
  whale:
    command: ["cowsay", "bye!"]

$ docker-compose -f docker-compose.yml -f docker-compose.second.yml up
Creating composeconfigs_whale_1
Attaching to composeconfigs_whale_1
whale_1  |  ______
whale_1  | < bye! >
whale_1  |  ------
whale_1  |     
whale_1  |      
whale_1  |       
whale_1  |                     ##        .
whale_1  |               ## ## ##       ==
whale_1  |            ## ## ## ##      ===
whale_1  |        /""""""""""""""""___/ ===
whale_1  |   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
whale_1  |        ______ o          __/
whale_1  |                     __/
whale_1  |           __________/
composeconfigs_whale_1 exited with code 0

Такий синтаксис не дуже зручний у процесі розробки, коли команду
знадобиться виконувати безліч разів.

На щастя, docker compose автоматично шукає спеціальний файл з ім'ям
docker-compose.override.yml для перевизначення значень докер-компост.імл. Якщо
перейменувати другий файл, то вийде той самий результат, тільки за допомогою початкової команди:

$ mv docker-compose.second.yml docker-compose.override.yml
$ docker-compose up
Starting composeconfigs_whale_1
Attaching to composeconfigs_whale_1
whale_1  |  ______
whale_1  | < bye! >
whale_1  |  ------
whale_1  |     
whale_1  |      
whale_1  |       
whale_1  |                     ##        .
whale_1  |               ## ## ##       ==
whale_1  |            ## ## ## ##      ===
whale_1  |        /""""""""""""""""___/ ===
whale_1  |   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
whale_1  |        ______ o          __/
whale_1  |                     __/
whale_1  |           __________/
composeconfigs_whale_1 exited with code 0

Добре, так запам'ятати простіше.

Інтерполяція змінних

Файли конфігурації підтримують інтерполяцію
змінних
та значення за замовчуванням. Тобто ви можете зробити таке:

services:
  my-service:
    build:
      context: .
    image: private.registry.mine/my-stack/my-service:${MY_SERVICE_VERSION:-latest}
...

І якщо ви виконуєте docker-compose build (або push) без змінної оточення
$MY_SERVICE_VERSION, буде використано значення останній, але якщо ви встановите
значення змінної оточення до складання, воно буде використано при складанні або пуші
у регістр private.registry.mine.

Мої принципи

Підходи, які зручні для мене, можуть стати у нагоді і вам. Я слідую цим
простим правилам:

  • Усі мої стеки для продакшену, розробки (або інших середовищ) визначаються через
    файли docker-compose
  • Файли конфігурації, необхідні для охоплення всіх середовищ, максимально
    уникають дублювання.
  • Мені потрібна одна проста команда для роботи в кожному середовищі.
  • Основна конфігурація визначається у файлі докер-компост.імл.
  • Змінні середовища використовуються для визначення тегів або інших образів
    змінних, які можуть змінюватися від середовища до середовища (стейджинг, інтеграція,
    продакшен).
  • Значення змінних для продакшена використовуються як значення по
    за замовчуванням, це мінімізує ризики у разі запуску стека в продакшені без
    встановленої змінної оточення.
  • Для запуску сервісу у продакшен-середовищі використовується команда docker stack deploy - compose-file docker-compose.yml -with-registry-auth my-stack-name.
  • Робоче оточення запускається за допомогою команди докер-створити -d.

Погляньмо на простий приклад.

# docker-compose.yml
...
services:
  my-service:
    build:
      context: .
    image: private.registry.mine/my-stack/my-service:${MY_SERVICE_VERSION:-latest}
    environment:
      API_ENDPOINT: ${API_ENDPOINT:-https://production.my-api.com}
...

И

# docker-compose.override.yml
...
services:
  my-service:
    ports: # This is needed for development!
      - 80:80
    environment:
      API_ENDPOINT: https://devel.my-api.com
    volumes:
      - ./:/project/src
...

Я можу використовувати docker-compose (docker-compose up), щоб запустити стек в
режим розробки з вихідним кодом, змонтованим у /project/src.

Я можу використовувати ці файли на продакшені! І я міг би використати точно
такий же файл докер-компост.імл для стейджингу. Щоб розгорнути це на
продакшен, мені просто потрібно зібрати та відправити образ із зумовленим тегом
на етапі CI:

export MY_SERVICE_VERSION=1.2.3
docker-compose -f docker-compose.yml build
docker-compose -f docker-compose.yml push

На продакшені це можна запустити за допомогою наступних команд:

export MY_SERVICE_VERSION=1.2.3
docker stack deploy my-stack --compose-file docker-compose.yml --with-registry-auth

І якщо ви хочете зробити те саме на стейджі, необхідно просто визначити
необхідні змінні оточення для роботи в середовищі стейджингу:

export MY_SERVICE_VERSION=1.2.3
export API_ENDPOINT=http://staging.my-api.com
docker stack deploy my-stack --compose-file docker-compose.yml --with-registry-auth

У результаті ми використовували два різних docker-compose файли, які без
дублювання конфігурацій можуть використовуватися для будь-якого вашого середовища!

Дізнатись докладніше про курс «Адміністратор Linux»

Джерело: habr.com

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