Пошук уроків, статей та іншого контенту
Навчитеся задавати образи, команди, порти, змінні та інші параметри контейнерів у секції services.
Сервіс — це опис контейнера, який потрібно запустити в складі застосунку. Усі сервіси описують у файлі compose.yaml або docker-compose.yml.
Мінімальна структура файлу:
services:
назва_сервісу:
image: назва_образуНаприклад:
services:
web:
image: nginx:alpineТут:
services — секція з усіма сервісами;
web — ім’я сервісу;
image — образ, з якого буде створено контейнер;
nginx:alpine — конкретний Docker-образ.
Ім’я сервісу не обов’язково має збігатися з назвою образу. Його обирають для зручності.
Параметр image визначає, який образ використовуватиме контейнер:
services:
web:
image: nginx:1.27-alpine
cache:
image: redis:7-alpineЯкщо образу немає локально, Docker Compose завантажить його з реєстру під час запуску.
Бажано вказувати конкретну версію або тег образу:
image: redis:7-alpineЗамість нечіткої версії:
image: redis:latestТег latest може вказувати на різний вміст у різний момент часу. Через це одна й та сама конфігурація може запускати різні версії образу.
Параметр command змінює команду, яку контейнер виконує після запуску.
services:
web:
image: node:22-alpine
command: ["node", "server.js"]У цьому прикладі Docker Compose запускає всередині контейнера команду:
node server.jsКоманду можна записати рядком:
command: node server.jsАле форма зі списком однозначніше описує окремі аргументи команди:
command: ["node", "server.js"]command замінює стандартну команду, визначену в образі. Тому вона має запускати процес, який повинен працювати всередині контейнера.
Контейнер має власну мережу. Щоб звертатися до його сервісу з комп’ютера, потрібно опублікувати порт через параметр ports.
services:
web:
image: nginx:alpine
ports:
- "8080:80"Формат запису:
ПОРТ_КОМП’ЮТЕРА:ПОРТ_КОНТЕЙНЕРАУ прикладі:
8080 — порт на комп’ютері;
80 — порт усередині контейнера;
запит до http://localhost:8080 буде передано на порт 80 контейнера.
Порти комп’ютера та контейнера не повинні збігатися:
ports:
- "3000:80"Тоді сервіс буде доступний на порту 3000 комп’ютера, хоча всередині контейнера використовує порт 80.
Змінні середовища передають налаштування процесу всередині контейнера. Їх задають через environment.
services:
web:
image: node:22-alpine
environment:
NODE_ENV: development
PORT: "3000"У контейнері будуть доступні змінні:
NODE_ENV=development
PORT=3000Ті самі змінні можна записати списком:
services:
web:
image: node:22-alpine
environment:
- NODE_ENV=development
- PORT=3000Словниковий формат зазвичай легше читати, особливо коли змінних багато.
Значення, які мають вигляд числа або логічного значення, краще брати в лапки:
environment:
PORT: "3000"
DEBUG: "true"Так YAML не намагатиметься трактувати їх як число або логічне значення.
Параметр working_dir визначає поточну директорію процесу в контейнері:
services:
web:
image: node:22-alpine
working_dir: /app
command: ["node", "server.js"]Команда node server.js у такому разі шукатиме файл за шляхом:
/app/server.jsПараметр volumes дає змогу підключити директорію з комп’ютера до контейнера:
services:
web:
image: node:22-alpine
working_dir: /app
volumes:
- ./app:/appФормат:
ШЛЯХ_НА_КОМП’ЮТЕРІ:ШЛЯХ_У_КОНТЕЙНЕРІУ прикладі:
./app — директорія поруч із файлом compose.yaml;
/app — директорія всередині контейнера.
Зміни у файлах ./app одразу будуть видимі в контейнері.
Якщо контейнеру потрібен лише перегляд файлів без можливості їх змінювати, додають режим ro:
volumes:
- ./app:/app:roro означає read-only, тобто «лише для читання».
Створимо простий HTTP-сервер на Node.js.
Структура проєкту:
my-compose-project/
├── compose.yaml
└── app/
└── server.jsФайл app/server.js:
const http = require("node:http");
const port = Number(process.env.PORT || 3000);
const message = process.env.APP_MESSAGE || "Привіт із контейнера";
const server = http.createServer((request, response) => {
response.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
response.end(`${message}\n`);
});
server.listen(port, "0.0.0.0", () => {
console.log(`Сервер слухає порт ${port}`);
});Файл compose.yaml:
services:
web:
image: node:22-alpine
working_dir: /app
command: ["node", "server.js"]
ports:
- "8080:3000"
environment:
PORT: "3000"
APP_MESSAGE: "Сервер працює в Docker Compose"
volumes:
- ./app:/app:ro
restart: unless-stoppedУ цьому описі:
web — ім’я сервісу;
node:22-alpine — образ Node.js;
working_dir — робоча директорія /app;
command — команда запуску сервера;
ports — порт 8080 комп’ютера з’єднано з портом 3000 контейнера;
environment — змінні для програми;
volumes — локальна директорія ./app підключена до /app;
ro — контейнер не може змінювати файли програми;
restart: unless-stopped — контейнер автоматично перезапускатиметься після збою або перезапуску Docker, якщо його не зупинили вручну.
Запустіть сервіс із директорії, де розташований compose.yaml:
docker compose up -dПеревірити запущені контейнери:
docker compose psПісля запуску відкрийте в браузері:
http://localhost:8080Для перегляду повідомлень програми використайте:
docker compose logs webЗупинити та видалити контейнер:
docker compose downОскільки директорія app змонтована з комп’ютера, її файли не видаляються під час виконання docker compose down.
.envЗначення можна винести в окремий файл .env, розташований поруч із compose.yaml.
Файл .env:
WEB_PORT=8080
APP_MESSAGE=Повідомлення з файлу envУ compose.yaml можна використати ці значення:
services:
web:
image: node:22-alpine
working_dir: /app
command: ["node", "server.js"]
ports:
- "${WEB_PORT}:3000"
environment:
PORT: "3000"
APP_MESSAGE: "${APP_MESSAGE}"
volumes:
- ./app:/app:roЗапис ${WEB_PORT} означає: «підставити значення змінної WEB_PORT».
Для значення за замовчуванням використовують такий синтаксис:
ports:
- "${WEB_PORT:-8080}:3000"Якщо WEB_PORT не задана, буде використано порт 8080.
Файл .env не є частиною опису сервісу. Це лише джерело значень, які Compose підставляє в конфігурацію.
У файлі Compose можна описати кілька сервісів:
services:
web:
image: nginx:alpine
ports:
- "8080:80"
cache:
image: redis:7-alpineКожен ключ під services описує окремий контейнер. У цьому прикладі Compose створить сервіси web і cache.
Для запуску всіх сервісів достатньо виконати:
docker compose up -dДля запуску лише одного сервісу вкажіть його ім’я:
docker compose up -d cacheСервіси одного Compose-проєкту знаходять один одного за іменем сервісу. Наприклад, якщо є сервіс:
services:
database:
image: postgres:16-alpineІнший контейнер може звертатися до нього за адресою database, а не localhost.
localhost усередині контейнера означає саме цей контейнер. Тому для підключення до іншого сервісу використовують його ім’я:
database:5432Порт, який використовується між контейнерами, не потрібно додавати в ports. ports потрібен для доступу з комп’ютера або зовнішньої мережі.
Неправильно:
ports:
- "80:8080"якщо програма всередині контейнера слухає порт 80, а не 8080.
Першим указують порт комп’ютера, другим — порт контейнера:
ports:
- "8080:80"localhostЯкщо сервер усередині контейнера слухає лише 127.0.0.1, він може бути недоступним через опублікований порт.
Для доступу ззовні контейнера сервер має слухати адресу:
0.0.0.0У прикладі Node.js це зроблено тут:
server.listen(port, "0.0.0.0");volumesШлях ./app обчислюється відносно директорії, у якій розташований compose.yaml.
Якщо директорія має іншу назву або знаходиться в іншому місці, контейнер не побачить очікувані файли.
Якщо command замінює стандартну команду образу, але задана команда неправильна, контейнер завершить роботу.
Перевірити причину можна через журнали:
docker compose logs weblocalhost для іншого сервісуУсередині контейнера localhost посилається на поточний контейнер. Для звернення до іншого сервісу використовуйте його ім’я з секції services.
Якщо порт 8080 уже використовується іншою програмою, Compose не зможе опублікувати його. Змініть порт комп’ютера:
ports:
- "8081:3000"Порт усередині контейнера при цьому залишається 3000.
Сервіси описують у секції services.
Кожен сервіс має власне ім’я та налаштування контейнера.
image визначає Docker-образ.
command задає команду запуску.
ports публікує порт контейнера на комп’ютері.
environment передає змінні середовища.
working_dir задає робочу директорію.
volumes підключає локальні файли або директорії.
restart визначає поведінку контейнера після завершення або перезапуску Docker.
Для доступу одного сервісу до іншого використовують ім’я сервісу, а не localhost.
Запуск, перегляд і зупинка сервісів виконуються командами docker compose up, docker compose ps, docker compose logs і docker compose down.