docker compose на Ubuntu 24.04: установка и рабочий compose.yaml
docker compose v2 — официальный плагин Docker для запуска многоконтейнерных приложений одним конфигом. Разбираем установку через официальный репозиторий Docker на Ubuntu 24.04 LTS, базовый `compose.yaml` с volumes и healthcheck, рестарт-политики, профили и запуск compose-стека как systemd-сервиса.
docker compose на Ubuntu: ставим plugin v2 и пишем рабочий compose.yaml
docker compose v2 — официальный плагин Docker для запуска многоконтейнерных приложений одним конфигом. Разбираем установку через официальный репозиторий Docker на Ubuntu 24.04 LTS, базовый compose.yaml с volumes и healthcheck, рестарт-политики, профили и запуск compose-стека как systemd-сервиса.
v1 умер, ставим v2
Docker Compose был переписан с Python (v1, команда docker-compose через дефис) на Go (v2, команда docker compose через пробел). v1 не получает обновлений с 2023 года. На Ubuntu 24.04 ставьте только v2 — это плагин, который кладёт бинарь в /usr/libexec/docker/cli-plugins/docker-compose, и Docker подхватывает его как подкоманду.
Старая команда docker-compose (через дефис) на v2 живёт как симлинк-обёртка для совместимости со скриптами, но в новых проектах используйте docker compose через пробел.
Главное правило: в репозиториях Ubuntu лежит устаревший docker.io. Ставьте Docker и Compose только из официального репозитория Docker — там свежие версии и вышеупомянутый plugin v2.
Ставим Docker и docker compose на Ubuntu 24.04
Полная последовательность для чистой Ubuntu 24.04:
# Удаляем старые версии, если они есть
sudo apt remove -y docker docker-engine docker.io containerd runc
# Зависимости для apt-репозитория с GPG-ключом
sudo apt update
sudo apt install -y ca-certificates curl gnupg
# Официальный GPG-ключ Docker
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Репозиторий Docker для Ubuntu 24.04 (noble)
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Установка Docker Engine + Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
Что мы поставили:
docker-ce— Docker Engine (демон).docker-ce-cli— клиентdocker.containerd.io— рантайм контейнеров.docker-buildx-plugin— плагин для сборки multi-arch образов.docker-compose-plugin— это и естьdocker composev2.
Проверка:
sudo docker version
sudo docker compose version
sudo docker run --rm hello-world
Если последняя команда вывела сообщение «Hello from Docker!» — установка успешна. На Ubuntu 22.04 (jammy), 24.04 (noble) и 24.10 — те же самые шаги, отличается только codename, который автоматически подставится из /etc/os-release.
Запускаем без sudo
По умолчанию Docker слушает Unix-сокет, доступ к которому имеет только root. Чтобы не писать sudo перед каждой командой, добавьте себя в группу docker:
sudo usermod -aG docker $USER
newgrp docker # применить группу к текущей сессии без логаута
docker ps # без sudo — должно сработать
Помните: членство в группе docker равносильно правам root. Любой, кто может запустить docker run -v /:/host, может прочитать и изменить любой файл на сервере. Не давайте эту группу пользователям, которым не доверяете на уровне sudo.
Пишем первый compose.yaml
Допустим, у нас веб-приложение на Node.js + PostgreSQL. Создаём папку проекта и compose.yaml:
# compose.yaml
services:
app:
image: node:22-alpine
working_dir: /app
command: ["node", "server.js"]
volumes:
- ./app:/app
environment:
DATABASE_URL: postgres://app:secret@db:5432/app
NODE_ENV: production
ports:
- "127.0.0.1:3000:3000"
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:17-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: app
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "app"]
interval: 5s
timeout: 3s
retries: 10
restart: unless-stopped
volumes:
db-data:
Что важно в этом конфиге:
compose.yamlбезversion:— в v2 версия не нужна, эта строка игнорируется. На v1 она была обязательной.services.app.image— берём готовый образ из Docker Hub. Для своего кода используйтеbuild: .с Dockerfile рядом.- Биндинг порта
127.0.0.1:3000:3000— внешний порт открывается только на localhost. Снаружи доступ — через nginx как reverse proxy. depends_onсcondition: service_healthy— app не стартует, пока у db не пройдёт healthcheck. Безconditionзависимость только по порядку запуска, но не по готовности.volumes: db-data— именованный volume, данные переживут пересоздание контейнера. Использовать./pgdata:/var/lib/postgresql/data(bind-mount) тоже можно, но именованные volume переносимее между машинами.restart: unless-stopped— Docker рестартит контейнер при падении и при ребуте машины. Альтернативы:no(по умолчанию),on-failure,always.
Управляем стеком
Запуск из той же папки, где лежит compose.yaml:
docker compose up -d # поднять в фоне
docker compose ps # что запущено
docker compose logs -f app # логи сервиса app, follow-режим
docker compose exec app sh # шелл внутрь контейнера
docker compose restart app # перезапуск одного сервиса
docker compose stop # остановить, не удаляя
docker compose down # остановить и удалить контейнеры (volume сохранится)
docker compose down -v # ... и удалить volumes (потеря данных!)
Имя проекта по умолчанию — название папки. Если хотите своё, передайте --project-name:
docker compose --project-name myapp up -d
Или положите в .env рядом с compose.yaml:
COMPOSE_PROJECT_NAME=myapp
Имя проекта используется как префикс для контейнеров (myapp-app-1, myapp-db-1) и сетей.
Выносим секреты в .env
Хардкодить пароль в compose.yaml плохо — он лежит в git. Используйте .env (он же добавляется в .gitignore):
# .env
POSTGRES_PASSWORD=really-secret
DATABASE_URL=postgres://app:really-secret@db:5432/app
# compose.yaml
services:
app:
environment:
DATABASE_URL: ${DATABASE_URL}
db:
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
Compose автоматически читает .env из текущей папки. Если хотите явно указать другой файл — docker compose --env-file production.env up -d.
Для совсем чувствительных секретов (TLS-ключи, токены) есть Docker Secrets — они монтируются как файлы в /run/secrets/<name>, не попадают в docker inspect:
services:
app:
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
В коде приложения читайте /run/secrets/db_password вместо переменной окружения.
Используем профили
Если у вас тестовый сервис, который не нужно запускать всегда (например, утилита миграций), используйте profiles:
services:
app:
image: myapp:latest
# без profiles — стартует по умолчанию
migrate:
image: myapp:latest
command: ["node", "migrate.js"]
profiles: ["tools"]
Запуск с профилем:
docker compose --profile tools run --rm migrate
Без --profile tools сервис migrate не стартует — это удобно для разовых задач, dev-инструментов, мониторинга.
Запускаем compose-стек как systemd-сервис
restart: unless-stopped поднимет контейнеры после ребута машины, если демон Docker стартовал и помнит про них. Но при свежей установке или после миграции на другой сервер это не работает — нужен явный systemd-сервис, который запустит docker compose up.
Создаём unit:
# /etc/systemd/system/myapp.service
[Unit]
Description=MyApp docker compose stack
Requires=docker.service
After=docker.service network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
Включаем:
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp
Type=oneshot + RemainAfterExit=yes — нужны потому, что docker compose up -d сразу завершается (контейнеры в фоне), а systemd должен считать сервис активным. Подробнее про unit-файлы — в гайде по systemctl и systemd unit.
Частые вопросы
Какой docker compose ставить на Ubuntu 24.04
Только v2 через docker-compose-plugin из официального репозитория Docker (download.docker.com). v1 (docker-compose через дефис, написан на Python) больше не поддерживается. В стандартных репозиториях Ubuntu лежит устаревший docker.io без plugin v2 — он не подходит.
В чём разница между docker-compose и docker compose
docker-compose (через дефис) — это старая v1, написанная на Python. docker compose (через пробел) — это новая v2, плагин Go-бинарь, который вызывается как подкоманда docker. Файлы конфигурации совместимы, но v1 заброшен. Используйте только v2.
Как установить docker compose на Ubuntu
Подключите официальный apt-репозиторий Docker, добавьте GPG-ключ и поставьте пакет docker-compose-plugin командой sudo apt install docker-compose-plugin. После этого команда docker compose version покажет установленную версию. Полная последовательность — в разделе «Ставим Docker и docker compose» выше.
Где должен лежать compose.yaml
В корне проекта. Compose ищет файлы по порядку: compose.yaml, compose.yml, docker-compose.yaml, docker-compose.yml. Запускать команды нужно из папки, где лежит файл, либо передавать путь через -f: docker compose -f /opt/myapp/compose.yaml up -d.
Чем именованные volumes лучше bind-mount
Именованные volumes (db-data:/var/lib/postgresql/data) живут в /var/lib/docker/volumes/, управляются Docker, переносимы между машинами через docker volume export/import. Bind-mount (./pgdata:/var/lib/postgresql/data) привязан к конкретному пути на хосте — удобно для разработки, неудобно для миграции. Для прод-баз обычно берут именованные volumes; для конфигов и кода — bind-mount.
Как docker compose down не потерять данные
docker compose down без флагов удаляет только контейнеры и сети — volumes сохраняются. Чтобы случайно не удалить данные, никогда не вызывайте docker compose down -v на проде. Если нужно пересоздать контейнер с новой конфигурацией: docker compose up -d --force-recreate.
Как обновить образы в docker compose
docker compose pull — скачать свежие версии образов, указанных в compose.yaml. Затем docker compose up -d — пересоздаст контейнеры на новых образах. Один шорткат: docker compose up -d --pull always. Старые образы остаются на диске; чистка — docker image prune -a.
Что запомнить
- На Ubuntu ставьте Docker только из официального репозитория
download.docker.com— стандартныйdocker.ioустаревший и без compose v2. - Команда v2 —
docker compose(через пробел), неdocker-compose. Файлы конфигурации совместимы, но используйте новую команду. - В
compose.yamlуже не нуженversion:— это v1-наследие. - Биндите порты на
127.0.0.1:port:port, наружу выставляйте через nginx-фронт. Подробно — гайд по nginx reverse proxy. - Используйте
depends_onсcondition: service_healthy, а не голыйdepends_on— он только про порядок старта, не про готовность. - Секреты — в
.env-файле (gitignored) или в Docker Secrets. Никогда не хардкодьте пароль вcompose.yaml. - Для автозапуска после ребута — systemd-сервис
Type=oneshot+ExecStart=/usr/bin/docker compose up -d. Подробно — systemd unit и systemctl enable.