Урок 8. Docker Compose: несколько контейнеров одним файлом
Сайту на WordPress нужны два контейнера: сам WordPress и база данных. Каждому — порты, переменные, тома, общая сеть. Набирать всё это командами docker run неудобно и легко ошибиться. Docker Compose описывает сервисы в одном файле, а запускает и останавливает их одной командой.
Compose ставится вместе с Docker (пакет docker-compose-plugin, урок Установка Docker). Проверка:
docker compose versionКоманда пишется через пробел: docker compose. Старая отдельная программа docker-compose через дефис больше не развивается — разница описана в справке docker compose и docker-compose.
Файл compose.yaml
Создайте папку проекта, например ~/blog, и в ней файл compose.yaml:
services:
db:
image: mariadb:12
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MARIADB_DATABASE: wordpress
MARIADB_USER: wordpress
MARIADB_PASSWORD: ${DB_PASSWORD}
volumes:
- db:/var/lib/mysql
wordpress:
image: wordpress:7
restart: unless-stopped
depends_on:
- db
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_DB_NAME: wordpress
volumes:
- wp:/var/www/html
volumes:
db:
wp:Рядом — файл .env с паролями (придумайте свои):
DB_ROOT_PASSWORD=Dlinny-Parol-Root-2026
DB_PASSWORD=Dlinny-Parol-Wp-2026Compose сам читает .env из папки проекта и подставляет значения вместо ${DB_PASSWORD}. Пароли не попадают в compose.yaml, и этот файл можно хранить в git, а .env — нет.
Что в файле
Файл написан на YAML: вложенность задаётся отступами из пробелов (табуляция не допускается), список — строками с - .
services— сервисы проекта, у каждого своё имя:dbиwordpress. Из каждого получится контейнер.image— образ, как вdocker run. Теги указаны явно: обновление базы на новую основную версию должно быть вашим решением, а не случайностью.restart— политика перезапуска, как--restart.environment— переменные окружения, как-e.volumesвнутри сервиса — тома и папки, как-v. Именованные тома перечисляются ещё и в разделеvolumesв конце файла.ports— публикация портов, как-p. Значения пишите в кавычках: YAML может по-своему понять запись вида22:22.depends_on— запускатьwordpressпослеdb.
Обратите внимание: у db нет ports. WordPress обращается к базе по имени сервиса — WORDPRESS_DB_HOST: db — через общую сеть проекта, которую Compose создаёт сам. Снаружи база недоступна, и так и должно быть.
Запуск
В папке с compose.yaml:
docker compose up -dCompose скачает образы, создаст сеть, тома и оба контейнера и запустит их в фоне (-d, как у docker run). Откройте http://localhost:8080 — появится установщик WordPress. Если вместо него сообщение об ошибке подключения к базе данных, подождите полминуты: при первом запуске MariaDB создаёт базу.
Пока установка WordPress не пройдена, её может пройти любой, кто откроет адрес, — и стать администратором сайта. На сервере, доступном из интернета, пройдите установку сразу после запуска или на время установки публикуйте порт только для самого сервера: "127.0.0.1:8080:80".
depends_on в простой записи только задаёт порядок запуска, но не ждёт, пока база будет готова принимать подключения. Для ожидания готовности в Compose есть проверки состояния (healthcheck) и запись condition: service_healthy — они описаны в документации Compose.
Основные команды
Все команды выполняются в папке проекта и относятся только к его сервисам:
| Задача | Команда |
|---|---|
| Создать и запустить всё в фоне | docker compose up -d |
| Состояние сервисов | docker compose ps |
| Логи всех сервисов, следить | docker compose logs -f |
| Логи одного сервиса, последние 50 строк | docker compose logs --tail 50 wordpress |
| Остановить и запустить | docker compose stop, docker compose start |
| Перезапустить сервис | docker compose restart wordpress |
| Зайти в контейнер сервиса | docker compose exec db bash |
| Остановить и удалить контейнеры и сеть | docker compose down |
| Проверить файл | docker compose config |
docker compose exec сразу даёт терминал — ключи -it, как у docker exec, не нужны. Например, консоль базы: docker compose exec db mariadb -u root -p.
docker compose config выводит итоговые настройки с подставленными переменными — удобно, чтобы найти опечатку в YAML. Учтите, что пароли из .env он тоже покажет.
Изменения в файле
Поменяли порт, переменную или образ — снова выполните:
docker compose up -dCompose сравнит файл с работающими контейнерами и пересоздаст только те сервисы, у которых что-то изменилось. Данные в томах при этом остаются.
down и тома
docker compose down удаляет контейнеры и сеть проекта, но не тома: база и файлы WordPress сохранятся, и следующий up -d поднимет сайт с теми же данными.
docker compose down -v удаляет и тома проекта — базу данных и загруженные файлы, без возможности восстановления. Используйте его, только когда действительно хотите начать с чистого листа, и сначала сделайте копию данных.
Имена проекта
Имя проекта Compose берёт из имени папки: для ~/blog — blog. Из него строятся имена всего, что он создаёт:
- контейнеры —
blog-db-1,blog-wordpress-1; - сеть —
blog_default; - тома —
blog_db,blog_wp(видны вdocker volume ls).
Отсюда подводный камень: если переименовать папку, Compose будет считать её новым проектом и создаст новые пустые тома. Старые никуда не денутся, но новые контейнеры их не увидят.
Свой образ в Compose
Вместо готового образа сервис можно собирать из Dockerfile в папке проекта:
services:
app:
build: .
ports:
- "8000:8000"docker compose up -d --build пересоберёт образ и пересоздаст контейнер — так обновляют свой код.
Коротко
- Сервисы описывают в
compose.yaml(старое имяdocker-compose.ymlтоже работает); команда —docker compose. image,ports,environment,volumes,restart— то же, что ключиdocker run.- Сервисы проекта связаны общей сетью; адрес сервиса — его имя.
- Пароли — в
.envрядом с файлом, не вcompose.yaml. up -dсоздаёт и обновляет,downудаляет контейнеры и сеть,down -v— ещё и данные.- Имя проекта — имя папки; от него зависят имена томов.