В чем разница между CMD и ENTRYPOINT в Docker

Ответ

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

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

На практике это выглядит так:

  1. Только CMD (исполняемая команда по умолчанию):

    CMD ["nginx", "-g", "daemon off;"]

    При docker run <image> запустится nginx. Но команду можно полностью заменить: docker run <image> /bin/bash.

  2. Комбинация ENTRYPOINT + CMD (наиболее частый случай):

    ENTRYPOINT ["curl"]
    CMD ["--help"]
    • docker run <image> выполнит curl --help.
    • docker run <image> -I https://example.com выполнит curl -I https://example.com (аргументы CMD заменяются).
  3. Только ENTRYPOINT (строгая команда):

    ENTRYPOINT ["/app/start.sh"]

    Контейнер всегда будет запускать этот скрипт, а любые аргументы docker run передадутся ему.

Итог: ENTRYPOINT — это «что запускать», а CMD — «с какими аргументами по умолчанию». Команда в контейнере формируется как [ENTRYPOINT] + [CMD (или аргументы из docker run)].

Ответ 18+ 🔞

А, ну это же классика, про которую все спотыкаются, как об хуй с горы! Слушай сюда, сейчас разжуем, чтобы даже мартышлюшка поняла.

Представь, что ENTRYPOINT — это твой основной инструмент, например, curl. Это как будто ты решил: "Всё, я сегодня только курлом и буду работать, ёпта". А CMD — это бумажка с дефолтными настройками для этого инструмента, типа "проверь --help".

Вот как это на практике работает, бля:

  1. Только CMD — это как "сделай что-нибудь по умолчанию, но я могу всё отменить".

    CMD ["nginx", "-g", "daemon off;"]

    Запускаешь контейнер просто так — он стартанёт nginx. Но если тебе вдруг приспичило, ты можешь нахуй послать эту команду и сказать: "Нет, бля, давай /bin/bash!" И контейнер, такой: "Окей, да похуй, делаю что сказали". Полная свобода, но и полный распиздяй может наворотить.

  2. ENTRYPOINT + CMD — это золотая середина, "делай вот это, но с такими настройками, если я не уточнил".

    ENTRYPOINT ["curl"]
    CMD ["--help"]
    • Запустил голый контейнер — он выполнит curl --help. Всё логично, справку показывает.
    • А если ты запустишь с аргументами, типа docker run <image> -I https://example.com, то он возьмёт свой жёсткий curl из ENTRYPOINT и прилепит к нему ТВОИ аргументы, выкинув --help нахуй. Получится curl -I https://example.com. Удобно, хитрая жопа!
  3. Только ENTRYPOINT — это железобетонная позиция, "делай ТОЛЬКО это, и точка".

    ENTRYPOINT ["/app/start.sh"]

    Что бы ты ни пытался передать при запуске, контейнер, как упрямый осёл, запустит этот скрипт. Твои аргументы просто прилетят скрипту на вход, но саму команду не поменяют. Доверия к пользователю — ноль ебать, зато надёжно.

Итог, ёбана рот: ENTRYPOINT — это "что запускать" (основная программа). CMD — это "с какими аргументами по умолчанию" (дефолтные флаги). Финальная команда в контейнере собирается просто: берётся [ENTRYPOINT] и к нему прикручивается либо [CMD], либо то, что ты в docker run написал. Если ENTRYPOINT нет, то CMD сам становится командой, которую можно полностью перебить. Всё, теперь ты сам от себя охуеешь, когда будешь это применять.