Пример: приложение и база данных

Собираем всё вместе: реальный 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 и nginximage (взять готовый образ). 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 не хранит данные на диске
Поддержать проект