Материал

Docker

Этап roadmapProduction basics →

Docker — это платформа для контейнеризации, которая позволяет упаковывать приложение со всеми его зависимостями в стандартизированный блок (контейнер) для разработки, доставки и запуска.

Основные преимущества:

  • Одинаковое окружение на всех машинах
  • Изоляция приложений друг от друга
  • Быстрый запуск и остановка
  • Экономия ресурсов по сравнению с VM
  • Простота масштабирования

Структура Docker

Dockerfile → Image → Container

Ключевые компоненты

  • Dockerfile: инструкции для сборки образа
  • Image: шаблон для создания контейнера
  • Container: запущенный экземпляр образа
  • Registry: хранилище образов (например, Docker Hub)

Dockerfile — текстовый файл с инструкциями сборки Docker-образа. Инструкции выполняются сборщиком в изолированных build-контейнерах и формируют слои образа; это не тот же контейнер, который позже запускается в production.

Вот пример простого Dockerfile и объяснение основных команд:

# Используем базовый образ
FROM ubuntu:20.04

# Устанавливаем необходимые пакеты
RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip

# Создаем рабочий каталог
WORKDIR /app

# Копируем файлы в контейнер
COPY . /app

# Устанавливаем зависимости Python
RUN pip3 install -r requirements.txt

# Определяем переменные среды
ENV APP_PORT=8000

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

# Команда, которая будет выполнена при запуске контейнера
CMD ["python3", "app.py"]
  • FROM: Указывает базовый образ, на основе которого строится новый образ.
  • RUN: Выполняет команды внутри образа в процессе построения. В данном случае, обновляется список пакетов и устанавливаются Python и pip.
  • WORKDIR: Устанавливает рабочий каталог для следующих инструкций.
  • COPY: Копирует файлы из build context в файловую систему образа.
  • RUN: Устанавливает зависимости Python из файла requirements.txt.
  • ENV: Определяет переменные среды.
  • EXPOSE: Документирует, какой порт слушает приложение. Инструкция не публикует порт на хосте; для этого используют docker run -p или настройку ports в Compose.
  • CMD: Задает команду, которая будет выполнена при запуске контейнера.

Multistage docker:

Multi-stage build — способ использовать несколько стадий FROM в одном Dockerfile. Из build-стадии в финальную копируют только необходимые артефакты, не включая компиляторы и другие временные зависимости.

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

# syntax=docker/dockerfile:1

FROM alpine:latest AS builder
RUN apk --no-cache add build-base

FROM builder AS build1
COPY source1.cpp source.cpp
RUN g++ -o /binary source.cpp

FROM builder AS build2
COPY source2.cpp source.cpp
RUN g++ -o /binary source.cpp

# docker build --target build1 .

Практические примеры использования

Запуск простого веб-приложения

# Dockerfile
FROM python:3.13-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
EXPOSE 8000

CMD ["python", "app.py"]
# Сборка и запуск
docker build -t myapp .
docker run -p 8000:8000 myapp

Разработка с базой данных

Используем Docker Compose v2, который запускается как docker compose. Старый отдельный бинарник docker-compose относится к Compose v1.

# compose.yaml
services:
  web:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - .:/app
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: example
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 10

volumes:
  postgres_data:

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

  1. Volumes: постоянное хранилище, создаваемое и управляемое Docker
docker volume create mydata
docker run -v mydata:/data myapp
  1. Bind Mounts: прямая привязка к хост-системе
docker run -v /host/path:/container/path myapp
  1. tmpfs: временное хранилище в памяти (только Linux)
docker run --tmpfs /tmp myapp

Сети в Docker

  • bridge: (по умолчанию) для контейнеров на одном хосте
  • host: использует сеть хоста
  • none: без сети
  • overlay: соединяет контейнеры на разных Docker-хостах, участвующих в Swarm mode
# Создание сети
docker network create mynetwork

# Подключение контейнера к сети
docker run --network mynetwork myapp

Оптимизация образов

Используйте multi-stage builds

# Этап сборки
FROM node:16 AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build

# Финальный этап
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

Минимизируйте слои

# Плохо
RUN apt-get update
RUN apt-get install -y package1
RUN apt-get install -y package2

# Хорошо
RUN apt-get update && apt-get install -y \\
    package1 \\
    package2

Типичные сценарии использования

Локальная разработка

# Запуск окружения разработки
docker compose up -d

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

# Перезапуск сервиса после изменений
docker compose restart web

Отладка

# Подключение к работающему контейнеру
docker exec -it container_id bash

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

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

Часто используемые команды

# Управление контейнерами
docker ps             # Список запущенных контейнеров
docker ps -a          # Все контейнеры
docker start/stop     # Запуск/остановка контейнера
docker rm             # Удаление контейнера

