Введение

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

CMD против ENTRYPOINT

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

Что общего у CMD и ENTRYPOINT

  • Эта команда выполняется в течение docker run.
  • Вы можете переопределить команду, передав аргумент во время docker run.
  • CMD также может быть объявлен только один раз в каждом Dockerfile ENTRYPOINT. Если сделано несколько объявлений, последние CMD и ENTRYPOINT будут действительными.

Особенности CMD

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

Особенности ENTRYPOINT

  • ENTRYPOINT заставляет команду выполняться в течение docker run.
  • Аргумент во время docker run выполняется как аргумент ENTRYPOINT. В отличие от CMD, он не перезаписывается.

Пример командной строки

Запуск контейнера Docker с помощью CMD

Давайте узнаем подробности на реальном примере выполнения CMD. Ниже приведен простой пример файла Dockerfile, который выводит строку в командной строке.

FROM alpine
CMD ["echo", "Hello!"]

Сохраните Dockerfile и выполните следующую команду, чтобы создать его.

$ docker build -t test .

Если вы выполните построенный контейнер с помощью следующей команды, вы увидите, что выводится строка Hello!.

$ docker run --rm test
Hello!

С другой стороны, если вы выполните его со следующими параметрами, вы увидите, что выводится строка AAAAAA, а строка Hello! перезаписывается. Другими словами, можно понять, что описание команды CMD является просто значением по умолчанию и может быть перезаписано.

$ docker run --rm test echo "AAAAAA"
AAAAAA

Пример Docker ENTRYPOINT (форма Exec)

Запуск контейнера Docker с помощью ENTRYPOINT

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

FROM alpine
ENTRYPOINT ["echo", "Hello!"]

Сохраните Dockerfile таким же образом и выполните следующую команду для его сборки.

$ docker build -t test .

Если вы выполните построенный контейнер с помощью следующей команды, вы увидите, что строка символов Hello! выводится, как и в случае CMD.

$ docker run --rm test
Hello!

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

$ docker run --rm test echo "AAAAAA"
Hello! echo AAAAA

Перезаписать с опцией --entrypoint

С другой стороны, в ENTRYPOINT вы можете изменить инструкцию, используя опцию —entrypoint следующим образом.

docker run --entrypoint [COMMAND] [IMAGE] [OPTIONAL_VALUE]

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

$ docker run --rm --entrypoint sh test -c'echo "test"'
test

Пример Docker ENTRYPOINT (форма оболочки)

Тогда как насчет примера выполнения в форме оболочки даже с той же ENTRY POINT? Ниже приведен пример файла Dockerfile, в котором используется форма exec ENTRYPOINT, которая выводит строку символов в командной строке.

FROM alpine
ENTRYPOINT echo "Hello!"

Сохраните Dockerfile и выполните следующую команду, чтобы создать его.

$ docker build -t test .

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

$ docker run --rm test
Hello!

Теперь давайте выполним его со следующими параметрами, как в форме exec. В этом случае, в отличие от CMD и exec формы ENTRYPOINT, вы можете видеть, что аргумент не влияет на поведение. Другими словами, даже с одной и той же ENTRYPOINT поведение между формой exec и формой оболочки отличается, поэтому будьте осторожны.

$ docker run --rm test echo "AAAAAA"
Hello!

Перезаписать с опцией --entrypoint

Однако даже в форме оболочки вы можете изменить инструкцию, используя параметр --entrypoint, как показано ниже.

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

$ docker run --rm --entrypoint sh test -c'echo "test"'
test

Пример совместного использования CMD и ENTRYPOINT

Наконец, каково поведение при совместном использовании CMD и ENTRYPOINT? В итоге поведение выглядит следующим образом.

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

Давайте подтвердим это на примере реализации. Ниже приведен пример совместного использования ENTRYPOINT и CMD. В настоящее время обратите внимание, что и ENTRYPOINT, и CMD находятся в форме exec.

FROM alpine
ENTRYPOINT ["echo", "Hello,"]
CMD ["World"]

Как и прежде, выполните следующую команду для сборки.

$ docker build -t test .

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

$ docker run --rm test
Hello, World

Но что, если указать аргументы, как и раньше? В этом случае содержимое ENTRYPOINT не изменяется, как показано ниже, а содержимое CMD перезаписывается как есть.

$ docker run --rm test "Alice!"
Hello, Alice

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

Заключение

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

— -

Shisho Cloud защищает вашу инфраструктуру как код всего за несколько кликов.

Вы можете сохранить свою безопасность IaC бесплатно. Кредитная карта не требуется.

(Эта статья перепечатана со следующего URL: https://shisho.dev/blog/posts/docker-cmd-entrypoint/)