Поиск по сайту:

Разница между CMD и ENTRYPOINT в образах Docker


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

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

Что такое точка входа?

Сначала мы рассмотрим ENTRYPOINT, так как он обрабатывается перед CMD при запуске нового контейнера. Точка входа образа определяет процесс, который будет запущен при запуске контейнера.

Docker по умолчанию устанавливает точку входа в /bin/sh -c. Это означает, что вы окажетесь в сеансе оболочки при запуске контейнера. Для многих контейнеров желательнее, чтобы по умолчанию запускался другой процесс. Вы хотите, чтобы безголовые сервисы сразу же запускали свою рабочую нагрузку.

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

ENTRYPOINT ["date"]

Контейнер, созданный с помощью этого Dockerfile, будет запускать команду date. Поскольку date не является долгоживущим процессом переднего плана, контейнер завершится сразу после этого.

Точки входа должны быть исполняемыми двоичными файлами или сценариями. Ваш контейнер не запустится, если вы укажете недопустимую точку входа. Если вы используете собственный скрипт, убедитесь, что для него установлен исполняемый бит. Вы можете добавить разрешения на выполнение, используя chmod +x my-script.sh.

Добавление команды (CMD)

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

ENTRYPOINT ["date"]
CMD ["+%A"]

В этом примере в контейнере работает date +%A. Аргумент +%A для date отображает текущий день недели (например, понедельник).

CMD предназначен для переопределения. docker run позволяет указать другую команду для отдельного экземпляра контейнера:

docker run my-image +%B

CMD по умолчанию будет заменено на +%B, в результате чего в контейнере будет отображаться название текущего месяца. Это работает, потому что точка входа изображения остается нетронутой. CMD всегда добавляется к ENTRYPOINT, поэтому последней командой становится date +%B.

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

Переопределение точки входа

Вы можете заставить Docker запустить образ, используя пользовательскую точку входа. Передайте флаг --entrypoint в docker run:

docker run --entrypoint /bin/sh my-image

Точка входа, определенная в образе контейнера, будет проигнорирована в пользу указанной вами команды. В нашем примере вместо команды date будет запущен сеанс оболочки.

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

Какой из них использовать?

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

Как пользователь изображения, вы обычно можете придерживаться переопределения CMD. docker run имеет прозрачную поддержку переопределения команд. Любые аргументы, указанные после имени изображения, будут интерпретироваться как строка CMD для контейнера.

Режимы точки входа: Shell или Exec

На самом деле Docker поддерживает две разные формы ENTRYPOINT: режим exec и режим оболочки. Режим Exec характеризуется использованием конструкции массива для указания параметров. В режиме оболочки команда указывается как одна строка.

# exec mode
ENTRYPOINT ["binary", "--param", "--another-param"]

# shell mode
ENTRYPOINT binary --param --another-param

Использование режима оболочки приводит к тому, что ваш двоичный файл выполняется как подпроцесс /bin/sh -c. Это дает вашей точке входа доступ к переменным среды, определенным оболочкой.

Однако у режима оболочки есть компромиссы. Вы не можете использовать CMD, чтобы пользователи не могли изменять настройки. Аргументы, переданные docker run, будут игнорироваться; ваш контейнер всегда будет использовать точку входа как есть.

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

ENTRYPOINT exec binary --param --another-param

Преимущества подхода Docker к точке входа

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

Установите двоичный файл CLI в качестве точки входа изображения. Это позволяет пользователям взаимодействовать, не повторяя двоичное имя в каждой команде.

Подумайте, упаковали ли мы приведенный выше Dockerfile как date:latest:

# default entrypoint (/bin/sh -c)
docker run date:latest date +%A

# with `date` as the entrypoint
docker run date:latest +%A`

Установка пользовательской точки входа сокращает количество команд и снижает количество повторений. Контейнер становится более специализированным, автоматически вызывая date. Это создает более дружественный интерфейс для ваших пользователей.

Краткое содержание

Инструкции Docker ENTRYPOINT и CMD — частый источник путаницы. Их имена маскируют их предназначение.

Используйте ENTRYPOINT, чтобы установить «команду», которая будет выполняться при запуске новых контейнеров. Вы можете определить аргументы по умолчанию, используя CMD. ENTRYPOINT и CMD объединяются вместе, чтобы создать окончательную командную строку контейнера.

Когда вы используете docker run, Docker заменяет CMD изображения по умолчанию указанными вами аргументами. Если вам нужно переопределить точку входа изображения, используйте флаг --entrypoint.