Ответ
В Dockerfile инструкции CMD и ENTRYPOINT обе определяют команду, которая будет выполняться при запуске контейнера, но их назначение и поведение при переопределении существенно различаются.
CMD (Command)
Назначение:
- Предоставляет команду по умолчанию для исполняемого файла контейнера.
- Может предоставлять аргументы по умолчанию для
ENTRYPOINT. - Если в Dockerfile указано несколько
CMD, используется только последняя.
Поведение при запуске:
- Легко переопределяется при запуске контейнера, передав новую команду в
docker run <image> <новая_команда>. Это позволяет пользователю запускать произвольные команды внутри контейнера. - Если
ENTRYPOINTне указан,CMDопределяет основную команду, которая будет выполнена.
Пример:
FROM alpine
CMD ["echo", "Hello from CMD"]
- Запуск:
docker run <image>выведетHello from CMD. - Переопределение:
docker run <image> echo "Overridden CMD"выведетOverridden CMD.
Почему используется: Для задания команды по умолчанию, которая может быть легко изменена пользователем контейнера, например, для запуска интерактивной оболочки или выполнения скрипта.
ENTRYPOINT (Entrypoint)
Назначение:
- Определяет основную команду или исполняемый файл, который всегда будет запускаться при старте контейнера.
- Превращает образ в исполняемый файл, делая его похожим на обычную программу.
- Аргументы, переданные в
docker run, или команда изCMD(если она есть), добавляются как аргументы кENTRYPOINT.
Поведение при запуске:
- Не переопределяется напрямую аргументами
docker run. Аргументыdocker runстановятся параметрами дляENTRYPOINT. - Для переопределения
ENTRYPOINTнеобходимо явно использовать флаг--entrypointвdocker run.
Пример:
FROM alpine
ENTRYPOINT ["echo"]
CMD ["Hello from ENTRYPOINT"]
- Запуск:
docker run <image>выведетHello from ENTRYPOINT(CMD используется как аргумент для ENTRYPOINT). - Передача аргументов:
docker run <image> "New argument"выведетNew argument(CMD заменяется на "New argument"). - Переопределение ENTRYPOINT:
docker run --entrypoint "/bin/sh" <image>запустит/bin/shвнутри контейнера.
Почему используется: Для создания контейнера, который ведет себя как исполняемая программа (например, утилита командной строки или сервис), где ENTRYPOINT является этой программой, а CMD — ее аргументами по умолчанию.
Ключевое отличие:
CMDпредоставляет аргументы по умолчанию дляENTRYPOINTили команду по умолчанию, которую легко переопределить.ENTRYPOINTопределяет основной исполняемый файл контейнера, который не меняется, а принимаетCMDили аргументыdocker runкак свои параметры.
Ответ 18+ 🔞
А, ну вот, опять про эту парочку, CMD и ENTRYPOINT, блядь. Слушай, как будто про семейную пару какую-то, где один — упёртый, как валенок, а второй — тряпка, которую можно выкрутить как угодно. Ёпта, сейчас разложу по полочкам, чтобы даже мартышлюшка поняла.
CMD — это как предложение по умолчанию, которое всем похуй.
Представь, ты заходишь в кафе, а там меню. И на нём написано: «По умолчанию мы вам принесём кофе». Это и есть CMD. Но если ты, сука, такой умный и крикнешь: «Нет, мне чай!», то официант (читай — Docker) такой: «Окей, похуй, будет тебе чай». Он легко переписывается.
Вот смотри, пример, чтобы мозг не взорвался:
FROM alpine
CMD ["echo", "Hello from CMD"]
- Запускаешь просто образ:
docker run <image>— и тебе вежливо плюёт в консоль:Hello from CMD. - А если ты хитрая жопа и хочешь своё?
docker run <image> echo "Overridden CMD"— и всё, привет,Overridden CMD. CMD послан нахуй, делается то, что ты сказал.
Зачем это нужно? Ну, чтобы контейнер из коробки что-то делал, но любой распиздяй мог это перебить своей командой. Типа запустить /bin/sh вместо сервера и поковыряться внутри.
А теперь ENTRYPOINT — это уже не предложение, а приговор, блядь.
Это как если бы ты пришёл в ту же забегаловку, а тебе сразу вручают в руки ложку и сажают за миску с борщом. Ты можешь попросить добавить сметаны или чеснока (это будут аргументы), но саму миску борща тебе не поменять. Хочешь другую еду? Придётся орать на весь зал «Я ХОЧУ ПИЦЦУ!» (это флаг --entrypoint).
Смотри, как это выглядит в деле:
FROM alpine
ENTRYPOINT ["echo"]
CMD ["Hello from ENTRYPOINT"]
- Запускаешь образ:
docker run <image>.ENTRYPOINT— это командаecho, аCMD— её аргумент по умолчанию. На выходе:Hello from ENTRYPOINT. - Хочешь другой текст? Кричи его при запуске:
docker run <image> "New argument".ENTRYPOINTостаётсяecho, а твой крик становится новым аргументом. Вывод:New argument. CMD опять нахуй. - А если тебе вдруг борщ надоел и захотелось пиццы? Тогда надо орать специальное заклинание:
docker run --entrypoint "/bin/sh" <image>. Вот теперь твойENTRYPOINT— это шелл, и ты в контейнере.
Зачем это нужно? Чтобы сделать из контейнера такую этакую утилиту, как будто программа. ENTRYPOINT — это сама программа (например, curl или nginx), а всё остальное — её флаги и аргументы, которые можно задать по умолчанию через CMD или передать при запуске.
Короче, суть в чём, чтобы не ебать мозг:
CMD— это что запустить по умолчанию. Легко переопределяется, если просто что-то сказать после имени образа. Используется, когда образ — это типа «окружение», в котором можно делать разное.ENTRYPOINT— это чем является контейнер. Он не меняется просто так. Всё, что ты скажешь после имени образа, станет аргументами для этой фиксированной команды. Используется, когда образ — это «исполняемый файл», типа готовой программы.
Сочетаются они так: ENTRYPOINT — это пушка, а CMD — патроны по умолчанию. Но если ты принёс свои патроны (аргументы в docker run), то дефолтные летят в мусорку. Вот и вся магия, блядь. Не благодари.