Использование инструкций Dockerfile ENTRYPOINT и CMD

Если вам когда-либо потребовалось выполнить одну или две команды в вашем контейнере Docker при запуске, этот учебник для вас. С использованием инструкций Dockerfile ENTRYPOINT и CMD вы можете запускать столько команд при запуске, сколько вам нужно.

В этом учебнике вы узнаете, как использовать инструкции ENTRYPOINT и CMD для выполнения команд при запуске в Dockerfile, а также поймете различия между ними.

Предварительные требования

Поскольку этот учебник предполагает практическую демонстрацию, убедитесь, что у вас есть следующее:

  • A Windows 10 PC – Windows 10 v10.0.19042 was used in this tutorial.
  • Docker Desktop – В этом учебнике используется Docker Desktop v3.3.1.

Создание Dockerfile

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

1. Во-первых, откройте PowerShell от имени администратора.

2. Создайте новую папку для хранения Dockerfile и всех связанных файлов, которые будут использоваться в этом руководстве, и перейдите в этот каталог. Это руководство использует ~/docker.

mkdir ~/docker
cd docker

3. Теперь создайте пустой текстовый файл с именем Dockerfile с помощью следующей команды.

cd > Dockerfile

Кроме того, вы можете создать Dockerfile с помощью следующей команды, если вы используете Linux или Mac OS.

touch Dockerfile

4. Наконец, добавьте следующее содержимое в файл Dockerfile

FROM ubuntu:20.04

Теперь у вас есть созданный в скором времени Dockerfile!

Создание образа Docker

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

Находясь в каталоге ~/docker, выполните следующую команду. Эта команда создает образ Docker с именем demo (-t demo) из Dockerfile в ~/docker, указывая текущий рабочий каталог (.).

docker build -t demo .
Building a Docker Image

Запуск контейнера Docker

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

Чтобы запустить контейнер Docker, вызовите команду run, чтобы создать записываемый контейнерный слой над образом Docker (demo). Приведенный ниже пример использует параметр -it для интерактивного подключения к контейнеру, чтобы вы могли увидеть пример вывода.

docker run -it demo
Running a Docker Container

Exec против Shell Form

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

Когда Docker выполняет команды, он может делать это непосредственно с помощью вызова exec или через оболочку контейнера (/bin/sh -c в Linux или cmd /S /C в Windows), называемую shell.

Вы заметите, что команды, выполненные с помощью exec, имеют инструкцию, за которой следуют исполняемые файлы для вызова, а затем один или несколько аргументов командной строки, как показано ниже.

