Современные веб-приложения почти никогда не состоят из одной-единственной программы. Даже скромный проект обычно требует совместной работы веб-сервера, базы данных и сервиса кэширования. Установка, настройка и связывание каждого из этих компонентов по отдельности отнимает много времени и часто приводит к ошибкам. Docker и Docker Compose были созданы именно для решения этой задачи: они позволяют описать всю рабочую среду в одном файле и запустить её одной командой.
Что такое контейнер и зачем он нужен
Контейнер Docker — это лёгкая изолированная среда, которая упаковывает приложение вместе со всеми его зависимостями. В отличие от виртуальной машины, контейнер не включает в себя целую операционную систему, а содержит только библиотеки и файлы, необходимые конкретному приложению. Благодаря этому он запускается за доли секунды и потребляет минимум ресурсов. Один и тот же контейнер работает одинаково и на ноутбуке разработчика, и на сервере sayt.uz, что полностью устраняет классическую проблему «а у меня всё работает». Образ контейнера — это шаблон, из которого можно поднять сколько угодно идентичных копий.
Работать с одним контейнером несложно, но в реальных проектах их требуется несколько, и управлять ими вручную становится утомительно. Прописывать сеть, порты и взаимные связи для каждого контейнера по отдельности — занятие неблагодарное и чреватое ошибками. Именно здесь на сцену выходит Docker Compose, который превращает разрозненный набор контейнеров в единую, согласованную систему.
Что делает Docker Compose
Docker Compose — это инструмент для описания и управления многоконтейнерными приложениями. Вы описываете все нужные сервисы, их образы, порты, тома и взаимные зависимости в одном YAML-файле под названием docker-compose.yml. После этого одна команда поднимает всю систему целиком: Compose скачивает нужные образы, создаёт контейнеры, настраивает между ними сеть и запускает их в заданном порядке. Такой подход позволяет хранить инфраструктуру как код, то есть версионировать конфигурацию в Git и легко делиться ею с командой.
Структура файла docker-compose.yml
В центре файла Compose находится раздел services — именно здесь объявляется каждый контейнерный сервис. Для каждого сервиса вы указываете через image, какой образ использовать, через ports — связь внешних и внутренних портов, через volumes — тома для постоянного хранения данных, через environment — переменные окружения, а через depends_on — порядок запуска. Следующий пример показывает основные поля:
services:
web:
image: php:8.2-apache
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
environment:
APP_ENV: production
depends_on:
- db
- cache
Запись «8080:80» под ports перенаправляет порт 8080 сервера на внутренний порт 80 контейнера. Раздел volumes подключает код проекта с хост-системы внутрь контейнера, поэтому при изменении кода контейнер не нужно пересобирать. Параметр depends_on сообщает Compose, что сервис web следует запускать после базы данных и кэша.
Практический пример: PHP + MySQL + Redis
Теперь рассмотрим полноценный пример, близкий к реальному проекту. В нём веб-приложение работает на PHP, данные хранятся в базе MySQL, а часто запрашиваемая информация лежит в кэше Redis. Следующая конфигурация связывает три сервиса друг с другом и объединяет их в единую сеть:
services:
app:
image: php:8.2-apache
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
depends_on:
- db
- cache
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: shop
volumes:
- db_data:/var/lib/mysql
cache:
image: redis:7
ports:
- "6379:6379"
volumes:
db_data:
Обратите внимание: при подключении к базе данных из сервиса app в качестве хоста можно использовать просто имя db, потому что Compose делает каждый сервис доступным в сети по его имени. Объявленный внизу в разделе volumes том db_data — это именованный том, который гарантирует сохранность данных MySQL даже после удаления контейнера. Это критически важно: иначе при каждом пересоздании контейнера база оказывалась бы пустой.
Основные команды
Работа с Compose опирается на несколько простых команд. Чтобы поднять всю среду, в папке проекта выполняется команда docker compose up; флаг -d запускает её в фоновом режиме, не занимая терминал. Чтобы остановить систему и удалить созданные контейнеры и сети, используется docker compose down. Для наблюдения за работой сервисов и поиска ошибок чрезвычайно полезна команда docker compose logs:
docker compose up -d
docker compose logs -f app
docker compose ps
docker compose down
За этими командами стоит жизненный цикл целой среды. Одна команда up избавляет разработчика от многочасовой ручной настройки, а down бесследно очищает окружение и возвращает систему в исходное состояние. Такая предсказуемость и есть главная ценность Compose в повседневной работе.
Преимущества и разница между dev и prod
Главное преимущество Docker Compose — возможность поднять всю сложную среду одной командой и так же легко её остановить. Когда в команду приходит новый разработчик, ему достаточно клонировать репозиторий и выполнить up; рабочее окружение он получает за минуты, а не за часы. Поскольку договорённость зафиксирована внутри файла конфигурации, все работают с одинаковыми версиями сервисов, и различия между средами исчезают.
При этом подход для среды разработки (dev) и для продакшена (prod) несколько отличается. В режиме dev удобно подключать хост-тома к контейнеру для живого редактирования кода, включается режим отладки, а пароли могут быть простыми. В режиме prod на первом месте стоит безопасность: секретные данные защищаются через переменные окружения или специальные хранилища секретов, вместо живого подключения кода предпочтительно полностью встраивать его в образ, а на ресурсы накладываются ограничения. При развёртывании вашего проекта на серверах sayt.uz применение именно такого продакшен-подхода обеспечивает стабильную и безопасную работу. Освоение Docker Compose сегодня стало необходимым навыком для любого разработчика и DevOps-инженера.