Плейбук по Docker

Полное руководство по Docker: установка, команды, Dockerfile, Compose, сети, volumes, CI/CD, безопасность и best practices

Версия 2.0 • 2026

1. Введение в Docker

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

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

ХарактеристикаКонтейнер (Docker)Виртуальная машина
ЯдроРазделяет ядро хостаСобственное ядро (гостевая ОС)
ИзоляцияProcess-level (namespaces)Полная (гипервизор)
РазмерMB (десятки-сотни)GB (единицы-десятки)
ЗапускСекундыМинуты
Потребление RAMТолько процесс + overlayПолная ОС (2-8 GB overhead)

2. Архитектура Docker

Docker использует клиент-серверную архитектуру:

  • Docker Client (docker) — CLI, отправляет команды демону
  • Docker Daemon (dockerd) — серверный компонент, управляет объектами: images, containers, networks, volumes
  • Docker Registry — репозиторий образов (Docker Hub, private registry)
  • Docker Objects — образы, контейнеры, сети, volumes, плагины

Ключевые технологии

ТехнологияРоль
NamespacesИзоляция процессов: PID, Network, Mount, User, UTS, IPC
CgroupsОграничение ресурсов: CPU, RAM, Disk I/O, Network
UnionFS (OverlayFS)Слоистая файловая система для образов (layers)
Container RuntimeЗапуск и управление контейнерами (runc, containerd)
libnetworkУправление сетями: bridge, overlay, host, macvlan

3. Установка и настройка

Linux (Ubuntu/Debian)

sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER  # перезайти в сессию

macOS / Windows

  • Docker Desktop: скачать с docker.com, установить, запустить
  • Проверка: docker --version && docker compose version

Post-install шаги

# Проверка установки
docker run hello-world

# Настройка автозапуска
sudo systemctl enable docker

# Без sudo (после usermod — перезайти)
docker ps

# Docker info
docker info

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

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

КомандаОписаниеПример
docker runСоздать и запустить контейнерdocker run -d --name nginx -p 8080:80 nginx
docker psСписок запущенных контейнеровdocker ps -a (все)
docker stopОстановить контейнерdocker stop nginx
docker startЗапустить остановленныйdocker start nginx
docker rmУдалить контейнерdocker rm -f nginx (force)
docker logsЛоги контейнераdocker logs -f nginx (follow)
docker execВыполнить команду внутри контейнераdocker exec -it nginx bash
docker cpКопировать файлы между хостом и контейнеромdocker cp data.txt nginx:/tmp

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

КомандаОписание
docker imagesСписок локальных образов
docker pullСкачать образ из registry
docker build -t name .Собрать образ из Dockerfile
docker pushОтправить образ в registry
docker rmiУдалить образ
docker tagПрисвоить тег образу
docker historyСлои образа

Системные команды

docker system df           # Использование диска
docker system prune        # Очистка неиспользуемых объектов
docker container prune     # Удалить остановленные контейнеры
docker image prune         # Удалить неиспользуемые образы
docker volume prune        # Удалить неиспользуемые volumes
docker network prune       # Удалить неиспользуемые сети

5. Dockerfile — создание образов

Dockerfile — текстовый файл с инструкциями для сборки образа. Каждая инструкция создаёт слой (layer).

Инструкции Dockerfile

ИнструкцияОписаниеПример
FROMБазовый образFROM python:3.12-slim
WORKDIRРабочая директорияWORKDIR /app
COPYКопировать файлы в образCOPY requirements.txt .
ADDКопировать + авто-распаковка архивов, URLADD app.tar.gz /app
RUNВыполнить команду в образеRUN pip install -r requirements.txt
CMDКоманда по умолчанию (exec form)CMD ["python", "app.py"]
ENTRYPOINTОсновная команда контейнераENTRYPOINT ["python"]
ENVПеременные окруженияENV MODE=production
ARGПеременные сборкиARG VERSION=1.0
EXPOSEДокументировать портEXPOSE 8000
VOLUMEТочка монтирования volumeVOLUME /data
USERПользователь для запускаUSER appuser
LABELМетаданные образаLABEL version="1.0"
HEALTHCHECKПроверка здоровья контейнераHEALTHCHECK --interval=30s CMD curl -f http://localhost/

Пример: Python FastAPI

FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Multi-stage build

  • AS builder — первый этап: установка зависимостей, компиляция
  • COPY --from=builder — копирование только артефактов из builder
  • Результат: минимальный финальный образ (без исходников, компиляторов)

6. Docker Compose

