Контейнеризация и автоматизация: руководство по Docker

Когда проект разрастается, настройка окружения превращается в настоящий квест. На одном сервере стоит PHP 7.4, на другом — 8.1, у одного разработчика — Windows, у другого — Mac, а в продакшене — свой Linux со своими нюансами. Знакомая ситуация?

Docker решает эту проблему, упаковывая приложение со всеми его зависимостями в изолированный контейнер, который работает одинаково на любой системе. Это позволяет разработчикам забыть о фразе «на моей машине работает», автоматизировать развёртывание и легко масштабировать инфраструктуру.

В этой статье мы разберём:

  • Что такое контейнеризация и чем Docker отличается от виртуальных машин.
  • Установку Docker и Docker Compose на разных ОС.
  • Основные команды для работы с контейнерами и образами.
  • Создание собственных образов через Dockerfile.
  • Организацию многоконтейнерных приложений с Docker Compose.
  • Практические примеры: запуск LEMP-стека и приложения на Node.js.
  • Автоматизацию развёртывания и лучшие практики.

1. Что такое Docker и зачем он нужен

Docker — это платформа для разработки, доставки и запуска приложений в контейнерах. Контейнер — это лёгкая, изолированная среда, которая содержит всё необходимое для работы приложения: код, библиотеки, системные зависимости, переменные окружения.

Контейнеры vs виртуальные машины

Главное отличие — контейнеры используют ядро хост-системы, а виртуальные машины эмулируют полноценное аппаратное обеспечение с собственной ОС.

ХарактеристикаКонтейнеры (Docker)Виртуальные машины
ЗапускМгновенныйОт секунд до минут
РесурсыЗанимают минимум памятиТребуют много памяти и диска
ИзоляцияНа уровне процессовПолная аппаратная изоляция
ПереносимостьВысокаяОграничена гипервизором
Время развёртыванияСекундыМинуты

Преимущества Docker:

  • Единообразие окружений — приложение работает одинаково на всех этапах (разработка, тестирование, продакшен).
  • Изоляция — контейнеры не влияют друг на друга.
  • Лёгкость масштабирования — можно запускать десятки экземпляров одного сервиса.
  • Версионирование — образы можно сохранять, тегировать и откатывать.
  • Упрощение деплоя — не нужно вручную настраивать сервер, достаточно запустить контейнер.

2. Установка Docker и Docker Compose

2.1 Установка Docker на Ubuntu / Debian

Bash
# Обновление пакетов и установка зависимостей
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common

# Добавление официального GPG-ключа
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Добавление репозитория
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Установка Docker
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

# Добавление пользователя в группу docker (чтобы не использовать sudo)
sudo usermod -aG docker $USER

# Запуск и автозагрузка
sudo systemctl start docker
sudo systemctl enable docker

После добавления пользователя в группу необходимо выйти из системы и зайти заново.

2.2 Установка Docker на CentOS / RHEL / Rocky Linux

Bash
# Установка зависимостей
sudo dnf install -y yum-utils

# Добавление репозитория
sudo yum-config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo

# Установка Docker
sudo dnf install docker-ce docker-ce-cli containerd.io

# Добавление пользователя в группу
sudo usermod -aG docker $USER

# Запуск и автозагрузка
sudo systemctl start docker
sudo systemctl enable docker

2.3 Установка Docker на Windows

  1. Скачайте и установите Docker Desktop с официального сайта.
  2. Убедитесь, что в BIOS включена виртуализация (Hyper-V или WSL2).
  3. После установки перезагрузите систему.
  4. В настройках Docker Desktop выберите использование WSL2 для лучшей производительности.

После установки Docker Desktop стоит проверить в настройках (Settings → Resources → WSL Integration), правильно ли настроена интеграция с WSL2 — это сильно влияет на производительность при работе с файловой системой.

2.4 Установка Docker Compose

Docker Compose — это инструмент для запуска многоконтейнерных приложений. Обычно он устанавливается отдельно.

Bash
# Скачивание последней версии
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Права на выполнение
sudo chmod +x /usr/local/bin/docker-compose

# Проверка версии
docker-compose --version

В новых версиях Docker Compose интегрирован в команду docker compose (без дефиса). Если у вас установлен Docker Desktop, он уже идёт в комплекте.

3. Основы работы с Docker

3.1 Образы (Images) и контейнеры (Containers)

  • Образ — это шаблон, содержащий всё необходимое для запуска приложения (ОС, зависимости, код). Образы неизменяемы.
  • Контейнер — запущенный экземпляр образа. Он может быть изменён, но изменения не сохраняются в образе.

3.2 Основные команды Docker

Работа с образами:

Bash
# Поиск образа в Docker Hub
docker search nginx

# Скачивание образа
docker pull nginx:latest

# Список локальных образов
docker images

# Удаление образа
docker rmi nginx:latest

Работа с контейнерами:

Bash
# Запуск контейнера из образа
docker run -d --name mynginx -p 8080:80 nginx

