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 | Копировать + авто-распаковка архивов, URL | ADD 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 | Точка монтирования volume | VOLUME /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
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
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
Основные правила безопасности
| Правило | Описание |
|---|---|
| Не запускать от root | USER appuser в Dockerfile, --user при запуске |
| Read-only rootfs | docker run --read-only container |
| Ограничение capabilities | --cap-drop=ALL --cap-add=NET_BIND_SERVICE |
| Не использовать privileged | --privileged даёт полный доступ к хосту |
| Security scanning | docker 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.12 | 945 MB | Debian Bookworm (полный) |
python:3.12-slim | 114 MB | Debian Slim (минимальный) |
python:3.12-alpine | 71 MB | Alpine Linux (musl) |
distroless/python3 | 52 MB | Distroless (только 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 Swarm | Kubernetes |
|---|---|---|
| Сложность | Низкая (простой) | Высокая (мощный, сложный) |
| Установка | Встроен в 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> sh | Shell внутрь контейнера |
docker inspect <container> | Подробная информация (JSON) |
docker stats | CPU/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 journal | Linux-серверы с systemd |
syslog | Логи в syslog | Централизованный syslog-сервер |
fluentd | Логи в Fluentd | Централизованный сбор логов |
loki | Логи в Grafana Loki | Grafana стек, cloud-native |
awslogs | Логи в AWS CloudWatch | AWS-инфраструктура |
gelf | Graylog Extended Log Format | Graylog-сервер |
splunk | Логи в Splunk | Enterprise 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
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)
- Статус:
starting→healthy/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
-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 / мониторинг | Ограничен |
Когда использовать
Безопасность rootless vs rootful
| Аспект | Rootful | Rootless |
|---|---|---|
| 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 SBOM | Software Bill of Materials — список всех пакетов в образе |
| Healthcheck | Проверка здоровья контейнера (liveness probe) |
| Capability | Привилегия Linux-процесса (CAP_NET_BIND_SERVICE) |
| Docker socket | Unix-socket /var/run/docker.sock — API Docker daemon |
| Entrypoint | Команда, запускаемая при старте контейнера (не переопределяется) |
| CMD | Аргументы по умолчанию для ENTRYPOINT (переопределяется при run) |
| BuildKit | Современный движок сборки Docker (DOCKER_BUILDKIT=1) |
| Rootless mode | Запуск Docker демона без root-привилегий |
| Distroless | Минимальные образы без shell и пакетного менеджера |
| Cosign | Инструмент для подписи контейнерных образов |
| SLSA | Supply-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 запускается регулярно
Плейбук подготовлен для проекта qasdet.github.io • 2026