Чем отличается 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
FROM ubuntu
CMD ["echo", "Hello, world!"]При запуске docker run <image> выведется Hello, world!. Но docker run <image> echo "Hello, Docker!" выведет Hello, Docker!, потому что CMD заменяется.
Только ENTRYPOINT
FROM ubuntu
ENTRYPOINT ["echo", "Hello,"]При запуске docker run <image> выведется Hello,. При docker run <image> Docker выведется Hello, Docker.
Комбинация ENTRYPOINT и CMD
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 и сигналами.
Похожие вопросы
- Расскажи об опыте работы93%
- Расскажите о текущем месте работы как проходит рядовой рабочий день какие задачи приходится решать86%
- Без какой инструкции не может существовать докер файл80%
- Что такое DevOps66%
- Какие задачи выполнял с использованием Terraform60%
- Чем отличает COPY от ADD60%
- Какой опыт работы с ansible46%
- Какие инструменты использовали46%