Открыть сервис

Dockerfile

Dockerfile — это текстовый файл, содержащий набор инструкций для автоматической сборки образа контейнера в среде Docker. Файл определяет базовый образ, устанавливаемое программное обеспечение, настройки окружения, команды для запуска и другие параметры, необходимые для создания изолированного и воспроизводимого окружения для приложения.

Dockerfile является ключевым элементом концепции «инфраструктура как код» (Infrastructure as Code, IaC), позволяя разработчикам и системным администраторам описывать процесс развёртывания приложения в виде версионируемого, читаемого и многократно используемого файла. Каждая инструкция в Dockerfile создаёт новый слой (layer) в образе, что способствует эффективному кэшированию и ускорению повторных сборок.

История

Разработка Dockerfile неразрывно связана с появлением и эволюцией платформы Docker. Компания Docker, Inc. (основана в 2010 году) выпустила первую публичную версию Docker в 2013 году. С самого начала был предложен декларативный способ описания сборки образа, который впоследствии получил название Dockerfile. Первоначально формат был простым и включал всего несколько инструкций (FROM, RUN, CMD, EXPOSE). По мере роста популярности Docker и усложнения сценариев использования, набор инструкций расширялся: были добавлены ENV, COPY, ADD, ENTRYPOINT, VOLUME, WORKDIR и другие.

В 2015 году Dockerfile стал частью спецификации формата образов Open Container Initiative (OCI), что способствовало его стандартизации и совместимости с другими системами контейнеризации (например, Podman, containerd). В 2017 году Docker представил многоэтапную сборку (multi-stage builds), позволяющую создавать более компактные и безопасные образы, разделяя этапы компиляции и финальной сборки.

Структура и синтаксис

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

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

  • FROM — задаёт базовый образ, на основе которого строится новый образ. Это обязательная инструкция, с которой должен начинаться любой Dockerfile. Пример: FROM ubuntu:22.04 или FROM python:3.11-slim.
  • RUN — выполняет команду в текущем слое образа во время сборки. Используется для установки пакетов, создания пользователей, настройки окружения. Пример: RUN apt-get update && apt-get install -y nginx.
  • CMD — задаёт команду по умолчанию, которая будет выполняться при запуске контейнера. Может быть переопределена при запуске. В Dockerfile может быть только одна инструкция CMD. Пример: CMD ["nginx", "-g", "daemon off;"].
  • ENTRYPOINT — определяет исполняемый файл, который будет запущен при старте контейнера. В отличие от CMD, аргументы, переданные при запуске, добавляются к команде ENTRYPOINT. Часто используется вместе с CMD для передачи аргументов по умолчанию. Пример: ENTRYPOINT ["python"], CMD ["app.py"].
  • COPY — копирует файлы или директории из контекста сборки (обычно из директории, где находится Dockerfile) в файловую систему образа. Пример: COPY ./app /app.
  • ADD — аналогична COPY, но дополнительно поддерживает автоматическое извлечение архивов (tar, gzip) и загрузку файлов по URL. Использование ADD рекомендуется только при необходимости этих функций, в остальных случаях предпочтительнее COPY.
  • ENV — устанавливает переменные окружения, которые будут доступны в контейнере во время сборки и при его запуске. Пример: ENV NODE_ENV=production.
  • WORKDIR — устанавливает рабочую директорию для последующих инструкций RUN, CMD, ENTRYPOINT, COPY и ADD. Пример: WORKDIR /usr/src/app.
  • EXPOSE — информирует Docker о том, что контейнер будет слушать указанные сетевые порты во время выполнения. Эта инструкция носит информационный характер и не публикует порты автоматически. Пример: EXPOSE 80.
  • VOLUME — создаёт точку монтирования для внешнего тома (volume) или анонимного тома. Пример: VOLUME /data.
  • USER — задаёт имя пользователя или UID, от имени которого будут выполняться последующие инструкции RUN, CMD и ENTRYPOINT. Пример: USER appuser.
  • ARG — объявляет переменные, которые могут быть переданы в Dockerfile во время сборки с помощью флага --build-arg. Пример: ARG VERSION=latest.
  • LABEL — добавляет метаданные к образу в формате ключ-значение. Используется для организации, лицензирования, версионирования. Пример: LABEL maintainer="team@example.com".
  • SHELL — позволяет изменить командную оболочку, используемую для выполнения инструкций RUN. По умолчанию для Linux используется /bin/sh -c, для Windowscmd /S /C.
  • HEALTHCHECK — определяет команду для проверки состояния контейнера. Docker периодически выполняет эту команду и на основе её результата устанавливает статус контейнера (healthy, unhealthy). Пример: HEALTHCHECK --interval=30s CMD curl -f http://localhost/ || exit 1.
  • ONBUILD — добавляет триггерную инструкцию, которая выполняется при использовании данного образа в качестве базового в другом Dockerfile. Применяется для создания универсальных базовых образов.

Многоэтапная сборка (Multi-stage builds)