# Список запущенных контейнеров
docker ps

# Список всех контейнеров (включая остановленные)
docker ps -a

# Остановка контейнера
docker stop mynginx

# Запуск остановленного контейнера
docker start mynginx

# Удаление контейнера
docker rm mynginx

# Выполнение команды внутри контейнера
docker exec -it mynginx bash

# Просмотр логов
docker logs mynginx

# Просмотр статистики использования ресурсов
docker stats

Ключи команды docker run:

КлючОписание
-dЗапуск в фоновом режиме (detach)
--nameУказание имени контейнера
-pПроброс портов (хост:контейнер)
-vМонтирование томов (хост:контейнер)
-eУстановка переменной окружения
--restartПолитика перезапуска (always, on-failure)
-itИнтерактивный режим с терминалом

3.3 Работа с томами (Volumes)

По умолчанию данные внутри контейнера не сохраняются после его удаления. Чтобы этого избежать, используют тома.

Три способа монтирования данных:

1. Базовое монтирование директории (bind mount):

Bash
docker run -d -p 8080:80 -v /путь/на/хосте:/usr/share/nginx/html nginx

2. Именованный том (volume):

Bash
# Создание тома
docker volume create mydata

# Использование тома
docker run -d -v mydata:/data alpine

3. Временное хранилище (tmpfs) — только в памяти:

Bash
docker run -d --tmpfs /tmp alpine

4. Создание собственных образов с Dockerfile

Dockerfile — это текстовый файл с инструкциями по сборке образа.

4.1 Структура Dockerfile

Рассмотрим простой пример для PHP-приложения:

# Базовый образ (используем официальный PHP с Apache)
FROM php:8.1-apache

# Копирование файлов проекта в контейнер
COPY . /var/www/html/

# Установка PHP-расширений
RUN docker-php-ext-install mysqli pdo pdo_mysql

# Включение модуля Apache
RUN a2enmod rewrite

# Настройка рабочей директории
WORKDIR /var/www/html

# Открываем порт
EXPOSE 80

# Команда по умолчанию (запуск Apache)
CMD ["apache2-foreground"]

4.2 Основные инструкции Dockerfile

ИнструкцияОписание
FROMБазовый образ
RUNВыполнение команды во время сборки
COPYКопирование файлов с хоста в контейнер
ADDАналог COPY, но умеет распаковывать архивы
WORKDIRУстановка рабочей директории
ENVУстановка переменных окружения
ARGПеременная времени сборки
EXPOSEДокументирование портов
CMDКоманда по умолчанию при запуске
ENTRYPOINTОсновная команда для запуска контейнера
VOLUMEМонтирование тома

4.3 Сборка и запуск образа

Bash
# Сборка образа
docker build -t my-php-app .

# Запуск контейнера из собранного образа
docker run -d -p 8080:80 --name myapp my-php-app

4.4 Оптимизация Dockerfile

Советы по сборке эффективных образов:

  • Используйте многоступенчатую сборку (multi-stage) для уменьшения размера.
  • Объединяйте команды RUN в одну строку (чтобы уменьшить количество слоёв).
  • Копируйте файлы в конце — это ускорит повторную сборку при изменении кода.
  • Используйте .dockerignore, чтобы исключить ненужные файлы.
  • Если часто меняется код приложения, но базовые зависимости (например, базовый образ ОС) остаются теми же, Docker будет эффективно использовать уже собранные слои — это ускорит повторные сборки.

Пример с многоступенчатой сборкой для Node.js:

# Этап сборки
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Этап исполнения
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80

5. Docker Compose для многоконтейнерных приложений

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

5.1 Базовая структура docker-compose.yml

YAML
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
    restart: always

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
    volumes:
      - db_data:/var/lib/mysql
    restart: always

volumes:
  db_data:

5.2 Основные команды Docker Compose

Bash
# Запуск всех сервисов (в фоне)
docker-compose up -d

# Остановка и удаление контейнеров
docker-compose down

# Просмотр логов
docker-compose logs -f

# Пересборка и запуск
docker-compose up -d --build

# Масштабирование сервиса
docker-compose up -d --scale web=3

# Выполнение команды в контейнере
docker-compose exec web bash

5.3 Пример: LEMP-стек (Linux, Nginx, MySQL, PHP)

YAML
services:
  db:
    image: mariadb:10.6
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 2s
      retries: 5
  php:
    depends_on:
      db:
        condition: service_healthy
    restart: always

volumes:
  db_data:

Никогда не храните пароли в docker-compose.yml в репозитории. Используйте .env и добавьте его в .gitignore.

5.4 Пример: Node.js + Redis

YAML
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - REDIS_URL=redis://redis:6379
    depends_on:
      - redis
    restart: always

  redis:
    image: redis:alpine
    restart: always

В нашем каталоге шаблонов docker-compose вы найдёте примеры с .env, healthcheck и безопасными настройками — их можно быстро адаптировать под свой проект.

6. Автоматизация развёртывания

6.1 Использование Docker в CI/CD