Docker Compose — инструмент для определения и запуска многоконтейнерных приложений. Конфигурация в YAML-файле compose.yml (или docker-compose.yml).

Структура compose.yml

services:
  web:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - db
      - redis
    environment:
      - DATABASE_URL=postgresql://postgres:pass@db:5432/app
    volumes:
      - .:/app
      - static_data:/static

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: pass

  redis:
    image: redis:7-alpine

volumes:
  pgdata:
  static_data:

networks:
  default:
    driver: bridge

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

КомандаОписание
docker compose up -dЗапустить все сервисы в фоне
docker compose downОстановить и удалить контейнеры, сети
docker compose logs -fЛоги всех сервисов (follow)
docker compose psСтатус сервисов
docker compose exec web bashВойти в контейнер сервиса web
docker compose buildПересобрать образы
docker compose pullОбновить образы из registry
docker compose restartПерезапустить сервисы

Profiles (профили)

  • Позволяют запускать подмножество сервисов: docker compose --profile test up
  • Пример: сервисы db (всегда), test-runner (profile: test)

Docker Compose Watch (горячая перезагрузка)

Начиная с Compose 2.24, доступна docker compose watch — автоматическое обновление контейнера при изменении файлов на хосте без пересборки образа:

services:
  web:
    build: .
    develop:
      watch:
        - path: ./src
          action: sync
          target: /app/src
        - path: ./package.json
          action: rebuild
docker compose watch
Режимы action: sync — синхронизация файлов (bind mount без пересборки), rebuild — пересборка образа при изменении критичных файлов, restart — перезапуск сервиса.

7. Сети в Docker

Типы сетей

ТипОписаниеИспользование
bridgeВнутренняя сеть на хосте (по умолчанию)Одиночные контейнеры, Compose
hostКонтейнер использует сеть хостаМаксимальная производительность, без изоляции
overlayСеть между несколькими хостами (Docker Swarm)Кластер, Swarm mode
macvlanКонтейнеру присваивается MAC-адресLegacy приложения, мониторинг сети
ipvlanКонтейнеру присваивается IP-адрес (без MAC)Высокая плотность, L3 сегментация
noneБез сетиИзолированные задачи, безопасность

Детально о типах сетей

Host mode

Контейнер использует сетевой стек хоста напрямую — нет изоляции, но максимальная производительность.

docker run --network host nginx
# Порт 80 контейнера доступен на localhost:80 хоста
  • Плюсы: минимальная задержка, нет NAT, порты не нужно публиковать
  • Минусы: конфликты портов, нет изоляции, не работает на Docker Desktop (macOS/Windows)
  • Когда использовать: высоконагруженные сервисы (Nginx, HAProxy), мониторинг

Macvlan

Контейнер выглядит как отдельное устройство в физической сети — с собственным MAC и IP адресом.

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  my-macvlan

docker run --network my-macvlan --ip=192.168.1.100 nginx
  • Плюсы: контейнеры доступны напрямую из LAN, поддержка legacy-приложений
  • Минусы: хост не может общаться со своими macvlan-контейнерами (нужен sub-interface), исчерпание MAC-адресов

Ipvlan

Современная альтернатива macvlan — контейнеры получают IP, но используют MAC-адрес хоста.

docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  -o parent=eth0 \
  -o ipvlan_mode=l3 \
  my-ipvlan
  • L2 mode: контейнеры в том же broadcast-домене
  • L3 mode: маршрутизация между подсетями, нет broadcast-трафика
  • Плюсы: выше плотность (один MAC на хост), хост может общаться с контейнерами

Управление сетями

docker network create --driver bridge mynet
docker network ls
docker network inspect mynet
docker network connect mynet container1
docker network disconnect mynet container1
docker network rm mynet

DNS и связь контейнеров

  • Контейнеры в одной сети видят друг друга по имени сервиса (Compose) или имени контейнера
  • Встроенный DNS-сервер (127.0.0.11) разрешает имена контейнеров
  • Пример: http://db:5432 — доступ к PostgreSQL
  • Кастомные DNS: --dns 8.8.8.8 или dns: 8.8.8.8 в Compose

8. Volumes и управление данными

Типы хранения данных

ТипОписаниеКогда использовать
VolumeУправляется Docker, хранится в /var/lib/docker/volumesБазы данных, постоянные данные, бекапы
Bind mountМонтирование директории хоста в контейнерРазработка (hot-reload), конфиги
tmpfsВременное хранение в RAMСекреты, временные файлы

Команды для volumes

