Docker Compose и основы работы с контейнерами
Запуск многоконтейнерных приложений в Docker Compose: расскажем про создание файла docker-compose.yml, настройку сети и команды для работы с контейнерами.

В этой статье рассмотрим, как использовать Docker Compose для управления многоконтейнерными приложениями. Разберем, зачем нужен Docker Compose и как он помогает решать задачи разработки, тестирования и развертывания. Узнаем, как создавать и настраивать контейнеры для приложений с помощью файла docker-compose.yml. Расскажем, какие команды будут полезны в работе с контейнерами и как настраивать пользовательские сети для взаимодействия компонентов внутри проекта.
Зачем нужен Docker Compose
Docker Compose — это инструмент управления многоконтейнерными приложениями. Он упрощает разработку, развертывание и тестирование сложных проектов, где используются несколько сервисов. Ими могут быть веб-серверы, базы данных, приложения и другие компоненты.
В отличие от Docker, который работает с отдельными контейнерами, Docker Compose ориентирован на управление несколькими контейнерами одновременно. Он описывает их конфигурацию в одном файле — docker-compose.yml. Это делает его незаменимым инструментом для разработчиков и DevOps-инженеров, которые хотят автоматизировать сборку, запуск и настройку сети между контейнерами.
Сравнивать Docker Compose с Docker корректно, но важно понимать их различия. Docker — это инструмент для создания и управления отдельными контейнерами. Docker Compose же предназначен для работы с группами контейнеров, объединенных в сервисы.
Например, с помощью Docker Compose можно одной командой запустить весь проект, включая веб-сервер, базу данных и приложение, а также настроить сеть между ними.
docker-compose up
Это значительно ускоряет разработку и упрощает управление зависимостями между компонентами. За это Docker Compose и ценят в современных IT-проектах.
Что такое YAML
YAML — это человекочитаемый формат данных, который часто используется для создания конфигурационных файлов, например docker-compose.yml. Формат прост и имеет понятный синтаксис. Это делает его идеальным для описания конфигураций сервисов, сетей, портов и других параметров в Docker Compose.
В YAML используются отступы для обозначения структуры, что позволяет легко описывать сложные зависимости и настройки. Например, из файла docker-compose.yml можно указать, какие образы использовать, как настроить сеть между контейнерами, какие порты открыть на хосте и как управлять переменными окружения. Благодаря своей гибкости и удобству, YAML стал стандартом для работы с Docker Compose и другими инструментами в сфере разработки и DevOps.
Создание проекта для запуска в Docker Compose
Запуск проекта с использованием Docker Compose предполагает создание и настройку нескольких контейнеров, которые работают вместе. В этом разделе мы рассмотрим, как создать контейнеры для Nginx и PHP, чтобы они могли взаимодействовать друг с другом. Это типичный сценарий для веб-приложений, где Nginx выступает в роли веб-сервера, а PHP обрабатывает backend-логику.
Создание контейнера для Nginx
Nginx — высокопроизводительный веб-сервер, который часто используется для обслуживания статических файлов и проксирования запросов к backend-сервисам. Для создания контейнера с Nginx необходимо:
- создать Dockerfile,
- настроить конфигурацию Nginx,
- описать сервис в docker-compose.yml.
Пример Dockerfile для Nginx:
FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf
COPY ./html /usr/share/nginx/html
Пример минимальной конфигурации для проксирования запросов к PHP (nginx.conf):
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php:9000; # Связь с PHP-контейнером
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Описание сервиса в docker-compose.yml:
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./html:/var/www/html
depends_on:
- php
networks:
- app_network
Создание контейнера для PHP
PHP-контейнер будет обрабатывать backend-логику приложения. Для его создания необходимо:
- использовать официальный образ PHP с поддержкой FPM (FastCGI Process Manager),
- настроить PHP для работы с Nginx,
- описать сервис в docker-compose.yml.
Пример Dockerfile для PHP:
FROM php:8.2-fpm
RUN docker-php-ext-install pdo_mysql
Описание сервиса в docker-compose.yml:
services:
php:
image: php:8.2-fpm
container_name: php
volumes:
- ./php:/var/www/html # Проброс директории с PHP-кодом
networks:
- app_network
Создание файла docker-compose.yml и настройка проекта
Чтобы Nginx мог передавать запросы PHP-FPM, необходимо:
- убедиться, что оба контейнера находятся в одной сети (app_network),
- указать в конфигурации Nginx правильный адрес PHP-контейнера (в нашем примере это php:9000, где php — имя сервиса в docker-compose.yml).
Итоговый docker-compose.yml:
version: '3.8'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/html:/var/www/html
depends_on:
- php
networks:
- app_network
php:
image: php:8.2-fpm
container_name: php
volumes:
- ./php:/var/www/html
networks:
- app_network
networks:
app_network:
driver: bridge
Создайте файл index.php в директории php/:
<?php
echo "Hello from PHP!";
?>
Запустите проект командой:
docker-compose up -d
Откройте браузер и перейдите по адресу http://localhost. Вы увидите сообщение «Hello from PHP!». Оно означает успешную работу связки Nginx и PHP.
Пример структуры проекта:
project/
├── docker-compose.yml
├── nginx/
│ ├── nginx.conf
│ └── html/
├── php/
│ └── index.php
Работа с контейнерами в Docker Compose
Docker Compose предоставляет удобный способ управления контейнерами, начиная от их сборки и запуска, заканчивая остановкой и удалением.
Сборка контейнеров в Docker Compose
Используйте команду:
docker-compose build
Она позволяет создать образы на основе инструкций, указанных в docker-compose.yml.
Запуск всех сервисов
docker-compose up
Запуск контейнеров в фоновом режиме
Для этой задачи можно добавить в команду флаг -d:
docker-compose up -d
Это особенно полезно для развертывания приложений на сервере.
Остановка контейнеров без их удаления
Это делается командой:
docker-compose stop
Она приостанавливает работу всех сервисов, описанных в docker-compose.yml, но сохраняет их состояние.
Остановка и полное удаление контейнеров, сети и тома
Выполните команду:
docker-compose down
Удаление образов
Чтобы удалить образы, необходим дополнительный флаг —rmi all:
docker-compose down --rmi all
Удаление томов
А для удаления томов добавьте флаг —volumes:
docker-compose down --volumes
Выполнение команд внутри запущенного контейнера
Для выполнения команд внутри запущенного контейнера используется команда:
docker-compose exec <service_name> <command>
Здесь <service_name> — это имя сервиса, а <command> — команда, которую нужно выполнить. Например, чтобы открыть терминал в контейнере с PHP, выполните:
docker-compose exec php bash
Зависимости между сервисами
Зависимости между сервисами задаются в docker-compose.yml с помощью опции depends_on. Например, чтобы база данных запускалась перед приложением:
services:
app:
depends_on:
- db
Для запуска контейнера от имени определенного пользователя, нужно настроить опцию user в конфигурации:
services:
app:
user: "<user_id_or_user_name>:<group_id_or_group_name>"
Проброс папок между хостом и контейнером настраивается через volumes. Например:
services:
app:
volumes:
- ./app:/var/www/html
Переменные окружения задаются с помощью environment в docker-compose.yml:
services:
db:
environment:
MYSQL_ROOT_PASSWORD: password
Для просмотра логов конкретного сервиса применяется команда:
docker-compose logs <service_name>
Например, если нужно, чтобы nginx показал логи веб-сервера, нужно запустить команду:
docker-compose logs nginx
Проброс портов настраивается через ports. Например, чтобы связать порт 80 на хосте с портом 8080 в контейнере, выполните:
services:
web:
ports:
- "80:8080"
Лимиты на использование CPU и памяти задаются через deploy.resources.limits:
services:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
Метки добавляются для удобства управления контейнерами. Например:
services:
web:
labels:
com.example.description: "Web service"
Docker Compose делает процесс работы с контейнерами простым и эффективным, автоматизируя множество рутинных задач.
Работа с сетью
Создание пользовательских сетей
Docker Compose позволяет создавать пользовательские сети для улучшения управления коммуникацией между контейнерами. По умолчанию Compose создает одну сеть для всех сервисов, но можно определить дополнительные сети в файле docker-compose.yml. Например, чтобы создать сеть с именем app_network, используется следующий код:
networks:
app_network:
driver: bridge
Чтобы подключить к этой сети нужные сервисы, нужно указать их в разделе networks каждого сервиса. Это полезно для сложных проектов, где требуется разделение сетевых ресурсов.
Изоляция сетей
Изоляция сетей позволяет ограничить взаимодействие между контейнерами, что повышает безопасность и упрощает управление. В Docker Compose можно создать несколько сетей и подключить к ним только определенные сервисы. Например, база данных может быть изолирована в отдельной сети, доступной только для backend-сервисов. Это делается через конфигурацию networks в docker-compose.yml:
services:
db:
networks:
- db_network
backend:
networks:
- db_network
- app_network
Здесь сервис db изолирован в сети db_network, а backend имеет доступ как к db_network, так и к app_network.
Коммуникация между контейнерами
Docker Compose упрощает коммуникацию между контейнерами, автоматически настраивая DNS-имена для каждого сервиса. Это позволяет обращаться к контейнерам по имени сервиса, указанному в docker-compose.yml. Например, если у вас есть сервис db, вы можете подключиться к нему из другого контейнера, используя имя db как хост. Пример:
services:
db:
image: postgres
app:
image: my_app
environment:
DB_HOST: db
В этом случае сервис app сможет подключиться к базе данных, используя db как хост. Docker Compose автоматически настроит сеть и DNS, чтобы обеспечить корректную коммуникацию между контейнерами.