Многоэтапная сборка — это техника, позволяющая использовать несколько инструкций FROM в одном Dockerfile. Каждый FROM начинает новый этап сборки. Артефакты (файлы, бинарники) из предыдущих этапов могут быть скопированы в финальный этап с помощью инструкции COPY --from=<имя_этапа>. Это позволяет создавать образы, содержащие только необходимые для выполнения приложения файлы, без инструментов сборки, компиляторов и промежуточных файлов, что значительно уменьшает размер образа и повышает безопасность.

Пример: первый этап может использовать образ Go для компиляции бинарника, а второй этап — минимальный образ (например, alpine или scratch), в который копируется только скомпилированный бинарник.

Лучшие практики

При написании Dockerfile рекомендуется следовать ряду правил для обеспечения эффективности, безопасности и воспроизводимости:

  • Минимизация количества слоёв. Каждая инструкция RUN, COPY, ADD создаёт новый слой. Объединение команд в одной инструкции RUN (например, с помощью &&) уменьшает число слоёв.
  • Использование .dockerignore. Файл .dockerignore позволяет исключить из контекста сборки ненужные файлы (.git, node_modules, временные файлы), что ускоряет передачу контекста в демон Docker.
  • Выбор минимального базового образа. Использование образов на основе alpine или scratch (пустой образ) снижает размер финального образа и уменьшает поверхность атаки.
  • Кэширование слоёв. Инструкции, которые редко меняются (например, установка системных пакетов), следует размещать в начале Dockerfile, а часто меняющиеся (копирование исходного кода) — в конце. Это позволяет эффективно использовать кэш Docker и ускоряет сборку.
  • Запуск от непривилегированного пользователя. Создание и использование пользователя с ограниченными правами (инструкция USER) снижает риски безопасности при эксплуатации контейнера.
  • Явное указание версий базового образа. Использование конкретных тегов (например, python:3.11.4-slim) вместо latest обеспечивает воспроизводимость сборки.
  • Минимизация количества устанавливаемых пакетов. Установка только необходимых зависимостей уменьшает размер образа и потенциальные уязвимости.

Пример Dockerfile

Ниже приведён пример Dockerfile для простого веб-приложения на Python с использованием Flask:

```dockerfile

Используем официальный образ Python

FROM python:3.11-slim

Устанавливаем рабочую директорию

WORKDIR /app

Копируем файл с зависимостями

COPY requirements.txt .

Устанавливаем зависимости

RUN pip install --no-cache-dir -r requirements.txt

Копируем исходный код приложения

COPY . .

Указываем порт, который будет слушать приложение

EXPOSE 5000

Определяем команду для запуска приложения

CMD ["python", "app.py"] ```

Применение

Dockerfile является основным инструментом для создания образов контейнеров в экосистеме Docker. Он используется в различных сценариях:

  • Разработка и тестирование. Разработчики создают Dockerfile для локального запуска приложений в изолированном окружении, что гарантирует идентичность сред разработки, тестирования и эксплуатации.
  • Непрерывная интеграция и непрерывная доставка (CI/CD). В пайплайнах CI/CD (например, Jenkins, GitLab CI, GitHub Actions) Dockerfile используется для автоматической сборки образов, которые затем публикуются в реестре образов (Docker Hub, Amazon ECR, Google Container Registry, Яндекс Container Registry).
  • Микросервисная архитектура. Каждый микросервис обычно описывается собственным Dockerfile, что позволяет независимо собирать, тестировать и развёртывать компоненты системы.
  • Обучение и демонстрация. Dockerfile позволяет быстро развернуть сложные окружения для обучения или демонстрации продукта.

Критика и ограничения

Несмотря на широкое распространение, Dockerfile имеет определённые недостатки:

  • Декларативность, но не идемпотентность. Хотя Dockerfile описывает, что должно быть в образе, выполнение одной и той же инструкции RUN может давать разные результаты, если внешние источники (например, репозитории пакетов) изменились. Это может нарушить воспроизводимость сборки.
  • Отсутствие встроенного управления зависимостями. Dockerfile не предоставляет механизмов для разрешения конфликтов версий пакетов, что может приводить к ошибкам сборки.
  • Сложность отладки. При возникновении ошибки во время сборки (особенно на этапе RUN) бывает сложно определить точную причину, так как контекст выполнения внутри слоя ограничен.
  • Риск создания «толстых» образов. При неопытном использовании Dockerfile легко создать образ большого размера, содержащий множество неиспользуемых файлов и уязвимых компонентов.

Для преодоления некоторых ограничений Dockerfile были разработаны альтернативные инструменты, такие как BuildKit (встроенный в Docker, улучшающий производительность и безопасность сборки), Kaniko (сборка образов без привилегий), Podman (альтернативный движок контейнеризации, совместимый с Dockerfile) и Cloud Native Buildpacks (автоматическое определение и установка зависимостей).

Источники

  1. Docker Documentation — Dockerfile reference.
  2. Docker Documentation — Best practices for writing Dockerfiles.
  3. Open Container Initiative — OCI Image Format Specification.
  4. Книга: «Docker: практическое руководство для разработчиков и администраторов» (авторы: Адриан Моуэт, Джеймс Тернбулл).
  5. Статья: «Multi-stage builds» в официальной документации Docker.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →