Что такое entrypoint \ cmd
ENTRYPOINT и CMD — это две инструкции в Dockerfile, которые определяют команду и параметры, исполняемые при запуске контейнера. Они похожи, но служат разным целям и взаимодействуют между собой: ENTRYPOINT задает исполняемый файл, а CMD — аргументы по умолчанию для него.
Как это работает
При запуске контейнера Docker объединяет ENTRYPOINT и CMD в одну команду. Если ENTRYPOINT не указан, CMD может использоваться для указания полной команды. Если ENTRYPOINT указан, CMD добавляет аргументы к нему. При запуске контейнера с помощью docker run можно переопределить CMD, передав аргументы после имени образа. ENTRYPOINT при этом остаётся неизменным, если только не использовать флаг --entrypoint.
Пример
Рассмотрим два подхода на примере Python-приложения.
Только ENTRYPOINT:
FROM python:3.8
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "app.py"]Здесь при запуске контейнера всегда выполняется python app.py. Любые аргументы, переданные в docker run, будут добавлены к этой команде. Например, docker run myimage --help выполнит python app.py --help.
ENTRYPOINT и CMD вместе:
FROM python:3.8
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]Здесь ENTRYPOINT задаёт команду python, а CMD — аргумент по умолчанию app.py. При запуске docker run myimage выполнится python app.py. Если передать аргументы, например docker run myimage hello.py, то CMD будет переопределён, и выполнится python hello.py.
Подводные камни
- Переопределение
CMD:CMDлегко переопределяется аргументами командной строки, что удобно для гибкости, но может привести к неожиданному поведению, если не учитывать это. - Переопределение
ENTRYPOINT: Чтобы изменитьENTRYPOINT, нужно использовать флаг--entrypointвdocker run, что менее очевидно. - Форма записи: Обе инструкции могут быть в exec-форме (JSON-массив) или shell-форме (строка). Exec-форма предпочтительнее, так как она не запускает оболочку и позволяет корректно передавать сигналы.
- Отсутствие
ENTRYPOINT: ЕслиENTRYPOINTне задан,CMDстановится полной командой. В этом случае переопределить её можно просто передав аргументы.
Когда использовать
- Используйте
ENTRYPOINT, когда контейнер должен вести себя как исполняемый файл с фиксированной командой, аCMD— для аргументов по умолчанию, которые пользователь может легко переопределить. - Если нужна максимальная гибкость и контейнер может выполнять разные команды, лучше задать только
CMD. - Для сервисов, которые всегда запускают один и тот же процесс (например, веб-сервер), комбинация
ENTRYPOINT+CMDдаёт удобный интерфейс: пользователь может передавать дополнительные флаги, не меняя основную команду.
Коротко
ENTRYPOINT— фиксированная команда,CMD— аргументы по умолчанию.CMDпереопределяется аргументамиdocker run,ENTRYPOINT— только флагом--entrypoint.- Используйте exec-форму (
["команда", "аргумент"]) для избежания проблем с сигналами. - Если
ENTRYPOINTнет,CMDзадаёт всю команду.