Инструкция Entrypoint в Dockerfile нужна для того, чтобы задать команду, которая выполнится при старте контейнера. Но для этого также есть и другая команда CMD. Так давайте тут разберёмся в чём собственно разница.
Начнём с того что использовать можно обе инструкции, но работают они немного по-разному.
CMD
Рассмотрим инструкцию CMD, для этого я сделаю следующее:
- Создам образ с
ubuntu:latestи в качестве команды для CMD укажуdate. Когда контейнер запустится выполнится командаdateи я увижу результат. - Соберу образ
date - Запущу контейнер
- Снова запущу контейнер, но только передам новое значение для CMD (
df)
🗃️Dockerfile.13
FROM ubuntu:latest
CMD ["date"]
docker build -t date -f Dockerfile.13 .
docker run date
Thu Nov 6 07:53:49 UTC 2025
docker run date df
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 52902668 26803728 26098940 51% /
tmpfs 65536 0 65536 0% /dev
shm 65536 0 65536 0% /dev/shm
/dev/mapper/cs-root 52902668 26803756 26098912 51% /etc/hosts
tmpfs 650128 0 650128 0% /proc/acpi
tmpfs 650128 0 650128 0% /proc/scsi
tmpfs 650128 0 650128 0% /sys/firmware
Т.е. используя инструкцию CMD в качестве команды для выполнения при старте контейнера можно передать новое значение для CMD при создании этого контейнера. По умолчанию при старте контейнера выполняется команда date, но ничего мне не мешает выполнить другую команду при создании контейнера, например, df.
ENTRYPOINT
Теперь я выполню всё тоже самое, но только вместо CMD я буду использовать ENTRYPOINT. Посмотрим, что из этого выйдет.
🗃️Dockerfile.14
FROM ubuntu:latest
ENTRYPOINT ["date"]
docker build -t date:1.1 -f Dockerfile.14 .
docker run date:1.1
Thu Nov 6 08:04:09 UTC 2025
docker run date:1.1 df
date: invalid date 'df'
В итоге я получаю ошибку. И вот она разница, используя ENTRYPOINT вы не можете перезаписать команду внутри инструкции ENTRYPOINT пи старте самого контейнера. Всё что вы передаёте в контейнер в качестве команды будет просто добавлено к команде, которая прописана в ENTRYPOINT образа Docker. Т.е. при старте контейнера во втором случае внутри него выполнилась команда date df.
Получается, чтобы команда отработала нормально я должен передать работающие параметры для команды date.
docker run date:1.1 -I
2025-11-06
Но если хочется заменить команду и в ENTRYPOINT, то можно использовать опцию --entrypoint.
docker run --entrypoint df date:1.1
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 52902668 26804400 26098268 51% /
tmpfs 65536 0 65536 0% /dev
shm 65536 0 65536 0% /dev/shm
/dev/mapper/cs-root 52902668 26804400 26098268 51% /etc/hosts
tmpfs 614288 0 614288 0% /proc/acpi
tmpfs 614288 0 614288 0% /proc/scsi
tmpfs 614288 0 614288 0% /sys/firmware
ENTRYPOINT + CMD
Как вы уже догадались можно использовать обе команды в одном файле Dockerfile. Когда вы используете обе команды в одном Dockerfile при старте контейнера Docker объединяет обе команды из инструкций (NTRYPOINT + CMD) и выполняет внутри контейнера что получилось.
Вариант 1
Как вы уже догадались можно использовать обе команды в одном файле Dockerfile. Когда вы используете обе команды в одном Dockerfile при старте контейнера Docker объединяет обе команды из инструкций (NTRYPOINT + CMD) и выполняет внутри контейнера.
Первый вариант это использовать ENTRYPOINT для запуска скрипта, который подготовит всё необходимое для запуска основного приложения, которое запуститься уже с помощью CMD.
🗃️script1.sh
echo "I'm just a script"
🗃️Dockerfile.15
FROM ubuntu:latest
WORKDIR /home/ubuntu
COPY script1.sh .
RUN chmod +x script1.sh
ENTRYPOINT ["sh","script1.sh"]
CMD ["date"]
docker build -t entry:1.0 -f Dockerfile.15 .
docker run entry:1.0
I'm just a script
Но в результате я получил только вывод скрипта, но не вывод команды date. Дело в том, что после объединения команда выглядит так: sh script1.sh /usr/bin/date. И это одна из самых частых ловушек при комбинировании ENTRYPOINT и CMD. Получается команда date передаётся просто как параметр для скрипта script1.sh, который ничего не ожидает и тем более ничего не делает с переданными ему аргументами.
Чтобы избежать такого и добиться выполнения обоих команд нужно использовать exec "$@" в самом скрипте. exec "$@" говорит скрипту о том, что пора бы завершить своё выполнения и передать право запуска другому приложению, которое должно запуститься после него.
🗃️script1.sh
echo "I'm just a script"
exec "$@"
docker build -t entry:1.0 -f Dockerfile.15 .
docker run entry:1.0
I'm just a script
Thu Nov 6 10:29:36 UTC 2025
Либо можно сделать тоже самое в самом Dockerfile:
🗃️Dockerfile.15
FROM ubuntu:latest
WORKDIR /home/ubuntu
COPY script1.sh .
RUN chmod +x script1.sh
ENTRYPOINT ["/bin/sh", "-c", "./script1.sh && exec \"$@\"", "--"]
CMD ["date"]
Вариант 2
Другой вариант — это когда у вас есть основной исполняемый файл, но параметры для него изменяемые, самый простой пример это обычный исполняемый файл curl, которому в качестве параметра передаются разные URL сайтов. При использовании только CMD каждый раз приходилось бы писать что-то вроде curl https://tipoit.kz.
🗃️Dockerfile.16
FROM ubuntu:latest
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["curl", "-kI"]
CMD ["https://tipoit.kz"]
docker build -t entry:1.1 -f Dockerfile.16 .
docker run entry:1.1
docker run entry:1.1 https://google.com
Получается, что по умолчанию я указал url https://tipoit.kz и при необходимости могу его поменять на любой другой.
Официальные образы
Если вы думаете, что использование одновременно ENTRYPOINT и CMD встречается только в частных сборках вы, ошибаетесь. Даже официальные образы на Docker Hub имеют такие связки, например, уже знакомый mariadb.


Комментарии