Глиф Учебники

Урок 8. Docker Compose: несколько контейнеров одним файлом

Курс «Docker» · урок 8 из 10 · 5 минут чтения

Сайту на WordPress нужны два контейнера: сам WordPress и база данных. Каждому — порты, переменные, тома, общая сеть. Набирать всё это командами docker run неудобно и легко ошибиться. Docker Compose описывает сервисы в одном файле, а запускает и останавливает их одной командой.

Compose ставится вместе с Docker (пакет docker-compose-plugin, урок Установка Docker). Проверка:

Bash
docker compose version

Команда пишется через пробел: docker compose. Старая отдельная программа docker-compose через дефис больше не развивается — разница описана в справке docker compose и docker-compose.

Файл compose.yaml

Создайте папку проекта, например ~/blog, и в ней файл compose.yaml:

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-2026

Compose сам читает .env из папки проекта и подставляет значения вместо ${DB_PASSWORD}. Пароли не попадают в compose.yaml, и этот файл можно хранить в git, а .env — нет.

Что в файле

Файл написан на YAML: вложенность задаётся отступами из пробелов (табуляция не допускается), список — строками с - .

Обратите внимание: у db нет ports. WordPress обращается к базе по имени сервиса — WORDPRESS_DB_HOST: db — через общую сеть проекта, которую Compose создаёт сам. Снаружи база недоступна, и так и должно быть.

Запуск

В папке с compose.yaml:

Bash
docker compose up -d

Compose скачает образы, создаст сеть, тома и оба контейнера и запустит их в фоне (-d, как у docker run). Откройте http://localhost:8080 — появится установщик WordPress. Если вместо него сообщение об ошибке подключения к базе данных, подождите полминуты: при первом запуске MariaDB создаёт базу.

хост сеть проекта blog_default браузер localhost:8080 8080:80 wordpress blog-wordpress-1 порт 80 WORDPRESS_DB_HOST: db db blog-db-1 порт не опубликован blog_wp /var/www/html blog_db /var/lib/mysql
Команда docker compose up -d в папке ~/blog создаёт сеть проекта, два контейнера и два тома; наружу открыт только порт WordPress.

Пока установка 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 он тоже покажет.

Изменения в файле

Поменяли порт, переменную или образ — снова выполните:

Bash
docker compose up -d

Compose сравнит файл с работающими контейнерами и пересоздаст только те сервисы, у которых что-то изменилось. Данные в томах при этом остаются.

down и тома

docker compose down удаляет контейнеры и сеть проекта, но не тома: база и файлы WordPress сохранятся, и следующий up -d поднимет сайт с теми же данными.

docker compose down -v удаляет и тома проекта — базу данных и загруженные файлы, без возможности восстановления. Используйте его, только когда действительно хотите начать с чистого листа, и сначала сделайте копию данных.

контейнеры сеть тома docker compose up -d blog-wordpress-1 blog-db-1 blog_default blog_db blog_wp docker compose down blog-wordpress-1 blog-db-1 blog_default blog_db blog_wp данные целы docker compose down -v blog-wordpress-1 blog-db-1 blog_default blog_db blog_wp данные удалены навсегда
После docker compose down тома проекта остаются, а docker compose down -v удаляет и контейнеры, и сеть, и тома с данными.

Имена проекта

Имя проекта Compose берёт из имени папки: для ~/blog — blog. Из него строятся имена всего, что он создаёт:

Отсюда подводный камень: если переименовать папку, Compose будет считать её новым проектом и создаст новые пустые тома. Старые никуда не денутся, но новые контейнеры их не увидят.

папка имя проекта тома проекта ~/blog blog blog_db данные blog_wp данные папку переименовали ~/myblog myblog myblog_db пусто myblog_wp пусто тома blog_db и blog_wp остались на диске, но новый проект их не видит
Имя проекта Compose берёт из имени папки, поэтому после переименования папки проект получает новые пустые тома, а старые остаются в стороне.

Свой образ в Compose

Вместо готового образа сервис можно собирать из Dockerfile в папке проекта:

YAML
services:
  app:
    build: .
    ports:
      - "8000:8000"

docker compose up -d --build пересоберёт образ и пересоздаст контейнер — так обновляют свой код.

Коротко

Проверьте себя

1. Как сервис wordpress находит базу данных в этом проекте?
2. Что произойдёт с данными базы после docker compose down?
3. В compose.yaml поменяли порт сервиса. Как применить изменение?
4. Зачем пароли вынесены в файл .env?
5. Что гарантирует depends_on: [db] в простой записи?