Встречается на 66% собеседований по DevOps

Чем отличается CMD от ENTRYPOINT в DockerFile

CMD и ENTRYPOINT — это две инструкции Dockerfile, которые задают команду, выполняемую при запуске контейнера, но с разным поведением: CMD задает команду и аргументы по умолчанию, которые можно полностью переопределить при запуске, а ENTRYPOINT задает фиксированную команду, к которой добавляются аргументы из docker run. Понимание их различий важно для создания гибких и предсказуемых образов.

Как это работает

Когда Docker запускает контейнер, он выполняет команду, определенную в образе. Эта команда формируется из двух частей: ENTRYPOINT (исполняемый файл) и CMD (аргументы по умолчанию). Если в Dockerfile указан только CMD, он становится полной командой. Если указан только ENTRYPOINT, он выполняется без дополнительных аргументов, если только они не переданы при запуске.

При запуске контейнера с помощью docker run можно добавить аргументы после имени образа. Эти аргументы ведут себя по-разному в зависимости от наличия ENTRYPOINT и CMD:

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

Примеры

Только CMD

dockerfile
FROM ubuntu
CMD ["echo", "Hello, world!"]

При запуске docker run <image> выведется Hello, world!. Но docker run <image> echo "Hello, Docker!" выведет Hello, Docker!, потому что CMD заменяется.

Только ENTRYPOINT

dockerfile
FROM ubuntu
ENTRYPOINT ["echo", "Hello,"]

При запуске docker run <image> выведется Hello,. При docker run <image> Docker выведется Hello, Docker.

Комбинация ENTRYPOINT и CMD

dockerfile
FROM ubuntu
ENTRYPOINT ["echo", "Hello,"]
CMD ["world!"]

При запуске без аргументов выведется Hello, world!. При docker run <image> Docker выведется Hello, Docker, так как CMD заменяется, а ENTRYPOINT остается.

Подводные камни

  • Форма записи: Обе инструкции можно задавать в exec-форме (JSON-массив) или shell-форме (строка). Exec-форма предпочтительнее, так как она не запускает оболочку и корректно обрабатывает сигналы. Shell-форма (CMD echo hello) запускает команду через /bin/sh -c, что может привести к неожиданному поведению с PID 1.
  • Переопределение ENTRYPOINT: ENTRYPOINT можно переопределить при запуске с помощью флага --entrypoint в docker run, но это редкий случай. Обычно ENTRYPOINT считается фиксированным.
  • Использование в скриптах: Если ENTRYPOINT — это скрипт, он должен быть исполняемым и иметь shebang. Иначе контейнер упадет с ошибкой.
  • Наследование: Если в базовом образе уже заданы ENTRYPOINT или CMD, они наследуются, если не переопределены в дочернем Dockerfile. Это может привести к неожиданному поведению.

Когда использовать

  • Используйте CMD, когда нужно задать команду по умолчанию, которую пользователь может легко переопределить. Например, для образов с утилитами, где пользователь может захотеть выполнить другую команду.
  • Используйте ENTRYPOINT, когда образ должен вести себя как исполняемый файл, и пользователь должен передавать только аргументы. Например, для образов, которые запускают конкретный сервис или скрипт.
  • Часто комбинируют: ENTRYPOINT задает основной процесс, а CMD — аргументы по умолчанию, которые можно переопределить. Это дает гибкость и сохраняет предсказуемость.

Коротко

  • CMD — команда по умолчанию, заменяется аргументами из docker run.
  • ENTRYPOINT — фиксированная команда, аргументы из docker run добавляются к ней.
  • Комбинация ENTRYPOINT + CMD позволяет задать исполняемый файл и аргументы по умолчанию.
  • Используйте exec-форму (["cmd", "arg"]) для избежания проблем с PID 1 и сигналами.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы