Работа с Dockerfile

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

Синтаксис Dockerfile близок к синтаксису конфигурационных файлов .ini. На каждую строчку приходится одна инструкция. Инструкции пишутся капсом, а их значения отделяются пробелом.

Dockerfile имеет следующую логику заполнения:

  1. Первой инструкцией всегда идёт FROM с указанием родительского образа. Например, FROM python:latest.
  2. Инструкция RUN может принимать конвейер команд Linux, чтобы не создавать лишние слои. Например, RUN apt-get update && apt-get install python3-pip -y && pip install --upgrade pip && pip install pipenv.
  3. Инструкция WORKDIR устанавливает рабочий каталог контейнера. Например, WORKDIR /usr/src/app/. Последующие команды RUN, CMD, ENTRYPOINT наследуют привязку WORKDIR.
  4. Завершающей инструкцией всегда идёт CMD. Например, CMD ["python", "web_interface.py"]. CMD наследует привязку к WORKDIR, поэтому web_interface.py будет запущен из папки /usr/src/app/.

Приведем пример несложного Dockerfile, и на его примере разберем логику взаимодействия инструкций между собой.

FROM python:latest
RUN apt-get update && apt-get install python3-pip -y && pip install --upgrade pip && pip install pipenv
RUN mkdir -p /usr/src/app/
WORKDIR /usr/src/app/
COPY . /usr/src/app/
EXPOSE 5000
RUN pip install --no-cache-dir -r requirements.txt
CMD ["python", "web_interface.py"]

Наш Dockerfile, как и положено, открывается инструкцией FROM с указанием родительского образа. Выбрать подходящий образ можно на hub.docker.com или с помощью команды docker search имя образа. Например, docker search python.

Далее следуют несколько команд RUN. Поскольку каждая инструкция создает новый слой — хорошей практикой считается писать конвейеры логически связанных команд в одной инструкции RUN. Например, мы поместили команды обновления пакетов apt, установку пакетного менеджера pip и его обновление в одну инструкцию. Для комбинирования команд используется логический оператор «И», обозначающийся как &&.

После серии инструкций RUN идет инструкция WORKDIR, которая устанавливает рабочую директорию контейнера. Все последующие команды, работающие с привязками к директории, такие как RUN, CMD, ENTRYPOINT будут выполняться исходя из установленной директории.

Далее идёт инструкция EXPOSE, которая выражает намерение открыть заданный порт. Инструкция сама по себе не открывает порт без применения команды docker run с ключом -P. Если нужно «повесить» контейнер на определённый внешний порт с переадресацией во внутренний порт контейнера — применяется ключ -p с указанием внутреннего и внешнего порта через «:». Например, docker run -p 5000:8080.

Предпоследней идет опять инструкция RUN. Мы уже рассматривали её выше, однако здесь она исполняется с зависимостью от WORKDIR. Инструкция WORKDIR в качестве рабочей директории установила /usr/src/app/, поэтому текущая инструкция RUN будет выполнять команду pip install --no-cache-dir -r requirements.txt из директории установленной инструкцией WORKDIR.

Завершающая инструкция в нашем Dockerfile — CMD с командой ["python", "web_interface.py"]. Опять же заметим, что здесь CMD связана с WORKDIR и скрипт web_interface.py будет выполнен из директории /usr/src/app/. Важно запомнить, что CMD всегда идет последней и должна быть в единственном экземпляре.

Приведем таблицу инструкций Dockerfile с примерами команд и опций:

Инструкция Описание Пример использования Комментарий
FROM Задает базовый образ. Все последующие инструкции создают слои поверх родительского образа. FROM python:latest
FROM debian:wheezy
Быстрее всего можно найти образ с нужным тегом на Docker hub.
RUN Выполняет команду внутри контейнера и сохраняет результат. RUN mkdir /usr/src/app/
RUN apt-get update && apt-get install python3-pip -y
RUN может исполнять конвейер команд с логическими операторами && и ||.
COPY Копирует файлы и папки из текущей директории, где находится пользователь в указанную директорию в контейнере COPY . /usr/src/app/ COPY считывает позицию пользователя на хосте, поэтому первым аргументом идет «.».
ADD Копирует файлы и папки из текущей позиции пользователя, скачивает файлы по URL и работает с tar-архивами. ADD https://1cloud.ru/archive/api_config.ini
/usr/src/app/
Официальная документация не рекомендует применять ADD. Для скачивания по URL можно использовать RUN с CURL или WGET, а для копирования — COPY.
CMD Выполняет команду с указанными аргументами во время запуска контейнера. CMD ["python", "web_interface.py"] CMD должна быть одна в конце Dockerfile. CMD может вызывать исполняемый файл — .sh
Аргументы docker run переопределяют CMD. Если в Dockerfile нет CMD, обязательно должна быть инструкция ENTRYPOINT.
ENTRYPOINT Похожа на CMD, но при запуске контейнера не переопределяется в отличие от CMD. ENTRYPOINT ["python", "web_interface.py"] ENTRYPOINT может использоваться совместно с CMD.
ENV Задает переменные среды внутри образа, на которые могут ссылаться другие инструкции. ENV ADMIN="ivan" ENV часто применяется для передачи информации в контейнеризированное приложение через переменные среды.
ARG Задает переменные, значение которых передается докером во время сборки образа. ARG maintainer=ivan В отличие от ENV-переменных, ARG-переменные недоступны во время выполнения контейнера.
WORKDIR Устанавливает рабочую директорию контейнера. WORKDIR /usr/src/app/ Последующие инструкции CMD, RUN, ENTRYPOINT наследуют привязку к директории установленной WORKDIR.
VOLUME Создает и подключает постоянный том хранения данных. VOLUME /data_cont_1 Просмотреть существующие тома можно командой docker volume ls. К контейнеру можно подключить существующий том, для этого достаточно указать уже существующий том.
EXPOSE Указывает планируемый рабочий порт у контейнера. Инструкция сама по себе не открывает порт. Чтобы использовался указанный в EXPOSE порт — нужно указать docker run -P при запуске контейнера. EXPOSE 5000 Если требуется пробросить и сопоставить разные порты внутри и снаружи контейнера используется docker run -p внутренний порт:внешний порт
LABEL Добавляет метаданные в образ. LABEL maintainer="katkov_ivan" Обычно LABEL содержит информацию об авторе образа.

Если вы интересуетесь Docker и контейнеризацией в целом, вам могут быть интересны следующие материалы:

Последнее обновление: 26.05.2023