# Управление образами
docker images         # Список образов
docker pull          # Загрузка образа
docker build         # Сборка образа
docker rmi           # Удаление образа

# Работа с Docker Compose
docker compose up    # Запуск сервисов
docker compose down  # Остановка и удаление сервисов
docker compose logs  # Просмотр логов

Docker compose

Docker Compose — инструмент для определения и запуска многоконтейнерных приложений. В YAML-файле описывают сервисы, сети, volumes, конфигурацию сборки и другие параметры, а CLI управляет жизненным циклом приложения.

Основные концепции Docker Compose Docker Compose упрощает разработку и тестирование приложений, особенно в контексте многоконтейнерных сценариев, где несколько сервисов должны взаимодействовать друг с другом.

  1. Файл конфигурации (compose.yaml): Docker Compose использует YAML-файл для определения настроек и параметров каждого сервиса в многоконтейнерном приложении. В этом файле можно указать образы контейнеров, порты, сети, volumes, переменные окружения и другие настройки. Пример файла compose.yaml:
services:
  web:
    image: nginx:1.28
    ports:
      - "8080:80"
  db:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: example
  1. Сервисы: Каждый сервис в многоконтейнерном приложении определяется как отдельный блок в файле конфигурации. Сервисы могут взаимодействовать друг с другом посредством сетевых соединений.
  2. Команды CLI: Docker Compose предоставляет команды docker compose up, docker compose down, docker compose ps и другие.
  3. Сети и объемы: Docker Compose позволяет определять сети и объемы для обеспечения связи и хранения данных между контейнерами.

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

docker run :

Запускает новый контейнер из образа.

docker run -it ubuntu:latest /bin/bash

docker ps:

Отображает список запущенных контейнеров.

docker ps

docker images:

Показывает список загруженных образов.

docker images

docker build:

Строит образ из Dockerfile.

docker build -t my_image:latest .

docker stop:

Останавливает работу одного или нескольких контейнеров.

docker stop container_id

docker rm:

Удаляет один или несколько контейнеров.

docker rm container_id

docker rmi:

Удаляет один или несколько образов.

docker rmi image_id

docker exec:

Запускает команду внутри запущенного контейнера.

docker exec -it container_id /bin/bash

docker compose up:

Запускает приложение согласно настройкам в файле compose.yaml.

docker compose up

docker network ls:

Отображает список сетей Docker.

docker network ls

docker pull:

Загружает образ из Docker Hub или другого репозитория.

docker pull nginx:latest

docker logs:

Просматривает вывод журналов контейнера.

docker logs container_id

docker inspect:

Возвращает подробную информацию о контейнере, образе, сети или томе.

docker inspect container_id

docker compose down:

Останавливает и удаляет контейнеры и сети проекта. Volumes удаляются только с флагом --volumes, а external-ресурсы не удаляются.

docker compose down

docker ps -a:

Отображает список всех контейнеров, включая остановленные.

docker ps -a

docker compose build:

Строит образы, определённые в файле compose.yaml.

docker compose build

docker exec -it:

Запускает интерактивную оболочку внутри контейнера.

docker exec -it container_id /bin/sh

docker compose logs:

Просматривает вывод журналов сервисов из compose.yaml.

docker compose logs

docker volume ls:

Отображает список созданных Docker-томов.

docker volume ls

docker compose ps:

Отображает статус сервисов, определённых в файле compose.yaml.

docker compose ps

Что могут спросить (теория)

Как создать образ Docker?

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

Что такое Docker и для чего он используется?

Docker — платформа для контейнеризации приложений. Контейнеры изолируют процессы и делают окружение переносимым между совместимыми ОС и архитектурами; при этом они разделяют ядро хоста. Используется для доставки и развертывания программного решения на разных устройствах, упрощая эту задачу.

Что такое Docker Compose и как он упрощает развертывание многоконтейнерных приложений?

Docker Compose - инструмент для определения и управления многоконтейнерных приложений через файл конфигурации YAML, что позволяет легко запускать и масштабировать связанные службы.

Как управлять сетями в Docker?

Docker предоставляет команды для создания и управления сетями, такие как docker network create и docker network connect, позволяя контейнерам взаимодействовать через изолированные сетевые пространства.

Что такое Docker Hub?

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

Что такое оркестрация контейнеров и какие инструменты вы знаете для неё?

Оркестрация контейнеров - это управление и развертывание контейнеров в крупномасштабных средах. Kubernetes, Docker Swarm и Amazon ECS - это примеры инструментов для оркестрации контейнеров.

Advanced вопросы

Как обеспечивается безопасность контейнеров в Docker?