docker volume create mydata
docker volume ls
docker volume inspect mydata
docker run -v mydata:/app/data nginx
docker run --mount type=bind,source=$(pwd),target=/app nginx
docker volume rm mydata
docker volume prune
Bind mount для разработки: монтируйте исходный код в контейнер — изменения на хосте сразу видны в контейнере без пересборки.

9. Docker Registry

Docker Hub

  • Публичный реестр образов (по умолчанию)
  • Официальные образы: python, node, nginx, postgres
  • Лимиты: 100 pull/6h (anonymous), 200 pull/6h (free account)

Private Registry

# Запуск локального registry
docker run -d -p 5000:5000 --name registry registry:2

# Тегирование и push
docker tag myapp:latest localhost:5000/myapp:latest
docker push localhost:5000/myapp:latest

# Pull с локального registry
docker pull localhost:5000/myapp:latest

Proxy Registry (Mirror)

Кэширующий proxy для Docker Hub — ускоряет pull'ы и снижает лимиты:

# /etc/docker/daemon.json
{
  "registry-mirrors": ["https://mirror.example.com"]
}

sudo systemctl restart docker

Популярные mirror'ы: Docker Hub mirror (Mirror) от провайдера, Nexus, Harbor, Sonatype Nexus.

Harbor

Enterprise-grade registry с открытым исходным кодом:

  • Security scanning: Trivy, Clair — автоматическое сканирование уязвимостей
  • Replication: синхронизация образов между registry (push/pull)
  • RBAC: управление доступом на уровне проектов и пользователей
  • Garbage Collection: очистка неиспользуемых слоёв
  • Web UI: управление образами через браузер
  • Helm Charts: хранение Helm-чартов
# Установка Harbor через Docker Compose
wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-online-installer-v2.10.0.tgz
tar xvf harbor-online-installer*.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml
./install.sh

Аутентификация

# docker login
docker login -u username
docker login ghcr.io -u username --password-stdin < token.txt

# Credential helpers (сохранение пароля безопасно)
docker-credential-pass  # через pass
docker-credential-secretservice  # через gnome-keyring
docker-credential-osxkeychain  # macOS Keychain

Альтернативные registry

  • GitHub Container Registry (ghcr.io) — интеграция с GitHub
  • GitLab Container Registry — встроенный в GitLab
  • AWS ECR — Amazon Elastic Container Registry
  • Harbor — enterprise registry с security scanning
  • Nexus — Sonatype Nexus Repository (multi-format)

10. Docker в CI/CD

GitHub Actions — пример пайплайна

name: Docker Build and Push
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: user/app:latest,user/app:${{ github.sha }}

Docker слои и кэширование в CI

  • Layer caching: порядок инструкций в Dockerfile важен — сначала COPY requirements.txt, потом RUN pip install (кэшируется)
  • GitHub Actions cache: docker/build-push-action автоматически кэширует слои
  • GitLab CI: cache: key: $CI_JOB_NAME + Docker-in-Docker

11. Docker Compose для тестирования

Docker идеально подходит для тестовых окружений: изолированно, повторяемо, быстро.

Пример: тестовый стек с Testcontainers

# tests/conftest.py
import pytest
import testcontainers.postgres
import testcontainers.redis

@pytest.fixture(scope="session")
def postgres():
    with testcontainers.postgres.PostgresContainer(
        "postgres:16-alpine"
    ) as pg:
        yield pg

@pytest.fixture(scope="session")
def redis():
    with testcontainers.redis.RedisContainer("redis:7-alpine") as r:
        yield r

Docker Compose для E2E-тестов

# compose.test.yml
services:
  app:
    build: ..
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16-alpine
    healthcheck:
      test: pg_isready -U test
  test-runner:
    build: ./tests
    depends_on:
      - app
    environment:
      - APP_URL=http://app:8000
    profiles: ["test"]  # запуск: docker compose --profile test up --abort-on-container-exit

Преимущества Docker для QA

  • Идентичное окружение на всех машинах (dev, CI, staging)
  • Быстрое создание и удаление тестовых стендов
  • Изоляция тестовых данных (чистая БД в контейнере)
  • Параллельные тесты (несколько инстансов сервиса)
  • Тестирование разных версий зависимостей (matrix testing)

12. Безопасность Docker

Docker Bench Security

docker run --it --net host --pid host --userns host \
  --cap-add audit_control -e DockerConfigFile=/etc/docker/daemon.json \
  -v /var/lib:/var/lib:ro -v /var/run/docker.sock:/var/run/docker.sock:ro \
  --label docker_bench_security \
  docker/docker-bench-security

Основные правила безопасности