Контейнеры идеально вписываются в пайплайны непрерывной интеграции и доставки.

Типичный сценарий:

  1. Разработчик пушит код в репозиторий.
  2. CI-система (например, GitHub Actions или GitLab CI) собирает Docker-образ.
  3. Образ тестируется в контейнере (запуск тестов, линтеров).
  4. Готовый образ отправляется в реестр (Docker Hub, приватный реестр).
  5. На сервере новый образ развёртывается автоматически.

Пример GitHub Actions для сборки и публикации образа:

YAML
name: Build and Push Docker Image

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Log in to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          push: true
          tags: myuser/myapp:latest

Эти значения хранятся в настройках репозитория (Settings → Secrets → Actions) и никогда не должны попадать в код. Не копируйте эти значения в репозиторий. Переменные DOCKER_USERNAME и DOCKER_PASSWORD берутся из секретов GitHub (Settings → Secrets → Actions)

6.2 Развёртывание на сервере

На продакшен-сервере достаточно иметь установленные Docker и Docker Compose.

Самый простой способ деплоя:

Bash
# Копирование кода и docker-compose.yml на сервер
rsync -avz --exclude='node_modules' ./ user@server:/app/

# Запуск обновлённой версии
cd /app
docker-compose down
docker-compose pull
docker-compose up -d

Можно автоматизировать этот процесс с помощью простого скрипта:

Bash
#!/usr/bin/env bash
set -euo pipefail

echo "Начинаем деплой..."

git pull origin main
echo "Контейнеры остановлены."
docker-compose down

echo "Образы собраны."
docker-compose build --pull

echo "Сервисы запущены."
docker-compose up -d

echo "✅ Деплой успешно завершён!"

6.3 Использование Docker Swarm или Kubernetes

Для крупных проектов с десятками серверов используют оркестраторы:

  • Docker Swarm — встроенный в Docker инструмент для кластеризации.
  • Kubernetes — мощная, но сложная система от Google, ставшая стандартом в индустрии.

Для небольших и средних проектов Docker Swarm может быть хорошим выбором благодаря своей простоте.

Bash
# Инициализация кластера Swarm
docker swarm init

# Развёртывание стека только для кластера!!!
docker stack deploy -c docker-compose.yml myapp

# Управление сервисами
docker service ls
docker service scale myapp_web=5

🔍 Важно: Команда docker stack deploy предназначена для кластеров Docker Swarm и не является заменой обычного docker-compose up. Для одиночного сервера используйте docker compose up -d.

7. Практические советы и лучшие практики

7.1 Безопасность Docker

  • Не запускайте контейнеры от root — используйте пользователя с ограниченными правами.
  • Регулярно обновляйте образы — старые версии могут содержать уязвимости.
  • Не храните секреты в образах — используйте переменные окружения или секреты (Docker Secrets).
  • Ограничивайте ресурсы контейнеров (CPU и память) с помощью --cpus и --memory.
  • Сканируйте образы на уязвимости (например, Docker Scout или Trivy).

7.2 Оптимизация и управление ресурсами

Bash
# Ограничение памяти и CPU при запуске
docker run -d --memory=256m --cpus=0.5 nginx

# Очистка неиспользуемых объектов Docker
docker system prune -af

# Очистка всех томов, образов и контейнеров
docker system prune -a --volumes

⚠️ Осторожно: Команды docker system prune -a --volumes удаляют все неиспользуемые объекты, включая тома с данными. Не используйте их на продакшене без полного понимания последствий.

7.3 Логирование

По умолчанию Docker записывает всё в stdout/stderr. Для продакшена стоит настроить драйвер логов:

Bash
# В docker-compose.yml
logging:
  driver: "json-file"
  options:
    max-size: "10m"
    max-file: "3"

7.4 Когда НЕ стоит использовать Docker

  • Очень маленькие проекты — настройка Docker может быть избыточной.
  • Приложения с высокими требованиями к производительности — особенно если критична задержка при работе с железом.
  • Специфическое ПО — иногда проще установить напрямую на хост.

8. Заключение

Docker — это мощный и гибкий инструмент, который позволяет:

  • Упаковывать приложения в изолированные и переносимые контейнеры.
  • Описывать всю инфраструктуру кодом (Infrastructure as Code).
  • Легко масштабировать и автоматизировать развёртывание.

Мы рассмотрели ключевые концепции, установку, базовые команды, создание образов, многоконтейнерные приложения и автоматизацию. Практические примеры показывают, как можно использовать Docker для организации реальных проектов.

Освоив контейнеризацию, вы перейдёте на новый уровень разработки и администрирования. Ваши проекты станут более надёжными, предсказуемыми и легко масштабируемыми.

На codestack.space собраны не только статьи, но и полезные инструменты для веб‑разработчиков и администраторов: конструкторы конфигураций, шаблоны Dockerfile, сниппеты для CI/CD и чек‑листы по безопасности — чтобы сложные вещи можно было быстро развернуть и адаптировать под свой сервер