ServerAID
Найти гайд, команду, тег… ⌘ K
Серверный стек

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 compose v2.

Проверка:

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.

Похожие материалы

nginx reverse proxy на Ubuntu: рабочий конфиг с заголовками и SSL
Серверный стек

nginx reverse proxy на Ubuntu: рабочий конфиг с заголовками и SSL

Reverse proxy — фронт, который принимает запросы из интернета и передаёт их вашему Node.js, Python или Docker-контейнеру. Разбираем `proxy_pass`, правильные заголовки `X-Forwarded-For` и `Host`, балансировку через `upstream`, прокси к Docker, WebSocket-апгрейд и SSL termination через certbot. Конфиги под Ubuntu 24.04 LTS.

Редакция
find — что это и зачем
Глоссарий

find — что это и зачем

find — стандартная команда Linux для поиска файлов и каталогов по имени, типу, правам, размеру, дате и десяткам других критериев. С помощью `-exec` поверх найденного можно сразу выполнять команды. Универсальный инструмент админа для массовой работы с файловой системой.

Редакция
snap — что это и зачем
Глоссарий

snap — что это и зачем

snap — система упаковки и установки приложений от Canonical, разработанная как альтернатива apt. Каждый snap — самодостаточный пакет со своими зависимостями, изолированный от системы через AppArmor. Используется на Ubuntu для Firefox, Chromium, microk8s и многих desktop-приложений.

Редакция
LVM — что это и зачем
Глоссарий

LVM — что это и зачем

LVM — слой абстракции между физическими дисками и файловыми системами в Linux. Объединяет диски в пулы (Volume Groups), нарезает их на логические тома (Logical Volumes) и позволяет изменять размер на лету. Альтернатива классическому partitioning, которая делает работу с дисками гибкой.

Редакция