Пример: приложение и база данных
Собираем всё вместе: реальный compose.yaml с веб-приложением, базой PostgreSQL и nginx.
Стек — набор связанных сервисов, поднимаемых вместе как единое приложение.
Что строим
Типичное веб-приложение из трёх частей: web (наше приложение, собираем из Dockerfile), db (PostgreSQL для данных) и nginx (раздаёт статику и проксирует запросы). Все три опишем в одном файле и поднимем одной командой.
Полный compose.yaml
services:
web:
build: .
environment:
DATABASE_URL: postgresql://postgres:secret@db:5432/appdb
depends_on:
- db
expose:
- "8000"
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: appdb
volumes:
- pgdata:/var/lib/postgresql/data
nginx:
image: nginx:1.27
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- web
volumes:
pgdata:
Разбор по сервисам
- web собирается из локального Dockerfile (
build: .), а не из готового образа. Черезenvironmentполучает строку подключения, где хост — имя сервисаdb.exposeоткрывает порт только внутри сети Docker (для nginx), наружу не публикует. - db — официальный PostgreSQL. Данные сохраняются в томе
pgdata, поэтому переживают перезапуск.POSTGRES_DBсоздаёт базуappdbпри первом старте. - nginx публикует порт
8080наружу, монтирует свой конфиг в режиме только для чтения (:ro) и проксирует на сервисwebпо имени.
build против image
Обратите внимание: web использует build: . (собрать из Dockerfile), а db и nginx — image (взять готовый образ). Compose умеет и то, и другое в одном файле.
Запуск и проверка
# Собрать web и поднять весь стек
docker compose up -d --build
# Убедиться, что все три сервиса работают
docker compose ps
Вывод:
NAME IMAGE STATUS PORTS myapp-db-1 postgres:16 Up 5 seconds myapp-web-1 myapp-web Up 4 seconds 8000/tcp myapp-nginx-1 nginx:1.27 Up 3 seconds 0.0.0.0:8080->80/tcp
Откройте http://localhost:8080 — запрос идёт в nginx, тот проксирует на web, а web ходит в базу db. Три контейнера, связанные по именам через автоматическую сеть Compose, работают как единое приложение.
Итог
- Реальный стек собирают в одном
compose.yaml: приложение, база и веб-сервер. buildсобирает образ из Dockerfile,imageберёт готовый — можно смешивать.- Сервисы общаются по именам, данные базы хранятся в томе, наружу публикуют только nginx.
Проверьте себя
1. Чем отличается build от image в описании сервиса Compose?
AЭто синонимы
Bbuild собирает образ из локального Dockerfile, image берёт готовый образ
Cimage собирает из Dockerfile, build скачивает готовый
Dbuild работает только с базами данных
2. Как сервис web в примере подключается к базе db?
AПо жёстко прописанному IP-адресу базы
BПо имени сервиса db в строке подключения, через автоматическую сеть Compose
CЧерез проброшенный наружу порт
DЧерез общий том
3. Почему данные PostgreSQL в этом примере не теряются при перезапуске?
AОни хранятся в образе postgres
BОни сохраняются в именованном томе pgdata
CОни записываются в nginx.conf
DPostgreSQL не хранит данные на диске