Docker Compose — готовые стеки
Для кого эта статья
Если вы гуглите docker compose example, docker-compose.yml postgres, как поднять nginx в docker, wordpress docker compose или локальная база данных docker — здесь готовые файлы с разбором каждой строки, как в популярных галереях кода для учёбы. Можно скопировать каталог, выполнить docker compose up -d и сразу увидеть результат в браузере или терминале.
Статья рассчитана на:
- школьников и студентов на лабораторных по информатике, DevOps и веб-разработке;
- начинающих, которым нужен шаблон «прямо сейчас», но хочется понять, что означает каждая строка YAML;
- тех, кто поднимает локальное окружение «как у команды» без десятка ручных команд
docker run.
Docker Compose — один текстовый файл (compose.yaml), в котором описано несколько контейнеров сразу: веб-сервер, база, кэш, мониторинг. Одна команда docker compose up поднимает весь набор связанных сервисов на вашем ПК.
Полный разбор Compose, команд CLI и типичных ошибок — Docker Compose. Основы Docker и образов — Docker. Сборка своего образа — Dockerfile и галерея из 10 типовых Dockerfile. Пошаговый стек Prometheus + Grafana — практикум.
Симулятор выше показывает, как depends_on с healthcheck откладывает старт приложения, пока PostgreSQL не станет healthy. Тот же приём — в стеках №3–5, 4, 14 ниже.
Три слова — контейнер, образ, compose
| Термин | Простыми словами | Аналогия |
|---|---|---|
| Образ (image) | «Чертёж» программы с ОС и файлами | Установочный диск |
| Контейнер | Запущенный экземпляр образа | Открытая программа |
| Compose-файл | Список контейнеров и связей между ними | Сценарий «поднять сайт + БД + кэш» |
| Сервис | Имя блока в YAML (web, db) | Имя участника в сценарии |
| Volume (том) | Место на диске, где данные живут вне контейнера | Флешка с файлами БД |
| Port mapping | 8080:80 — с вашего ПК на порт внутри контейнера | Дверь в комнату |
Ваш браузер Docker-сеть проекта
localhost:8080 ──ports──► [ web :80 ]
│
│ DB_HOST=db
▼
[ db :5432 ] ◄── volume pg_data (данные на диске)
Запомните: браузер на Windows/macOS/Linux ходит на localhost + левый порт из ports. Контейнер api к PostgreSQL подключается по имени db — это DNS внутри Docker, не IP и не localhost.
Как читать compose-файл
| Ключ | Смысл простыми словами |
|---|---|
services | Список контейнеров проекта (web, db, cache…) |
image | Готовый образ из registry (nginx:1.27-alpine) |
build | Собрать образ из Dockerfile в указанной папке |
ports | Проброс хост:контейнер — браузер ходит на localhost |
environment | Переменные внутри контейнера |
env_file | Подтянуть пары ключ=значение из .env |
volumes | Том или bind-mount — данные переживают пересоздание контейнера |
depends_on | Порядок старта (без гарантии «БД уже принимает SQL») |
healthcheck | Compose ждёт успешной проверки перед service_healthy |
networks | Отдельные виртуальные сети между сервисами |
profiles | Сервис поднимается только с --profile имя |
restart | Политика перезапуска после сбоя или reboot хоста |
Два адреса — запомните в первую очередь:
| Откуда | Куда подключаться |
|---|---|
| Браузер на вашем ПК | http://localhost:8080 — левое число в ports |
| Контейнер к контейнеру | имя сервиса (db, redis), не localhost |
Пример: в compose-сервисе api строка DB_HOST=db верна; DB_HOST=localhost укажет на loopback внутри контейнера api, где PostgreSQL не слушает.
Как работать с примерами
- Создайте пустую папку, например
my-stack/. - Сохраните блок YAML в
compose.yaml(илиdocker-compose.yml— оба имени Compose понимает). - При необходимости добавьте
.envи вспомогательные файлы из раздела. - Откройте терминал в этой папке (PowerShell, cmd, bash, WSL — без разницы).
- Выполните команды по порядку:
docker compose config
docker compose up -d
docker compose ps
Разбор команд:
| Команда | Что делает |
|---|---|
docker compose config | Читает YAML, подставляет .env, печатает итог без запуска контейнеров — ловит опечатки до up |
docker compose up -d | Скачивает образы (если нет), создаёт сеть и тома, запускает все сервисы; -d = detached, терминал свободен |
docker compose ps | Таблица: имя, статус (Up, healthy), какие порты проброшены на хост |
- Откройте URL из раздела «Проверка» или смотрите логи:
docker compose logs -f web(имя сервиса из YAML). - Остановка без удаления данных БД:
docker compose down. - Полный сброс данных в named volumes:
docker compose down -v— все таблицы Postgres «как новые».
Перед docker compose up убедитесь, что Docker Desktop запущен (иконка в трее «Running»). Ошибка Cannot connect to the Docker daemon означает, что демон не работает — не ошибка в YAML.
Значения вроде secret и admin подходят только для локального dev. В общий Git пароли не коммитьте — используйте .env (в .gitignore) или Docker secrets.
Обязательный каркас проекта
Любой стек ниже можно собрать на этом фундаменте:
services:
example:
image: alpine:3.20
command: ["sleep", "infinity"]
# volumes:
# data:
| Фрагмент | Смысл |
|---|---|
services: | Корневая секция — без неё файл невалиден |
example: | Имя сервиса; по нему же резолвится DNS внутри сети |
image: | Образ из Docker Hub или локального кэша |
command: | Переопределяет CMD образа (здесь контейнер «висит» для отладки) |
Что делает файл целиком:
- Объявляет один сервис
exampleна базе минимального образа Alpine Linux. - Команда
sleep infinityне даёт контейнеру завершиться — удобно дляdocker compose exec example sh. - Закомментированная секция
volumes:— заготовка; раскомментируйте, когда понадобится постоянное хранилище.
Проверка синтаксиса до запуска:
docker compose config
Стартовые стеки
Пять минимальных конфигураций — с одного сервиса до классической связки приложение + БД.
1. Один nginx — «Hello»
Задача: проверить, что Docker и Compose работают. Частый запрос в поиске: docker compose nginx example, nginx docker compose yml.
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
Разбор по строкам:
| Строка | Смысл |
|---|---|
services: | Начало списка контейнеров проекта |
web: | Имя сервиса; по нему же обращаются другие контейнеры (http://web) |
image: nginx:1.27-alpine | Образ с Docker Hub: веб-сервер nginx на лёгкой Alpine Linux; тег 1.27-alpine фиксирует версию |
ports: | Секция проброса портов на ваш ПК |
- "8080:80" | Формат порт_хоста:порт_контейнера. Браузер → localhost:8080 → nginx слушает :80 внутри |
Что происходит при docker compose up -d:
- Compose создаёт виртуальную сеть проекта (имя = имя папки).
- Если образа
nginx:1.27-alpineнет — скачивает (pull). - Создаёт контейнер
…-web-1, подключает к сети, пробрасывает порт 8080. - Nginx стартует и отдаёт дефолтную страницу «Welcome to nginx».
Проверка: http://localhost:8080 — страница «Welcome to nginx».
Команды и разбор:
docker compose up -d
docker compose logs web
docker compose down
| Команда | Смысл |
|---|---|
up -d | Поднять стек в фоне |
logs web | Показать stdout/stderr сервиса web (ошибки конфига nginx видны здесь) |
down | Остановить и удалить контейнер и сеть; образ nginx на диске остаётся |
Если порт 8080 занят — замените на "8888:80" и откройте http://localhost:8888.
2. Статика с диска
Задача: отдавать свой index.html без пересборки образа. Поиск: docker nginx static files, монтировать папку в контейнер.
Структура каталога:
static-site/
compose.yaml
html/
index.html
Пример html/index.html:
<!DOCTYPE html>
<html lang="ru">
<head><meta charset="UTF-8"><title>Мой сайт</title></head>
<body><h1>Привет из Docker!</h1></body>
</html>
compose.yaml:
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
Разбор по строкам:
| Строка | Смысл |
|---|---|
volumes: | Подключение папок или томов к файловой системе контейнера |
./html:/usr/share/nginx/html:ro | Bind mount: папка html рядом с YAML → стандартная папка статики nginx; :ro = read-only (контейнер не перезапишет ваши файлы) |
Что делает bind mount:
- Файлы лежат на вашем диске в
static-site/html/. - Nginx внутри контейнера читает их как
/usr/share/nginx/html/index.html. - Правка
index.htmlв блокноте → F5 в браузере — безdocker compose upзаново.
Проверка: измените текст в html/index.html — обновите страницу в браузере.
3. Только PostgreSQL для разработки
Задача: локальная БД на порту 5432 с сохранением данных в томе. Поиск: docker compose postgres, postgresql docker-compose.yml example, поднять postgres локально docker.
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: appdb
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
interval: 5s
timeout: 3s
retries: 5
volumes:
pg_data:
Разбор по строкам:
| Строка | Смысл |
|---|---|
db: | Имя сервиса; другие контейнеры подключаются к хосту db, порт 5432 |
postgres:16-alpine | Официальный образ PostgreSQL 16 |
POSTGRES_USER | Имя суперпользователя БД (создаётся при первом старте тома) |
POSTGRES_PASSWORD | Пароль; без него образ не стартует |
POSTGRES_DB | База, которую Postgres создаст при инициализации |
"5432:5432" | DBeaver, pgAdmin, Python на хосте подключаются к localhost:5432 |
pg_data:/var/lib/postgresql/data | Данные таблиц хранятся в named volume, не внутри слоя контейнера |
healthcheck | Периодически запускает pg_isready; статус healthy виден в docker compose ps |
interval: 5s | Проверка каждые 5 секунд |
retries: 5 | После 5 неудач — сервис unhealthy |
volumes: (в корне) | Объявление имени тома pg_data; Docker создаст его автоматически |
Строка подключения с вашего ПК (не из контейнера):
postgresql://app:secret@localhost:5432/appdb
Что происходит при первом up:
- Создаётся пустой том
pg_data. - Postgres инициализирует кластер, создаёт пользователя
appи БДappdb. - При повторном
upпослеdownданные на месте — init не повторяется.
Проверка:
docker compose exec db psql -U app -d appdb -c "SELECT 1;"
| Часть команды | Смысл |
|---|---|
exec db | Выполнить команду внутри работающего контейнера сервиса db |
psql -U app -d appdb | Клиент SQL: пользователь app, база appdb |
-c "SELECT 1;" | Один запрос без интерактивной оболочки |
Ожидаемый вывод — таблица с числом 1.
Подробнее про Postgres в контейнере — PostgreSQL в Docker.
4. Приложение + PostgreSQL
Задача: API или бэкенд подключается к БД по имени сервиса db. Поиск: docker compose node postgres, spring boot docker compose postgres, backend + database compose.
services:
api:
image: node:20-alpine
working_dir: /app
command: ["node", "server.js"]
volumes:
- ./app:/app
ports:
- "3000:3000"
environment:
DB_HOST: db
DB_PORT: "5432"
DB_USER: app
DB_PASSWORD: secret
DB_NAME: appdb
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: appdb
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
interval: 5s
retries: 5
volumes:
pg_data:
Разбор сервиса api:
| Строка | Смысл |
|---|---|
node:20-alpine | Образ Node.js 20 — для учебного примера без своего Dockerfile |
working_dir: /app | Текущая папка внутри контейнера |
command: ["node", "server.js"] | Что запустить вместо дефолтного CMD образа |
./app:/app | Ваш код на диске монтируется в контейнер — правки без rebuild |
DB_HOST: db | Ключевой момент: хост БД = имя сервиса db, не localhost |
depends_on + service_healthy | Контейнер api создаётся только после healthy у db |
Почему localhost ломает подключение:
| Где выполняется код | Куда указывать DB_HOST |
|---|---|
Node/Python внутри контейнера api | db |
| DBeaver на вашем ПК | localhost |
psql через docker compose exec db | сокет внутри контейнера db |
Минимальный app/server.js для проверки (опционально):
const http = require('http');
const { Client } = require('pg');
const client = new Client({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});
client.connect()
.then(() => {
http.createServer((_req, res) => {
res.end('API + Postgres OK');
}).listen(3000);
})
.catch((err) => {
console.error('DB error:', err.message);
process.exit(1);
});
В папке app/ выполните npm init -y && npm install pg на хосте (или добавьте package.json в репозиторий).
Проверка: http://localhost:3000 — текст «API + Postgres OK»; в логах docker compose logs api нет connection refused.
5. Redis рядом с PostgreSQL
Задача: кэш или сессии в Redis, постоянные данные — в Postgres. Поиск: docker compose redis postgres, full stack docker compose.
services:
api:
build: .
ports:
- "3000:3000"
environment:
DB_HOST: db
REDIS_URL: redis://redis:6379/0
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: secret
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes:
pg_data:
redis_data:
Разбор ключевых строк:
| Строка | Смысл |
|---|---|
build: . | Compose соберёт образ из Dockerfile в текущей папке (ваше приложение) |
REDIS_URL: redis://redis:6379/0 | URL к Redis: хост redis — имя сервиса; /0 — номер логической БД Redis |
service_healthy для db | Ждём готовности SQL |
service_started для redis | Достаточно запущенного процесса; Redis поднимается быстро |
redis_data:/data | Персистентность Redis (RDB/AOF в томе) — опционально для dev, полезно для учебных данных |
Типичное разделение ролей:
| Сервис | Что хранит |
|---|---|
| PostgreSQL | Пользователи, заказы, всё, что нельзя потерять |
| Redis | Сессии, кэш страниц, счётчики, очереди на время |
Проверка Redis из контейнера api:
docker compose exec redis redis-cli ping
Ответ PONG — сервер жив.
Примеры стеков
Готовые конфигурации под типовые задачи — от CMS до мониторинга и S3-совместимого хранилища.
6. WordPress + MariaDB
Задача: блог или учебный сайт за пару минут. Поиск: wordpress docker compose, wordpress mysql docker-compose.yml.
services:
wordpress:
image: wordpress:6.7-apache
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wp
WORDPRESS_DB_PASSWORD: wppass
WORDPRESS_DB_NAME: wpdb
volumes:
- wp_uploads:/var/www/html/wp-content/uploads
depends_on:
db:
condition: service_healthy
db:
image: mariadb:11
environment:
MARIADB_USER: wp
MARIADB_PASSWORD: wppass
MARIADB_DATABASE: wpdb
MARIADB_ROOT_PASSWORD: rootpass
volumes:
- mariadb_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
volumes:
wp_uploads:
mariadb_data:
Разбор по строкам:
| Строка | Смысл |
|---|---|
wordpress:6.7-apache | CMS + Apache PHP в одном образе |
WORDPRESS_DB_HOST: db | WordPress подключается к MariaDB по имени сервиса |
WORDPRESS_DB_* | Учётные данные должны совпадать с MARIADB_* у db |
wp_uploads | Загруженные картинки переживают пересоздание контейнера wordpress |
mariadb:11 | Форк MySQL, совместим с WordPress |
MARIADB_ROOT_PASSWORD | Пароль root (для админских задач, не для WP) |
healthcheck.sh | Встроенный скрипт образа MariaDB — ждёт инициализацию InnoDB |
Что происходит при первом открытии сайта:
- WordPress подключается к MariaDB и создаёт таблицы.
- Мастер установки просит язык, заголовок сайта, логин admin.
- Данные таблиц — в томе
mariadb_data; медиафайлы — вwp_uploads.
Проверка: http://localhost:8080 — мастер установки WordPress.
7. MongoDB + веб-админка
Задача: документная БД и UI для просмотра коллекций. Поиск: mongodb docker compose, mongo-express docker.
services:
mongo:
image: mongo:7
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: secret
volumes:
- mongo_data:/data/db
ports:
- "27017:27017"
mongo-express:
image: mongo-express:1.0.2-20
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: secret
ME_CONFIG_MONGODB_URL: mongodb://root:secret@mongo:27017/
depends_on:
- mongo
volumes:
mongo_data:
Разбор по строкам:
| Строка | Смысл |
|---|---|
MONGO_INITDB_ROOT_* | Создаёт root-пользователя при первом старте тома |
mongo_data:/data/db | Файлы БД на named volume |
"27017:27017" | Драйвер MongoDB на хосте (Compass, Node, Python) → mongodb://root:secret@localhost:27017 |
mongo-express | Веб-UI для просмотра коллекций (только dev, не для prod) |
ME_CONFIG_MONGODB_URL | URL из контейнера mongo-express: хост mongo, не localhost |
depends_on: - mongo | Порядок старта без healthcheck |
Проверка:
| URL / строка | Назначение |
|---|---|
http://localhost:8081 | mongo-express в браузере |
mongodb://root:secret@localhost:27017 | Подключение с вашего ПК |
mongodb://root:secret@mongo:27017 | Подключение из другого сервиса в том же compose |
8. Prometheus + Grafana (минимум)
Задача: локальный мониторинг метрик. Поиск: prometheus grafana docker compose. Полный стенд с provisioning — в практикуме Prometheus.
Структура каталога:
monitoring/
compose.yaml
prometheus/
prometheus.yml
compose.yaml:
services:
prometheus:
image: prom/prometheus:v2.53.0
ports:
- "9090:9090"
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
grafana:
image: grafana/grafana:12.0.0
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: admin
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- prometheus
volumes:
prometheus_data:
grafana_data:
Разбор по строкам:
| Строка | Смысл |
|---|---|
./prometheus/prometheus.yml:...:ro | Конфиг scrape с диска; :ro — контейнер не перезапишет файл |
prometheus_data:/prometheus | История метрик (TSDB) сохраняется между перезапусками |
GF_SECURITY_ADMIN_* | Логин и пароль первого входа в Grafana |
grafana_data | Дашборды и настройки Grafana |
depends_on: prometheus | Grafana стартует после Prometheus (без healthcheck) |
Минимальный prometheus/prometheus.yml:
global:
scrape_interval: 15s
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]
Разбор prometheus.yml:
| Строка | Смысл |
|---|---|
scrape_interval: 15s | Как часто опрашивать targets |
job_name: prometheus | Имя job в UI |
targets: ["localhost:9090"] | Внутри контейнера prometheus он сам слушает 9090 — здесь localhost корректен |
| URL | Назначение |
|---|---|
http://localhost:9090 | Prometheus UI |
http://localhost:3000 | Grafana (логин admin / admin) |
Настройка datasource в Grafana: URL http://prometheus:9090 — Grafana работает в контейнере и видит Prometheus по имени сервиса. localhost:9090 в datasource Grafana не сработает — это был бы loopback самой Grafana.
Готовые PromQL-запросы с разбором — Prometheus + Grafana — запросы: up, rate, CPU, HTTP, P99, алерты.
9. MailHog — перехват писем в dev
Задача: приложение шлёт SMTP на MailHog; письма видны в браузере, реальная почта не уходит. Поиск: mailhog docker compose, тестовая почта docker.
services:
mailhog:
image: mailhog/mailhog:v1.0.1
ports:
- "1025:1025"
- "8025:8025"
Разбор по строкам:
| Строка | Смысл |
|---|---|
mailhog/mailhog | Лёгкий SMTP-сервер + веб-инbox для разработки |
"1025:1025" | SMTP — ваше приложение на хосте шлёт на localhost:1025 |
"8025:8025" | HTTP UI — список писем в браузере |
Переменные для приложения на хосте:
| Переменная | Значение |
|---|---|
SMTP_HOST | localhost |
SMTP_PORT | 1025 |
| TLS / auth | не нужны — MailHog принимает всё |
Проверка: http://localhost:8025 — пустой inbox; отправьте тестовое письмо из приложения — оно появится в UI.
10. MinIO — S3-совместимое хранилище
Задача: локальный объектный storage для загрузки файлов. Поиск: minio docker compose, s3 local docker.
services:
minio:
image: minio/minio:RELEASE.2024-12-18T13-15-44Z
command: server /data --console-address ":9001"
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
volumes:
- minio_data:/data
volumes:
minio_data:
Разбор по строкам:
| Строка | Смысл |
|---|---|
command: server /data ... | Запуск сервера MinIO; данные в /data (том minio_data) |
--console-address ":9001" | Админ-консоль на порту 9001 внутри контейнера |
9000 | S3 API — SDK и aws-cli ходят сюда |
9001 | Веб-консоль — buckets, ключи доступа |
MINIO_ROOT_* | Root-логин для консоли и API |
| URL | Назначение |
|---|---|
http://localhost:9000 | S3 API endpoint |
http://localhost:9001 | Консоль MinIO (логин minioadmin / minioadmin) |
11. Nginx как reverse proxy
Задача: один входной порт, два бэкенда по пути /api и /. Поиск: nginx reverse proxy docker compose, docker compose несколько сервисов один порт.
Структура:
proxy-demo/
compose.yaml
nginx.conf
frontend/
index.html
compose.yaml:
services:
proxy:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- frontend
- api
frontend:
image: nginx:1.27-alpine
volumes:
- ./frontend:/usr/share/nginx/html:ro
api:
image: hashicorp/http-echo:1.0
command: ["-text=API OK"]
nginx.conf (фрагмент):
events {}
http {
upstream front { server frontend:80; }
upstream back { server api:5678; }
server {
listen 80;
location /api/ {
proxy_pass http://back/;
}
location / {
proxy_pass http://front;
}
}
}
Разбор compose:
| Сервис | Роль |
|---|---|
proxy | Единственный с ports — «лицо» стека для браузера |
frontend | Внутренний nginx со статикой; без проброса портов наружу |
api | Учебный HTTP-сервер; слушает 5678 (дефолт http-echo) |
Разбор nginx.conf:
| Строка | Смысл |
|---|---|
upstream front { server frontend:80; } | Имя frontend — DNS в Docker-сети |
location /api/ | Запросы с префиксом /api/ → бэкенд |
proxy_pass http://back/; | Проксирование на upstream back (http-echo) |
location / | Всё остальное → статика |
Проверка:
| URL | Ожидание |
|---|---|
http://localhost:8080/ | Ваш frontend/index.html |
http://localhost:8080/api/ | Текст API OK |
Подробнее про конфиги nginx — Nginx — конфиги под задачу.
12. Профили dev и tools
Задача: БД поднимается всегда; pgAdmin — только когда нужен. Поиск: docker compose profiles, pgadmin docker compose.
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: secret
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
pgadmin:
profiles: ["tools"]
image: dpage/pgadmin4:8
ports:
- "5050:80"
environment:
PGADMIN_DEFAULT_EMAIL: admin@local.dev
PGADMIN_DEFAULT_PASSWORD: admin
depends_on:
- db
volumes:
pg_data:
Разбор по строкам:
| Строка | Смысл |
|---|---|
profiles: ["tools"] | Сервис не стартует при обычном docker compose up |
PGADMIN_DEFAULT_EMAIL | Логин в UI pgAdmin |
5050:80 | UI pgAdmin → http://localhost:5050 |
Запуск и разбор команд:
docker compose up -d
docker compose --profile tools up -d pgadmin
| Команда | Смысл |
|---|---|
up -d | Только db — pgAdmin пропущен |
--profile tools | Включить сервисы с профилем tools |
up -d pgadmin | Поднять только pgAdmin (db уже работает) |
Подключение в pgAdmin: host db, port 5432, user/password из compose Postgres (создайте server в UI).
13. Переменные из .env
Задача: порты и пароли в одном файле, не захардкожены в YAML. Поиск: docker compose env file, docker-compose .env example.
.env:
APP_PORT=3000
POSTGRES_PASSWORD=secret
POSTGRES_USER=app
POSTGRES_DB=appdb
compose.yaml:
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
volumes:
pg_data:
Разбор:
| Файл / строка | Смысл |
|---|---|
.env | Лежит рядом с compose; Compose подставляет значения автоматически |
`${POSTGRES_USER}` | Плейсхолдер — заменится на app из .env |
.gitignore | Файл .env не коммитьте; в репозиторий — .env.example без секретов |
Что делает docker compose config:
- Читает
compose.yaml. - Подставляет переменные из
.envи из окружения ОС. - Печатает итоговый YAML — удобно проверить, что пароль подставился.
Шаблон .env.example для README:
POSTGRES_USER=app
POSTGRES_PASSWORD=change_me
POSTGRES_DB=appdb
14. Стек для CI-тестов
Задача: поднять БД, прогнать тесты в одноразовом контейнере, остановить всё. Поиск: docker compose run test, ci postgres docker compose.
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: test
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 3s
retries: 10
test:
build: .
environment:
DATABASE_URL: postgres://postgres:test@db:5432/postgres
depends_on:
db:
condition: service_healthy
command: ["npm", "test"]
Разбор по строкам:
| Строка | Смысл |
|---|---|
db без ports | БД только внутри Docker-сети — с хоста порт не нужен |
DATABASE_URL | Стандартная строка для ORM; хост db, пароль test |
command: ["npm", "test"] | Переопределяет CMD образа — запуск тестов |
retries: 10 | В CI БД иногда дольше стартует — больше попыток healthcheck |
Типичный сценарий в пайплайне:
docker compose up -d db
docker compose run --rm test
docker compose down -v
Разбор команд:
| Команда | Смысл |
|---|---|
up -d db | Поднять только сервис db, не test |
run --rm test | Создать контейнер test, выполнить npm test, удалить контейнер после exit |
down -v | Очистить тома — следующий прогон CI с чистой БД |
Отличие run от up: up держит сервисы постоянно; run — одноразовая команда (миграции, тесты, seed).
Шпаргалка команд
| Задача | Команда | Что происходит под капотом |
|---|---|---|
| Поднять стек | docker compose up -d | pull/build → сеть → тома → контейнеры → healthcheck |
| Пересобрать образы | docker compose up -d --build | docker build для каждого build: перед стартом |
| Статус | docker compose ps | Имена контейнеров, Up (healthy), проброшенные порты |
| Логи | docker compose logs -f api | stdout/stderr; -f = поток, как tail -f |
| Shell в контейнере | docker compose exec db sh | Новый процесс внутри уже работающего контейнера |
| Одноразовая команда | docker compose run --rm test npm test | Новый контейнер, команда, удаление после exit |
| Проверка YAML | docker compose config | Merge файлов + подстановка .env, без изменений на хосте |
| Остановка | docker compose down | Stop + remove контейнеров и сети; тома остаются |
| Сброс данных | docker compose down -v | Удаляет named volumes — БД «с нуля» |
| Только один сервис | docker compose up -d db | Остальные сервисы не трогаются |
Частые вопросы из поиска
| Вопрос | Короткий ответ | Где пример |
|---|---|---|
| Как поднять PostgreSQL локально? | compose.yaml + docker compose up -d | стек №3 |
| docker-compose.yml nginx | Один сервис web, ports: "8080:80" | стек №1 |
| WordPress docker compose | wordpress + mariadb + volumes | стек №6 |
| app + postgres + redis | три сервиса, DB_HOST=db, REDIS_URL=redis://redis:6379 | стек №5 |
| Cannot connect to Docker daemon | Запустите Docker Desktop / systemctl start docker | раздел «Как работать» |
| connection refused к БД | В контейнере app — хост db, не localhost | стек №4 |
| Куда делись данные после down? | Нужен named volume; down -v удаляет тома | стек №3 |
| version: '3' obsolete | В Compose V2 ключ version: часто опускают | теория |
Типичные ошибки новичка
| Ошибка | Что происходит | Как исправить |
|---|---|---|
DB_HOST=localhost в сервисе app | API не видит Postgres | указать имя сервиса db |
Нет healthcheck, только depends_on | app падает при старте БД | condition: service_healthy + pg_isready |
| Забыли том для БД | данные пропали после down | named volume на /var/lib/postgresql/data |
| Порт занят на хосте | Bind for 0.0.0.0:5432 failed | сменить левую часть в ports, например 15432:5432 |
.env в Git | утечка паролей | .gitignore + пример .env.example |
docker compose down -v на учебной БД | все таблицы «с нуля» | бэкап или без -v |
Практика — задания для лабораторной
- Nginx. Поднимите стек №1, замените порт
8080на8888, выполнитеdocker compose ps— в колонке PORTS должно быть8888->80/tcp. - Postgres. Подключитесь к стеку №3 через DBeaver или
psql: hostlocalhost, port5432, userapp, passwordsecret, databaseappdb. - Сеть. В стеке №4 выполните
docker compose exec api getent hosts db— в ответе IP контейнераdb. - Том. Создайте таблицу в Postgres, выполните
docker compose downи сноваup -d— таблица на месте. Затемdown -vиup -d— таблицы нет (данные сброшены). - Профиль. В стеке №12 убедитесь, что после
up -dpgAdmin не запущен (docker compose ps), а после--profile tools— появился.
Разбор команд и архитектуры — в Docker Compose.
Оглавление стеков — быстрый выбор
| № | Стек | Когда брать |
|---|---|---|
| 1 | nginx | Проверка Docker, первая лабораторная |
| 2 | nginx + папка html | Статический сайт, фронт без сборки |
| 3 | PostgreSQL | Локальная SQL-база для Java, Python, C# |
| 4 | Node + PostgreSQL | Backend + БД, учебный fullstack |
| 5 | app + Postgres + Redis | Кэш, сессии, «как в проде» |
| 6 | WordPress + MariaDB | CMS, блог, курсовой сайт |
| 7 | MongoDB + mongo-express | NoSQL, документы JSON |
| 8 | Prometheus + Grafana | Метрики, мониторинг |
| 9 | MailHog | Тест email без реальной отправки |
| 10 | MinIO | Файлы, S3 API |
| 11 | nginx reverse proxy | Один порт, несколько бэкендов |
| 12 | Postgres + pgAdmin (profile) | БД всегда, GUI по необходимости |
| 13 | .env + Postgres | Секреты вне YAML |
| 14 | db + test (CI) | GitHub Actions, GitLab CI |
Чек-лист перед сдачей лабораторной
-
docker compose configпроходит без ошибок. - Для связи между сервисами используются имена сервисов, не
localhost. - У PostgreSQL/MySQL/MariaDB есть named volume.
- Пароли вынесены в
.envили secrets, не в публичный репозиторий. - В README указаны URL, логины и команды
up/down.
Связанные материалы
| Материал | Зачем открыть |
|---|---|
| Docker Compose | теория, healthcheck, secrets, CI |
| Docker | образы, тома, сеть |
| Dockerfile | build: в compose |
| Dockerfile — 10 типовых образов | готовые Dockerfile под Node, Python, Go… |
| Манифесты зависимостей | compose в структуре проекта |
| Шаблоны | минимальный Dockerfile и прочие каркасы |
| Практикум Prometheus | полный observability-стек |
| PostgreSQL в Docker | init-скрипты и PGDATA |
| Nginx — конфиги под задачу | proxy, SPA, PHP-FPM, TLS вне compose |
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Практическая карта типовых IT-задач: термины, пошаговое внедрение, проверка качества и типичные ошибки. Простой консольный чат на C# — учебное приложение с сокетами: TCP между клиентом и сервером, многопоточность и обмен сообщениями в консоли. Примеры вёрстки на HTML и CSS с разбором: центрирование, Flexbox, Grid, формы, шапка, подвал и адаптив для учебы и портфолио. Перед началом работы обязательно изучите главу Turtle . Галерея 3D-фигур на Panda3D — карточки, куб, пирамида, сфера, сетки и составные сцены; код для локального запуска. Примеры nginx.conf для статики, reverse proxy, React/Vue SPA, PHP, SSL и балансировки — построчный разбор директив, проверка curl и типичные ошибки для лабораторных и VPS. dockerfile example — 10 готовых Dockerfile с построчным разбором: node, python, golang, react nginx, spring boot, php, dotnet. Для студентов, лабораторных и docker build с нуля. PromQL example — готовые запросы Prometheus и Grafana с построчным разбором: up, rate, node_exporter cpu, memory, disk, http_requests_total, histogram_quantile p99, алерты. Для студентов, лабораторных и devops docker compose. Готовые манифесты Kubernetes с разбором каждой строки — Pod, Deployment, Service, ConfigMap, Secret, Ingress. Примеры для Minikube, kind и kubectl apply. Примеры графиков Matplotlib на Python для школьников и студентов — sin, cos, парабола, столбцы, scatter, гистограмма, подграфики; код с подробным разбором. Примеры pandas на Python для школьников и студентов — DataFrame, фильтрация, groupby, очистка, merge, сводные таблицы и экспорт; код с подробным разбором каждой строки. p5.js и Processing — готовый код фигур с подробным разбором каждой строки: квадрат, треугольник, цветок, снежинка, фракталы, анимация; для школьников и студентов.Готовые решения
Простой консольный чат на CSharp
HTML + CSS — готовые макеты
Примеры фигур Turtle на Python
Примеры фигур Panda3D на Python
Nginx — конфиги под задачу
Dockerfile — 10 типовых образов
Prometheus + Grafana — запросы
Kubernetes YAML — минимальные манифесты
Matplotlib — графики
Pandas — типовые операции
Примеры фигур на Processing/p5.js