Чем отличается CMD от ENTRYPOINT в DockerFile
В Dockerfile существуют две инструкции, которые определяют поведение контейнера при его запуске: CMD и ENTRYPOINT. Обе задают команду по умолчанию, которую выполняет контейнер, но у них разные цели, особенности и правила переопределения. Понимание различий между ними важно для точного управления поведением контейнеров.
🔹 CMD
Назначение:
Инструкция CMD задаёт команду по умолчанию, которая будет выполнена при запуске контейнера, если не указана другая команда в момент запуска через docker run.
Синтаксис:
Строковая форма:
<br/>CMD "echo Hello"
— интерпретируется shell'ом (/bin/sh -c).
Exec-форма (рекомендуется):
<br/>CMD \["echo", "Hello"\]
CMD с аргументами:
<br/>CMD \["nginx", "-g", "daemon off;"\]
Особенности:
Может быть переопределена при запуске контейнера:
docker run myimage ls -la
-
— в этом случае ls -la заменит CMD.
-
Может использоваться совместно с ENTRYPOINT для передачи аргументов по умолчанию (см. ниже).
🔹 ENTRYPOINT
Назначение:
Инструкция ENTRYPOINT задаёт основную неизменяемую команду, которую контейнер будет всегда запускать. Даже если пользователь укажет другие команды при запуске контейнера, они будут переданы как аргументы к ENTRYPOINT, а не заменят его.
Синтаксис:
Exec-форма (рекомендуется):
<br/>ENTRYPOINT \["python", "app.py"\]
Shell-форма (использует /bin/sh -c, не рекомендуется):
<br/>ENTRYPOINT "python app.py"
Особенности:
Команда, заданная ENTRYPOINT, не переопределяется обычными параметрами docker run, а дополняется:
<br/>docker run myimage arg1 arg2
— будет интерпретировано как:
<br/>python app.py arg1 arg2
Чтобы переопределить ENTRYPOINT, нужно использовать --entrypoint:
<br/>docker run --entrypoint ls myimage
🔸 Совместное использование ENTRYPOINT и CMD
Можно комбинировать ENTRYPOINT и CMD для задания неизменяемой команды и настраиваемых аргументов по умолчанию:
ENTRYPOINT \["python", "app.py"\]
CMD \["--port=8080"\]
В этом случае:
docker run myimage
\=> выполнит:
python app.py --port=8080
А если при запуске передать аргументы:
docker run myimage --debug
\=> выполнит:
python app.py --debug
— то есть CMD будет заменён.
🔍 Таблица сравнения
Характеристика | CMD | ENTRYPOINT |
---|---|---|
Назначение | Указывает команду по умолчанию | Указывает основную команду |
--- | --- | --- |
Переопределяется при docker run | Да | Нет (аргументы передаются) |
--- | --- | --- |
Рекомендуемый синтаксис | Exec-форма (["cmd", "arg"]) | Exec-форма (["cmd", "arg"]) |
--- | --- | --- |
Совместимость | Может использоваться с ENTRYPOINT | Может использовать CMD как аргументы |
--- | --- | --- |
Поведение при запуске | Заменяется аргументами командной строки | Сохраняется, аргументы добавляются |
--- | --- | --- |
Shell-поддержка | Есть (shell-форма) | Есть, но не рекомендуется |
--- | --- | --- |
🔧 Примеры
Пример 1: Только CMD
FROM ubuntu
CMD \["echo", "Hello from CMD"\]
docker run myimage # → echo Hello from CMD
docker run myimage ls -la # → ls -la (CMD заменяется)
Пример 2: Только ENTRYPOINT
FROM ubuntu
ENTRYPOINT \["echo", "Hello from ENTRYPOINT"\]
docker run myimage test # → echo Hello from ENTRYPOINT test
docker run myimage ls -la # → echo Hello from ENTRYPOINT ls -la
Пример 3: ENTRYPOINT + CMD
FROM ubuntu
ENTRYPOINT \["echo"\]
CMD \["Hello from CMD"\]
docker run myimage # → echo Hello from CMD
docker run myimage world # → echo world
⚠️ Частые ошибки
-
Shell-форма ENTRYPOINT: приводит к проблемам с сигналами и PID 1 — лучше использовать exec-форму.
-
CMD без ENTRYPOINT: легко забыть, что она переопределяется при docker run.
-
CMD и ENTRYPOINT в shell-форме одновременно: может вызвать нестабильное поведение.
🧠 Когда использовать ENTRYPOINT, а когда CMD
-
Используйте CMD, если хотите предоставить настраиваемую команду по умолчанию, которую пользователь может легко заменить.
-
Используйте ENTRYPOINT, если хотите, чтобы команда всегда выполнялась, а пользователь добавлял только аргументы.
-
Используйте оба вместе, чтобы сделать ENTRYPOINT основным действием, а CMD — конфигурируемыми аргументами по умолчанию.