ENTRYPOINT ["executables", "parameter1", "parameter2", ...]
CMD ["executables", "parameter1", "parameter2:, ...]

Написание команд в форме shell, с другой стороны, не требует оборачивания команд в квадратные скобки, как показано ниже.

ENTRYPOINT <command> "parameter1"
CMD <command> "parameter1"

Если вы не указываете аргумент для CMD, Docker всегда будет выполнять команду в форме exec, например, CMD <command>.

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

Выполнение команд запуска

Давайте теперь перейдем к сути этого учебного пособия и погрузимся в дело, пройдя несколько примеров выполнения команд запуска внутри Dockerfile с помощью инструкций ENTRYPOINT и CMD.

1. Откройте Dockerfile, который вы создали ранее, в вашем предпочтительном текстовом редакторе.

2. Скопируйте и вставьте пример содержимого Dockerfile в ваш Dockerfile, как показано ниже, и сохраните его.

Этот Dockerfile создает слой, используя образ ubuntu:20.04 в качестве базового образа. Затем он сообщает Docker вызвать команду echo, передавая ей аргумент Hello world как для инструкций Dockerfile CMD, так и ENTRYPOINT, используя форму exec и shell.

FROM ubuntu:20.04
# Инструкция CMD
CMD ["echo", "Hello world"] # Exec Form
CMD echo "Hello world"      # Shell Form
# Инструкция ENTRYPOINT
ENTRYPOINT ["echo", "Hello world"] # Exec Form
ENTRYPOINT echo "Hello world"      # Shell Form

3. Находясь в каталоге ~/docker, соберите новый образ, запустив docker build и назовите его demo. Введенная ниже команда маркирует образ как demo и ищет Dockerfile в текущем рабочем каталоге (.).

docker build -t demo .
Building a Docker image with docker build

4. Теперь запустите контейнер, используя образ, затем запустите контейнер Docker на основе созданного ранее образа Docker. Теперь вы увидите, что контейнер возвращает Hello world, который был передан в инструкции CMD в Dockerfile.

docker run -it demo
Running a Docker container with docker run

Использование переменных в Dockerfile

Иногда вы можете не знать точные аргументы командной строки заранее. Аргументы, которые вам нужно передать команде, доступны только во время выполнения. Вместо статического назначения аргументов команды вы можете захватывать и передавать эти аргументы командам с использованием переменных.

Вы можете использовать переменные Dockerfile только в форме shell. Docker не поддерживает переменные в командах, вызванных с использованием формы exec.

Откройте Dockerfile в вашем предпочтенном текстовом редакторе снова, замените все внутри следующей серией команд и сохраните.

Вы заметите, что на этот раз Dockerfile использует переменные среды и отображается с использованием ENV. В приведенном ниже примере Dockerfile определяет переменную среды с именем name со значением friend. После создания этой переменной среды на нее можно ссылаться с помощью $name.

Когда Docker запускает контейнер на основе этого Dockerfile, он вызывает команду echo и передает аргумент Welcome, friend.

FROM ubuntu:20.04
ENV name friend

CMD echo "Welcome, $name"
# или
## ENTRYPOINT echo "Добро пожаловать, $name"

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

Building a Docker Image (shellform) and Running a Docker Container

Комбинирование инструкций Dockerfile ENTRYPOINT и CMD

Большую часть времени вы будете вызывать команды запуска, либо в командной строке CMD, либо в инструкции ENTRYPOINT. В конце концов, вы можете вызывать столько команд, сколько захотите, используя каждый из этих методов. Однако вы также можете вызывать одну команду и “добавлять к ней” используя обе инструкции.

Основываясь на предыдущих примерах, возможно, у вас есть Dockerfile, который выглядит примерно как в следующем примере. Как есть, если вы создадите образ и запустите контейнер с этого образа, Docker вызовет команду echo и вернет Hello.

FROM ubuntu:20.04
ENTRYPOINT ["echo", "Hello"]

Возможно, у вас есть еще один аргумент, который вы хотели бы передать команде echo, но не сразу. Возможно, вы хотели бы сделать это позже в Dockerfile. Вызывая инструкцию CMD без команды, вы можете это сделать.

Когда вы указываете команду для выполнения с помощью инструкции ENTRYPOINT, за которой следует инструкция CMD, Docker автоматически предполагает, что переданное значение CMD является аргументом, а не командой.

Теперь добавьте ссылку на инструкцию CMD без команды, только с аргументом под названием world, как показано ниже.

FROM ubuntu:20.04
ENTRYPOINT ["echo", "Hello"]
CMD ["world"]

Совмещение инструкций должно всегда быть записано в виде exec-формы из-за ее “массивоподобного” поведения, при котором значения указываются индивидуально, разделенные запятыми, а не в одной строке.

После создания образа и запуска контейнера из образа вы увидите, что вместо двух строк вывода (Hello и world) Docker возвращает только одну, что означает выполнение только одной команды echo.

Building a Docker Image (demo3) and Running a Docker Container

Заключение

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

Можете ли вы представить себе сценарий, когда вы предпочли бы использовать CMD вместо ENTRYPOINT для выполнения команды запуска?

Source:
https://adamtheautomator.com/dockerfile-entrypoint/