ПравилоОписание
Не запускать от rootUSER appuser в Dockerfile, --user при запуске
Read-only rootfsdocker run --read-only container
Ограничение capabilities--cap-drop=ALL --cap-add=NET_BIND_SERVICE
Не использовать privileged--privileged даёт полный доступ к хосту
Security scanningdocker scout, Trivy, Snyk, Grype
Secrets не в образахDocker secrets, внешние vaults (HashiCorp Vault)
Resource limits--memory=512m --cpus=0.5
Не открывать docker.sockДоступ к сокету = полный контроль над хостом

Image Scanning

# Trivy (open-source)
trivy image python:3.12-slim

# Docker Scout (встроенный)
docker scout quickview python:3.12-slim
docker scout recommendations python:3.12-slim

SBOM (Software Bill of Materials)

Docker SBOM — детальный список всех пакетов внутри образа (с версиями и лицензиями):

# Создание SBOM
docker sbom python:3.12-slim

# Экспорт в разных форматах
docker sbom python:3.12-slim --format json > sbom.json
docker sbom python:3.12-slim --format spdx > sbom.spdx

# Сравнение SBOM двух образов
docker sbom python:3.12-slim > sbom1.json
docker sbom python:3.12-slim --diff sbom1.json

Подпись образов и аттестация

Цепочка поставки (supply chain) — проверка, что образ не был изменён:

# Docker Content Trust (DCT) — ручное включение
export DOCKER_CONTENT_TRUST=1
docker push user/app:latest  # образ автоматически подписывается

# Cosign (внешний инструмент)
cosign sign --key cosign.key user/app:latest
cosign verify --key cosign.pub user/app:latest

# SLSA attestation
docker buildx build --attest type=provenance,mode=max -t user/app:latest .
docker buildx imagetools inspect user/app:latest --format '{{ json .Provenance }}'

13. Оптимизация Docker-образов

Принципы оптимизации

  • Минимальный базовый образ: alpine, slim, distroless
  • Multi-stage builds: разделение build и runtime слоёв
  • Минимизация слоёв: объединение RUN команд (&&), чистка кэша
  • Порядок слоёв: часто меняющееся — в конце (кэширование)
  • .dockerignore: исключить node_modules, .git, __pycache__

Сравнение размеров Python-образов

ОбразРазмерОснова
python:3.12945 MBDebian Bookworm (полный)
python:3.12-slim114 MBDebian Slim (минимальный)
python:3.12-alpine71 MBAlpine Linux (musl)
distroless/python352 MBDistroless (только runtime)
Multi-stage + distroless~40 MBТолько артефакты

Distroless-образы

Google Distroless — минимальные образы, содержащие только приложение и его runtime-зависимости. Ни shell, ни менеджеров пакетов, ни лишних утилит.

# Пример distroless для Python (экспериментальный)
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM gcr.io/distroless/python3
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
USER nonroot
CMD ["main.py"]
  • Плюсы: минимальная поверхность атаки, маленький размер
  • Минусы: сложнее отладка (нет shell), не все языки хорошо поддерживают

Продвинутые техники

# BuildKit — используйте DOCKER_BUILDKIT=1 или export
# --squash (экспериментальный) — объединение всех слоёв в один
docker build --squash -t app:latest .

# --no-cache — игнорировать кэш слоёв (чистая сборка)
docker build --no-cache -t app:latest .

# Inline cache — кэширование слоёв в registry
docker buildx build --cache-from=user/app:cache --cache-to=type=inline -t user/app:latest .

# BuildKit cache mounts — кэш между сборками
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt

14. Оркестрация: Docker Swarm и Kubernetes

Docker Swarm

  • Встроенная оркестрация в Docker
  • Кластер из manager + worker нод
  • Сервисы, стеки, секреты, сети overlay
# Инициализация Swarm
docker swarm init --advertise-addr 192.168.1.10

# Деплой стека
docker stack deploy -c compose.yml myapp

# Просмотр сервисов
docker service ls
docker service ps myapp_web

# Масштабирование
docker service scale myapp_web=5

Kubernetes vs Docker Swarm

ХарактеристикаDocker SwarmKubernetes
СложностьНизкая (простой)Высокая (мощный, сложный)
УстановкаВстроен в DockerОтдельная (minikube, k3s, kind)
Auto-scalingРучноеАвтоматическое (HPA)
Self-healingБазовыйПродвинутый (liveness/readiness probes)
CommunityМаленькаяОгромная
Когда выбратьНебольшой кластер, простотаEnterprise, сложные приложения

15. Best Practices

