Docker Compose — основы работы с контейнерами и с файлом yml (YAML) - Академия Selectel

Docker Compose и основы работы с контейнерами

Геннадий Паршаков
Геннадий Паршаков Разработчик
12 марта 2025

Запуск многоконтейнерных приложений в 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 необходимо:

  1. создать Dockerfile,
  2. настроить конфигурацию Nginx,
  3. описать сервис в 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-логику приложения. Для его создания необходимо:

  1. использовать официальный образ PHP с поддержкой FPM (FastCGI Process Manager),
  2. настроить PHP для работы с Nginx,
  3. описать сервис в 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, необходимо:

  1. убедиться, что оба контейнера находятся в одной сети (app_network),
  2. указать в конфигурации 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, чтобы обеспечить корректную коммуникацию между контейнерами.