Docker предоставляет namespaces, cgroups и capabilities для изоляции, но это не автоматическая гарантия безопасности. Нужны минимальные privileges/capabilities, непривилегированный пользователь, доверенные обновляемые образы, защита Docker socket и отказ от --privileged, если он не необходим.

Какие инструменты можно использовать для мониторинга Docker-контейнеров?

Для мониторинга Docker-контейнеров можно использовать инструменты, такие как Prometheus, Grafana, cAdvisor, которые предоставляют метрики и визуализацию состояния контейнеров.

Как Docker влияет на производительность приложения?

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

Вопросы на собеседовании: как построить честный ответ

Ниже — не готовая история, а варианты структуры ответа. Используйте только те пункты, которые соответствуют вашему реальному опыту: назовите контекст задачи, свои действия, ограничения и результат. Если с инструментом работала другая команда, прямо отделите её ответственность от своей.

Как вы решали проблемы сбоев в работе контейнеров?

Расскажите о конкретном сбое и последовательности диагностики: проверка статуса контейнера, docker logs, docker inspect, метрик, healthcheck, сети, volumes и лимитов ресурсов. Завершите ответ причиной сбоя и тем, как предотвратили повторение. Если такого случая не было, опишите знакомый вам порядок диагностики как теоретический алгоритм.

Какие типичные проблемы вы сталкивались при использовании Docker в проектах?

Выберите одну или две проблемы, с которыми действительно сталкивались: различия окружений, неверные переменные, права на volume, нехватка памяти, healthcheck или сеть. Например, внутри Compose приложение обращается к БД по имени сервиса и внутреннему порту, а с хоста — через опубликованный порт на localhost. Объясните, как нашли и исправили проблему.

Как вы масштабировали приложение, если работали с Kubernetes?

Опишите только свою зону ответственности. Например: «Deployment и Service поддерживала platform-команда, а я проверял логи Pod'ов, менял согласованные переменные окружения или тег образа и контролировал rollout». Если самостоятельно настраивали replicas, requests/limits, autoscaling или балансировку, назовите конкретные параметры и наблюдаемый результат. Не приписывайте себе настройку кластера, если ей занималась другая команда.

Как ответить, если с Kubernetes не работали?

Скажите об этом прямо и расскажите о ближайшем реальном опыте. Если масштабировали сервис без Kubernetes, можно описать профилирование, устранение узких мест, запуск дополнительных реплик и балансировку через Nginx. Если нагрузка оставалась небольшой, корректный ответ: «Горизонтальное масштабирование проекту не требовалось; я понимаю общий подход, но в production его не настраивал».

Как вы решали проблемы совместимости между окружениями разработки и продакшена при использовании Docker?

Назовите реальные меры, которые использовали: единый Dockerfile, Compose для локальных зависимостей, фиксированные версии образов, одинаковые команды запуска и проверка конфигурации в CI. Безопасный пример: в репозитории хранится только несекретный .env.example, а реальные .env и секреты передаёт среда развёртывания или secret manager.

Какие инструменты мониторинга и логирования Docker вы предпочитаете и почему?

Перечисляйте только инструменты, которыми пользовались лично, и поясняйте свою задачу. Например: Prometheus собирал метрики, Grafana показывала dashboards и alerts, а Elasticsearch/Logstash/Kibana использовались для поиска по логам. Если только читали готовые dashboards и логи, так и сформулируйте.

Как обновляли образы в production?

Если работали с Kubernetes, можно описать реальный rolling update Deployment: новый тег образа, постепенная замена Pod'ов, maxUnavailable/maxSurge, readiness probes, наблюдение за rollout и rollback при ошибке. Не называйте это canary deployment, если новая версия не получала отдельно ограниченную долю трафика. Если процесс обновления выполняла platform-команда, опишите только свои действия — например, подготовку образа и проверку приложения после выкладки.

Каков был ваш опыт в управлении конфигурациями и переменными окружения в контейнерах?

Расскажите, где в вашем проекте хранилась несекретная конфигурация, как передавались секреты, кто менял значения и как проверялись обязательные переменные при старте приложения. Не показывайте реальные секреты и не утверждайте, что использовали secret manager, если работали только с переменными окружения.

Какие преимущества вы заметили при использовании Docker в тестировании и развертывании приложений?

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

Какие были ваши подходы к оптимизации размера Docker-образов и уменьшению потребления ресурсов?

Выберите применявшиеся у вас приёмы и добавьте измеримый результат, если он есть: подходящий минимальный базовый образ, multi-stage build, .dockerignore, воспроизводимая установка зависимостей и удаление build-файлов из финального образа. Alpine подходит не всегда: для Python-пакетов с нативными зависимостями Debian slim может оказаться меньше итогового результата и проще в сборке. Не заявляйте конкретное уменьшение размера без замеров.

Официальные источники