Dockerfile

  • Используйте официальные образы (alpine/slim)
  • Объединяйте RUN команды: apt-get update && apt-get install -y pkg && rm -rf /var/lib/apt/lists/*
  • Не устанавливайте лишние пакеты
  • Используйте .dockerignore — аналог .gitignore
  • Добавляйте HEALTHCHECK
  • Указывайте конкретные версии тегов (не latest)

Compose

  • Используйте profiles для тестовых/фоновых сервисов
  • Настраивайте healthcheck для сервисов
  • Используйте restart policies: always, unless-stopped
  • Определяйте resource limits
  • Используйте .env файлы для переменных

CI/CD

  • Кэшируйте слои между сборками
  • Сканируйте образы на уязвимости
  • Используйте семантическое тегирование: v1.2.3, sha-abc123
  • Подписывайте образы (Docker Content Trust / Cosign)

16. Troubleshooting

Контейнер завершает работу сразу после запуска

docker logs <container>          # проверить вывод
docker inspect <container>       # посмотреть ExitCode, ошибки
docker run -it <image> sh        # проверить CMD/ENTRYPOINT вручную
  • Exit 0: CMD/ENTRYPOINT — короткая команда (ls, echo). Нужен процесс, который не завершается
  • Exit 127: команда не найдена — проверьте путь в CMD/ENTRYPOINT
  • Exit 137 (SIGKILL): OOM kill — превышен лимит памяти
  • Exit 139 (SIGSEGV): segmentation fault — проблема с приложением или архитектурой

Порт уже используется

sudo lsof -i :8080              # кто занял порт на хосте
docker ps                       # не занял ли другой контейнер
docker run -p 8081:80 nginx     # использовать другой порт хоста

Permission denied (доступ к volume)

  • Контейнер работает от root, файлы создаются с uid 0 — хост не может их читать
  • Решение: использовать USER appuser с совпадающим UID/GID хоста
  • Или: docker run --user $(id -u):$(id -g) — запуск от текущего пользователя
docker run --user 1000:1000 -v $(pwd)/data:/data alpine touch /data/test

Disk space / No space left on device

docker system df                 # сколько занимают образы, контейнеры, volumes
docker system prune -a --volumes # глобальная очистка
docker rm $(docker ps -aq)       # удалить все остановленные контейнеры
docker rmi $(docker images -q)   # удалить все неиспользуемые образы
Внимание: docker system prune -a --volumes удаляет все остановленные контейнеры, неиспользуемые образы и неиспользуемые volumes — безвозвратно.

Docker daemon не отвечает

sudo systemctl status docker     # статус демона
sudo systemctl restart docker    # перезапуск
sudo journalctl -u docker -n 50 # логи демона
docker info                      # проверить, что демон отвечает

DNS проблемы внутри контейнера

docker run alpine ping google.com            # проверить DNS
docker run --dns 8.8.8.8 alpine ping google.com  # принудительный DNS
# /etc/docker/daemon.json
# { "dns": ["8.8.8.8", "1.1.1.1"] }

Debug-инструменты

КомандаОписание
docker logs -f <container>Логи контейнера (follow)
docker exec -it <container> shShell внутрь контейнера
docker inspect <container>Подробная информация (JSON)
docker statsCPU/RAM/IO всех контейнеров
docker top <container>Процессы внутри контейнера
docker eventsСобытия демона в реальном времени
docker container diffИзменения в файловой системе контейнера

Restart policies

PolicyПоведение
noНе перезапускать (по умолчанию)
on-failure[:max-retries]Перезапуск только при ненулевом exit code
alwaysВсегда перезапускать (даже после docker stop → docker start)
unless-stoppedПерезапускать, если контейнер не был явно остановлен

17. Resource Limits

Ограничение памяти

# --memory: жёсткий лимит (контейнер будет убит при превышении)
docker run --memory=512m nginx

# --memory-swap: общий лимит память + swap (по умолч. = memory*2)
docker run --memory=512m --memory-swap=768m nginx

# --memory-reservation: мягкий лимит (не гарантируется)
docker run --memory=512m --memory-reservation=256m nginx
  • При превышении --memory контейнер получает OOM kill (Exit 137)
  • --memory-swap=-1 — неограниченный swap (опасно для хоста)
  • --memory-swap должен быть больше или равен --memory

Ограничение CPU

# --cpus: количество ядер CPU (дробное)
docker run --cpus=1.5 nginx        # полтора ядра максимум

# --cpuset-cpus: привязка к конкретным ядрам
docker run --cpuset-cpus="0,2" nginx  # только ядра 0 и 2

# --cpu-shares: относительный вес (по умолч. 1024)
docker run --cpu-shares=512 nginx  # половина от "стандартного"
  • --cpus — предпочтительный способ (работает через CFS scheduler)
  • --cpuset-cpus — для latency-critical приложений
  • --cpu-shares — только при конкуренции за CPU

Другие ограничения

# --ulimit: лимиты ядра (nofile, nproc, nofile)
docker run --ulimit nofile=1024:2048 nginx

# --device-read-bps / --device-write-bps: I/O чтения/записи
docker run --device-read-bps /dev/sda:1mb nginx

# --device-read-iops / --device-write-iops: I/O operations
docker run --device-write-iops /dev/sda:100 nginx

Resource limits в Compose

services:
  web:
    image: nginx
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: "256M"
        reservations:
          cpus: "0.25"
          memory: "128M"

Мониторинг ресурсов

docker stats              # live-статистика всех контейнеров
docker stats --no-stream  # однократный срез
docker inspect <container> | jq '.[].HostConfig.Memory' # лимит памяти

18. Docker в разработке

Bind mounts для hot-reload

Монтируйте исходный код в контейнер — изменения на хосте сразу видны внутри контейнера, без пересборки образа:

# Python (FastAPI + uvicorn с --reload)
docker run -v $(pwd):/app -p 8000:8000 \
  -e PYTHONDONTWRITEBYTECODE=1 \
  python:3.12-slim uvicorn main:app --reload --host 0.0.0.0

# Node.js (nodemon)
docker run -v $(pwd):/app -p 3000:3000 node:20 \
  npx nodemon server.js

Docker Compose для разработки

# compose.dev.yml — переопределение для разработки
services:
  web:
    build: .
    volumes:
      - .:/app          # bind mount для hot-reload
    environment:
      - DEBUG=true
      - PYTHONDONTWRITEBYTECODE=1
    command: uvicorn main:app --reload --host 0.0.0.0

# Запуск: docker compose -f compose.yml -f compose.dev.yml up

docker compose watch (hot-reload)

# compose.yml
services:
  web:
    build: .
    develop:
      watch:
        - path: ./src
          action: sync
          target: /app/src
        - path: ./requirements.txt
          action: rebuild

# В терминале
docker compose watch

Docker автоматически синхронизирует изменённые файлы (sync) или пересобирает образ (rebuild).

DevContainers

DevContainers — запуск VS Code / JetBrains внутри контейнера. Весь инструментарий (расширения, компиляторы, БД) — в контейнере, не на хосте.

# .devcontainer/devcontainer.json
{
  "name": "Python Dev",
  "image": "mcr.microsoft.com/devcontainers/python:3.12",
  "features": {
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },
  "customizations": {
    "vscode": {
      "extensions": ["ms-python.python"]
    }
  },
  "postCreateCommand": "pip install -r requirements.txt"
}

Практичные советы для разработки

  • .dockerignore — исключите .git, __pycache__, .env, .venv для быстрой сборки
  • .env файл — храните переменные окружения отдельно от Compose-файла
  • docker compose config — проверка итоговой конфигурации (объединяет все compose-файлы)
  • docker compose run --rm test — разовый запуск сервиса (например, тестов)
  • docker compose up --scale web=3 — масштабирование для локального тестирования

19. Мониторинг и логирование

Драйверы логирования

Docker поддерживает несколько драйверов для вывода логов:

ДрайверОписаниеКогда использовать
json-fileЛоги в JSON-файлах (по умолчанию)Локальная разработка
journaldЛоги в systemd journalLinux-серверы с systemd
syslogЛоги в syslogЦентрализованный syslog-сервер
fluentdЛоги в FluentdЦентрализованный сбор логов
lokiЛоги в Grafana LokiGrafana стек, cloud-native
awslogsЛоги в AWS CloudWatchAWS-инфраструктура
gelfGraylog Extended Log FormatGraylog-сервер
splunkЛоги в SplunkEnterprise Splunk
# Глобальная настройка драйвера
# /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

# Настройка для конкретного контейнера
docker run --log-driver loki --log-opt loki-url=http://loki:3100 nginx

Мониторинг с cAdvisor

cAdvisor (Container Advisor) — сбор и визуализация метрик контейнеров:

docker run --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:rw \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  --device=/dev/kmsg \
  gcr.io/cadvisor/cadvisor
cAdvisor предоставляет Web UI на порту 8080 — графики CPU, RAM, сети, файловой системы для каждого контейнера.

Prometheus + Grafana

# docker-compose.yml для мониторинг-стека
services:
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    depends_on:
      - prometheus
# prometheus.yml — сбор метрик cAdvisor
scrape_configs:
  - job_name: "cadvisor"
    static_configs:
      - targets: ["cadvisor:8080"]

Healthcheck — глубокое погружение

# Dockerfile
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:8000/health || exit 1

# docker run
docker run --health-cmd="curl -f http://localhost/health" \
  --health-interval=10s \
  --health-retries=3 \
  nginx
  • interval: как часто проверять (по умолч. 30s)
  • timeout: таймаут выполнения проверки (по умолч. 30s)
  • start-period: задержка перед первой проверкой (для инициализации)
  • retries: количество провалов до статуса unhealthy (по умолч. 3)
  • Статус: startinghealthy / unhealthy — видно в docker ps и docker inspect

20. Базы данных в Docker

PostgreSQL

# Запуск PostgreSQL
docker run -d --name pg \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=app \
  -p 5432:5432 \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16-alpine

# Подключение
docker exec -it pg psql -U postgres -d app

# pg_isready (healthcheck)
docker run --rm postgres:16-alpine pg_isready -h host.docker.internal

MySQL / MariaDB

docker run -d --name mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=app \
  -p 3306:3306 \
  -v mysqldata:/var/lib/mysql \
  mysql:8.4

# Подключение
docker exec -it mysql mysql -u root -p
Персистентность: всегда используйте named volumes (-v pgdata:/var/lib/...), а не bind mounts. Docker управляет правами доступа к volume, а bind mount может вызвать ошибки прав.

Backup и Restore

# Backup PostgreSQL
docker exec -t pg pg_dump -U postgres app > backup.sql

# Restore PostgreSQL
docker exec -i pg psql -U postgres -d app < backup.sql

# Backup MySQL
docker exec -t mysql mysqldump -u root -psecret app > backup.sql

# Restore MySQL
docker exec -i mysql mysql -u root -psecret app < backup.sql

# Автоматический backup (cron + скрипт)
docker exec -t pg pg_dump -U postgres app | gzip > backup_$(date +%Y%m%d).sql.gz

Multi-container DB setups

# compose.yml — PostgreSQL + Redis + Adminer
services:
  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: pg_isready -U postgres
      interval: 5s

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data
    healthcheck:
      test: redis-cli ping

  adminer:
    image: adminer
    ports:
      - "8080:8080"
    depends_on:
      - db

volumes:
  pgdata:
  redisdata:

Миграции БД

Запуск миграций как отдельного сервиса в Compose:

# compose.yml
services:
  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data

  migrate:
    build: ./migrations
    depends_on:
      db:
        condition: service_healthy
    environment:
      DATABASE_URL: postgresql://postgres:secret@db:5432/app
    profiles: ["migrate"]
    # Запуск: docker compose --profile migrate run --rm migrate

volumes:
  pgdata:

21. Rootless Mode

Что такое Rootless Docker

Docker в rootless-режиме запускает демон и контейнеры от обычного пользователя (без root-привилегий). Все операции выполняются в user namespace — даже если атакующий получит доступ к контейнеру, он не сможет повысить привилегии до root на хосте.

Установка rootless Docker

# Установка (не требует sudo)
curl -fsSL https://get.docker.com/rootless | sh

# Настройка окружения (добавить в ~/.bashrc)
export PATH=/home/user/bin:$PATH
export DOCKER_HOST=unix:///run/user/$UID/docker.sock

# Проверка
dockerd-rootless-setuptool.sh install
docker info --format '{{.SecurityOptions}}'  # должно быть "name=rootless"

Ограничения rootless mode

ФичаСтатус
Запуск контейнеровДа
docker build, pull, pushДа
Docker ComposeДа
Port mapping (-p)Да (только порты > 1024 без root)
Bind mountsДа
VolumesДа
Overlay networkЧастично (через slirp4netns)
--privilegedНет
Host networkНет
Ports < 1024Нет (без доп. настроек)
cAdvisor / мониторингОграничен

Когда использовать

Рекомендуется для: разработки на shared-серверах, CI-раннеры, multi-tenant окружения, любой сценарий, где у вас нет root-доступа к хосту.
Для продакшена: rootless mode всё ещё имеет ограничения по производительности сети (slirp4netns). Для production-нагрузок рекомендуется rootful Docker с дополнительными мерами безопасности (SELinux, AppArmor, seccomp).

Безопасность rootless vs rootful

АспектRootfulRootless
User namespaceОтключён по умолчанию (--userns-remap для включения)Включён всегда
Доступ к docker.sockПолный root на хостеТолько от пользователя
Escape из контейнераВозможен (CVE-2019-5736 и др.)Сильно затруднён
Производительность сетиНативная (iptables)slirp4netns (5-10% overhead)
Простота настройкиПростаяТребует настройки окружения

22. Глоссарий Docker-терминов

ТерминОпределение
ContainerЗапущенный экземпляр образа, изолированный процесс
ImageНеизменяемый шаблон для создания контейнеров (read-only)
LayerСлой образа — результат выполнения одной инструкции Dockerfile
DockerfileНабор инструкций для сборки образа
RegistryХранилище образов (Docker Hub, ghcr.io)
VolumeПостоянное хранение данных, управляемое Docker
Bind mountМонтирование директории хоста в контейнер
tmpfsВременное хранение в RAM (теряется при остановке)
Docker ComposeИнструмент для запуска многоконтейнерных приложений
SwarmРежим кластеризации Docker'а
ServiceОписание приложения в Swarm (образ, порты, реплики)
StackГруппа сервисов в Swarm (из compose.yml)
NamespaceИзоляция процессов в Linux (PID, NET, MNT, USER)
CgroupsОграничение ресурсов (CPU, RAM, IO)
Overlay networkСеть между хостами в Swarm
Multi-stage buildНесколько стадий сборки для минимизации финального образа
Docker ScoutИнструмент анализа уязвимостей образов
Docker SBOMSoftware Bill of Materials — список всех пакетов в образе
HealthcheckПроверка здоровья контейнера (liveness probe)
CapabilityПривилегия Linux-процесса (CAP_NET_BIND_SERVICE)
Docker socketUnix-socket /var/run/docker.sock — API Docker daemon
EntrypointКоманда, запускаемая при старте контейнера (не переопределяется)
CMDАргументы по умолчанию для ENTRYPOINT (переопределяется при run)
BuildKitСовременный движок сборки Docker (DOCKER_BUILDKIT=1)
Rootless modeЗапуск Docker демона без root-привилегий
DistrolessМинимальные образы без shell и пакетного менеджера
CosignИнструмент для подписи контейнерных образов
SLSASupply-chain Levels for Software Artifacts — фреймворк безопасности
OOM KillЗавершение контейнера при превышении лимита памяти (Exit 137)

23. Чеклист Docker

Dockerfile

  • Используется минимальный базовый образ (slim/alpine/distroless)
  • Multi-stage build для отделения build от runtime
  • Команды объединены (&&), кэш apt/pip очищен
  • Порядок слоёв оптимизирован для кэширования
  • .dockerignore добавлен
  • HEALTHCHECK настроен
  • USER не root
  • Используется BuildKit (DOCKER_BUILDKIT=1)
  • Образ просканирован на уязвимости (Trivy / Scout)

Compose

  • Сервисы имеют resource limits
  • restart policy настроена
  • healthcheck для зависимых сервисов
  • Profiles для тестовых/фоновых сервисов
  • .env файл для переменных
  • Используются named volumes (не bind mount в проде)
  • Compose watch настроен для разработки
  • docker compose config проверен

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

  • Не используется —privileged
  • Capabilities ограничены (—cap-drop=ALL)
  • Secrets не встроены в образ
  • Image scanning: Trivy / Docker Scout пройден
  • Read-only rootfs (—read-only)
  • Не открыт docker.sock
  • SBOM создан для production-образов
  • Образы подписаны (Cosign / Docker Content Trust)
  • Rootless mode рассмотрен для multi-tenant окружений

CI/CD

  • Сборка образов автоматизирована
  • Layer caching настроен
  • Образы сканируются перед push
  • Теги: версия + sha (не latest)
  • Registry аутентификация через secrets
  • Аттестация (provenance) включена в сборку

QA и тестирование

  • compose.test.yml для тестового стека
  • Testcontainers для unit/integration тестов
  • Тестовые данные изолированы (чистая БД)
  • Parallel test execution
  • Smoke-тесты после деплоя

Производительность и мониторинг

  • Resource limits настроены для всех сервисов
  • Драйвер логирования настроен (json-file с ротацией или внешний)
  • cAdvisor / Prometheus развёрнуты для мониторинга
  • БД имеют backup-стратегию
  • Docker system prune запускается регулярно
Золотое правило Docker: Контейнер должен быть эфемерным (ephemeral) — его можно остановить, удалить и создать заново без потери данных и функциональности.

Плейбук подготовлен для проекта qasdet.github.io • 2026