Пошук уроків, статей та іншого контенту
Створите надійну конфігурацію Compose для production із мережами, томами, секретами та політиками сервісів.
Production-конфігурація Docker Compose повинна явно описувати:
які сервіси запускаються;
у яких мережах вони працюють;
які дані мають переживати перезапуск контейнера;
як передаються паролі та інші секрети;
що відбувається після падіння сервісу;
як визначити готовність залежностей;
які ресурси доступні контейнеру;
які порти справді потрібно публікувати назовні.
Compose-файл для production — це не просто список образів. Він задає межі доступу, життєвий цикл контейнерів і спосіб зберігання даних.
У сучасному Docker Compose ключ version зазвичай не потрібен. Compose використовує актуальну Compose Specification.
Типова структура має такий вигляд:
services:
app:
image: example/app:1.4.2
networks:
- public
- private
volumes:
- uploads:/var/lib/app/uploads
secrets:
- app_secret
restart: unless-stopped
networks:
public:
private:
internal: true
volumes:
uploads:
secrets:
app_secret:
file: ./secrets/app_secret.txtФіксуйте конкретні версії образів:
image: postgres:16.4Тег latest небезпечний для production, оскільки однаковий Compose-файл може запустити різні версії образу в різний час.
Не кожен сервіс повинен бути доступним з інтернету.
Зазвичай використовують щонайменше дві мережі:
public — для reverse proxy або frontend;
private — для внутрішнього обміну між застосунком і базою даних.
Мережа з параметром internal: true не призначена для зовнішнього доступу через Docker-мережу:
networks:
public:
private:
internal: trueСервіс можна під’єднати лише до потрібних мереж:
services:
proxy:
image: nginx:1.27-alpine
networks:
- public
app:
image: example/app:1.4.2
networks:
- public
- private
db:
image: postgres:16.4
networks:
- privateУ цьому прикладі:
proxy не має прямого доступу до бази;
db не під’єднана до публічної мережі;
app може приймати запити від proxy і звертатися до db.
Контейнери однієї мережі звертаються один до одного за іменем сервісу:
postgres://app_user:password@db:5432/app_dbІм’я db — це DNS-ім’я сервісу в мережі Compose. Не використовуйте IP-адреси контейнерів: вони можуть змінюватися після перезапуску.
Порт потрібно публікувати лише тоді, коли до сервісу має звертатися хост або зовнішня мережа:
services:
proxy:
ports:
- "80:8080"Для внутрішньої бази даних секція ports не потрібна:
services:
db:
image: postgres:16.4
expose:
- "5432"Більше того, expose часто також не обов’язковий: сервіс доступний іншим контейнерам тієї самої мережі за внутрішнім портом. Головне — не використовувати ports, якщо база не повинна бути доступною з хоста.
Контейнерний файловий шар зникає після видалення контейнера. Дані бази даних, завантажені файли та інші важливі дані потрібно зберігати в томах.
services:
db:
image: postgres:16.4
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:Ім’я тому краще оголошувати на верхньому рівні. Docker керуватиме життєвим циклом тому незалежно від контейнера.
Команда:
docker compose downвидаляє контейнери та мережі, але зазвичай залишає іменовані томи.
Команда:
docker compose down --volumesвидаляє також томи. Для production це може означати втрату даних бази, тому використовуйте її лише свідомо.
Перед небезпечними операціями перевіряйте список томів:
docker volume lsТом не є резервною копією. Для production все одно потрібне окреме резервне копіювання.
Паролі не варто записувати безпосередньо в environment у Compose-файлі:
# Невдалий варіант
environment:
POSTGRES_PASSWORD: super-secret-passwordКраще оголосити секрет:
secrets:
db_password:
file: ./secrets/db_password.txtі підключити його лише до потрібного сервісу:
services:
db:
image: postgres:16.4
secrets:
- db_passwordУ контейнері секрет буде доступний як файл:
/run/secrets/db_passwordОфіційний образ PostgreSQL підтримує змінну POSTGRES_PASSWORD_FILE, тому пароль можна передати без значення у Compose-файлі:
services:
db:
image: postgres:16.4
environment:
POSTGRES_USER: app_user
POSTGRES_DB: app_db
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_passwordФайл секрету повинен містити саме значення секрету, наприклад:
strong-production-passwordОбмежте доступ до файлу на хості:
mkdir -p secrets
printf '%s\n' 'strong-production-password' > secrets/db_password.txt
chmod 600 secrets/db_password.txtУ Docker Compose, який запускається через docker compose up, секрет із file: береться з локальної файлової системи та монтується в контейнер. Це зручно, але такий файл не є зашифрованим сховищем секретів.
Це відрізняється від Docker Swarm secrets, де секрети передаються через механізми Swarm.
Тому локальний Compose-файл із file: не повинен автоматично вважатися повноцінною системою керування секретами. Для production обмежуйте доступ до файлів і не додавайте каталог secrets до системи контролю версій.
depends_on задає порядок запуску контейнерів, але сам по собі не гарантує готовність сервісу.
Наприклад, контейнер PostgreSQL може бути вже запущений, але база ще приймати запити не готова. Для цього використовуйте healthcheck:
services:
db:
image: postgres:16.4
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"
]
interval: 10s
timeout: 5s
retries: 5
start_period: 20sПодвійний знак долара $$ потрібен, щоб змінна залишилася для інтерпретації всередині контейнера, а не була оброблена Compose під час читання файлу.
Залежний сервіс може чекати на стан healthy:
services:
app:
depends_on:
db:
condition: service_healthyЦе покращує порядок запуску, але застосунок все одно повинен коректно обробляти тимчасову недоступність бази. Healthcheck не замінює повторні підключення та обробку помилок у самому застосунку.
Для звичайного запуску через docker compose up використовують параметр restart:
services:
app:
restart: unless-stoppedОсновні значення:
no — не перезапускати контейнер автоматично;
on-failure — перезапускати після завершення з помилкою;
always — завжди перезапускати;
unless-stopped — перезапускати, якщо контейнер не був зупинений вручну.
Для довготривалих production-сервісів часто підходить:
restart: unless-stoppedНе плутайте restart із deploy.restart_policy:
deploy:
restart_policy:
condition: on-failuredeploy призначений насамперед для Docker Swarm. При запуску звичайною командою docker compose up частина параметрів deploy може не застосовуватися. Для локального Compose-сценарію використовуйте restart, а для Swarm — політики всередині deploy.
Перезапуск контейнера не виправляє:
помилки конфігурації;
проблеми з міграціями;
відсутні секрети;
несумісність версій;
помилки самого застосунку.
Він лише автоматично запускає контейнер знову.
Контейнери можуть конкурувати за CPU та пам’ять. Для сервісів із передбачуваним навантаженням можна задати обмеження:
services:
app:
deploy:
resources:
limits:
cpus: "1.0"
memory: 512MСумісність параметрів deploy.resources залежить від способу запуску та версії Compose. Перед застосуванням у production перевіряйте фактичну поведінку вашої версії Docker Engine і Compose.
Обмеження пам’яті особливо важливе для сервісів, які можуть неконтрольовано споживати RAM. Водночас занадто низьке значення призведе до аварійного завершення контейнера.
Нижче наведено самодостатній Compose-файл для невеликого production-подібного стеку:
proxy доступний через порт хоста;
app доступний лише через внутрішні мережі;
db ізольована у приватній мережі;
дані PostgreSQL зберігаються в іменованому томі;
пароль бази передається як секрет;
застосунок запускається після готовності бази;
для сервісів налаштовані healthcheck і restart policy.
services:
proxy:
image: nginx:1.27-alpine
restart: unless-stopped
ports:
- "80:80"
networks:
- public
depends_on:
app:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "nginx -t"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
app:
image: nginx:1.27-alpine
restart: unless-stopped
networks:
- public
- private
depends_on:
db:
condition: service_healthy
volumes:
- app_uploads:/usr/share/nginx/html/uploads
healthcheck:
test: ["CMD-SHELL", "nginx -t"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
db:
image: postgres:16.4
restart: unless-stopped
networks:
- private
environment:
POSTGRES_USER: app_user
POSTGRES_DB: app_db
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"
]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
networks:
public:
private:
internal: true
volumes:
app_uploads:
postgres_data:
secrets:
db_password:
file: ./secrets/db_password.txtУ реальному проєкті proxy зазвичай має власну конфігурацію маршрутизації до app, а app використовує образ вашого застосунку замість nginx. Структура мереж, томів, секретів і політик при цьому залишається такою самою.
Перед запуском перевірте, як Compose інтерпретує файл:
docker compose configЦя команда допомагає виявити:
помилки YAML;
неправильні відступи;
відсутні змінні;
некоректну структуру сервісів;
проблеми з мережами, томами та секретами.
Перевірте стан сервісів:
docker compose psПерегляньте журнали конкретного сервісу:
docker compose logs --follow appЗапустіть стек у фоновому режимі:
docker compose up -dПісля запуску перевірте:
docker compose ps
docker compose logs db
docker compose logs appЗупиніть сервіси без видалення даних:
docker compose downports:
- "5432:5432"Так база стає доступною з хоста, а за відповідних мережевих правил — потенційно і ззовні. Якщо доступ потрібен лише застосунку, приберіть ports і залиште базу у приватній мережі.
Якщо для PostgreSQL не вказати том, видалення контейнера може призвести до втрати даних.
Значення в environment видно через конфігурацію Compose та метадані контейнера. Використовуйте secrets або зовнішню систему керування секретами.
depends_onЗвичайний запис:
depends_on:
- dbне перевіряє готовність PostgreSQL. Додайте healthcheck і використайте condition: service_healthy.
latestОбраз може оновитися без зміни Compose-файлу. Фіксуйте версію або ще надійніше — конкретний digest образу.
Команда docker compose down --volumes може видалити production-дані. Перевіряйте команду перед виконанням.
Так послаблюється ізоляція. Підключайте сервіс лише до мереж, які йому справді потрібні.
Політика перезапуску не повідомляє про деградацію сервісу та не створює резервних копій. Потрібно окремо контролювати логи, healthcheck, доступність і стан даних.
Перед використанням Compose-конфігурації в production перевірте:
образи мають зафіксовані версії;
лише потрібні сервіси публікують порти;
база даних не доступна через публічну мережу;
важливі дані зберігаються в іменованих томах;
секрети не записані у відкритому вигляді;
для залежностей налаштовані healthcheck;
для довготривалих сервісів задано політику перезапуску;
Compose-файл проходить перевірку через docker compose config;
команда видалення томів не використовується без необхідності;
резервне копіювання томів налаштоване окремо.
Надійна production-конфігурація Docker Compose спирається на кілька принципів:
ізолюйте сервіси через окремі мережі;
не публікуйте внутрішні порти без потреби;
зберігайте постійні дані в іменованих томах;
передавайте паролі через secrets;
перевіряйте готовність залежностей healthcheck-ами;
налаштовуйте політики автоматичного перезапуску;
фіксуйте версії образів;
перевіряйте конфігурацію до запуску;
пам’ятайте, що томи, секрети та автоматичний restart не замінюють резервне копіювання й моніторинг.