Ответ
ENTRYPOINT и CMD определяют команду, которая выполняется при запуске контейнера. Их можно использовать вместе для создания гибкого интерфейса.
ENTRYPOINTзадает исполняемую команду, которая всегда будет запущена. Её сложно переопределить. Аргументы, переданные вdocker run, добавляются в конец командыENTRYPOINT.CMDзадает аргументы по умолчанию дляENTRYPOINT. ЕслиENTRYPOINTне указан,CMDопределяет команду для выполнения. АргументыCMDлегко переопределяются аргументами изdocker run.
Практические сценарии:
-
ENTRYPOINTкак исполняемый файл,CMDкак аргументы по умолчанию (наиболее полезный вариант):ENTRYPOINT ["curl"] CMD ["--help"]docker run my-curlвыполнитcurl --help.docker run my-curl -s https://example.comвыполнитcurl -s https://example.com(аргументыCMDпереопределены).
-
Только
CMD(для одноразовых команд):CMD ["nginx", "-g", "daemon off;"]docker run my-nginxзапустит nginx.docker run my-nginx shполностью переопределитCMDи запустит оболочку.
-
Только
ENTRYPOINT(для создания контейнера как бинарника):ENTRYPOINT ["python", "app.py"]docker run my-appвыполнитpython app.py.docker run my-app --debugвыполнитpython app.py --debug.
Рекомендация: Используйте ENTRYPOINT для фиксированной части команды (например, интерпретатор или основной бинарник), а CMD для предоставления изменяемых по умолчанию аргументов. Это делает контейнер похожим на исполняемую программу.
Ответ 18+ 🔞
Давай разберём эту тему про ENTRYPOINT и CMD, а то у многих тут волнение ебать начинается, когда они в Dockerfile смотрят. Представь, что контейнер — это какой-нибудь полупидор, который должен что-то делать, когда ты его запускаешь. Так вот, эти две директивы и говорят ему, что именно.
ENTRYPOINT — это как бы его судьба, приговор. Это команда, которую он выполнит в любом случае, даже если ты будешь орать и ногами топать. Её сложно перебить. А если ты в docker run что-то допишешь, то это просто прилепится в конец этой железобетонной команды.
CMD — это его предложение на день. Аргументы по умолчанию. Если ENTRYPOINT не назначили, то CMD становится полноправной командой. Но её-то как раз легко переплюнуть, просто сказав в docker run что-то своё. Доверия к CMD — ебать ноль, если честно.
А теперь на живых примерах, чтобы совсем ядрёна вошь не съела:
-
Классика жанра:
ENTRYPOINT— программа,CMD— её довесок.ENTRYPOINT ["curl"] CMD ["--help"]- Запустил
docker run my-curl— получилcurl --help. Всё просто, как три копейки. - А вот если запустил
docker run my-curl -s https://example.com— то выполнится ужеcurl -s https://example.com. Видишь? Аргументы изCMDнакрылись медным тазом, потому что ты приказал своё. Но самcurl— нет, он железно стоит на своём месте благодаряENTRYPOINT.
- Запустил
-
Только
CMD— для простых смертных.CMD ["nginx", "-g", "daemon off;"]docker run my-nginx— и nginx пошёл работать.- Но если ты такой хитрожопый и скажешь
docker run my-nginx sh— то всё, приехали.CMDвыкинули нахуй, и контейнер запустит тебе оболочку. Полный переворот.
-
Только
ENTRYPOINT— когда ты уверен в себе как хуй с горы.ENTRYPOINT ["python", "app.py"]docker run my-app— выполнитpython app.py. Без вариантов.docker run my-app --debug— выполнитpython app.py --debug. Твои аргументы просто прицепили в хвост.
Так какого хуя со всем этим делать? Самый адекватный совет — используй ENTRYPOINT для чего-то главного и нерушимого (типа интерпретатора python или бинарника curl), а CMD — для аргументов по дефолту, которые ты, скорее всего, захочешь поменять. Тогда твой контейнер будет вести себя как нормальная программа: у неё есть имя (ENTRYPOINT), а флаги (CMD) ты можешь подкручивать под себя. И никакого пиздеца.