← Назад к вопросам

Что произойдет если указать ENTRYPOINT и CMD в Dockerfile?

2.0 Middle🔥 171 комментариев
#Docker и контейнеризация

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# ENTRYPOINT и CMD в Dockerfile: когда они оба указаны

Краткий ответ

Если в Dockerfile указаны оба ENTRYPOINT и CMD, то CMD используется как аргументы (параметры) для ENTRYPOINT, а не как самостоятельная команда.

Детальное объяснение

Три формата команд в Docker

1. Shell form (shell форма):

ENTRYPOINT echo "Hello"
CMD ["World"]

2. Exec form (exec форма) — рекомендуется:

ENTRYPOINT ["echo", "Hello"]
CMD ["World"]

3. Комбинация форм:

ENTRYPOINT ["echo"]  # exec form
CMD "World"          # shell form

Правило взаимодействия

Когда оба указаны:

FROM alpine:latest
ENTRYPOINT ["echo", "Hello"]
CMD ["World"]

Выполнится:

echo Hello World

Команда будет: ENTRYPOINT + CMD = финальная команда

Практические примеры

Пример 1: Python приложение

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

# ENTRYPOINT — главная команда
ENTRYPOINT ["python", "/app/app.py"]

# CMD — параметры по умолчанию
CMD ["--config", "/etc/app.conf"]

При docker run myimage:

python /app/app.py --config /etc/app.conf

При docker run myimage --debug:

python /app/app.py --debug
# CMD заменяется на --debug

Пример 2: Flask приложение

FROM python:3.9
WORKDIR /app

ENTRYPOINT ["flask"]
CMD ["run", "--host=0.0.0.0"]

По умолчанию:

flask run --host=0.0.0.0

При docker run myimage db upgrade:

flask db upgrade
# CMD полностью заменяется

Пример 3: Node.js сервис

FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm ci

ENTRYPOINT ["node"]
CMD ["src/server.js"]

Запуск контейнера:

# Вариант 1: используется CMD
$ docker run myapp
# Выполняется: node src/server.js

# Вариант 2: переопределяем CMD
$ docker run myapp src/cli.js
# Выполняется: node src/cli.js

# Вариант 3: переопределяем и ENTRYPOINT, и CMD
$ docker run --entrypoint npm myapp start
# Выполняется: npm start

Важные различия

Когда указан только CMD

FROM ubuntu:20.04
CMD ["echo", "Hello"]
$ docker run myimage
# Выполняется: echo Hello

$ docker run myimage ls -la
# Выполняется: ls -la (CMD заменен полностью)

Когда указан только ENTRYPOINT

FROM ubuntu:20.04
ENTRYPOINT ["echo"]
$ docker run myimage
# Выполняется: echo (пусто)

$ docker run myimage Hello
# Выполняется: echo Hello (аргумент добавлен)

$ docker run --entrypoint ls myimage -la
# Выполняется: ls -la (ENTRYPOINT переопределён)

Когда указаны оба

FROM ubuntu:20.04
ENTRYPOINT ["echo"]
CMD ["Hello"]
$ docker run myimage
# Выполняется: echo Hello

$ docker run myimage World
# Выполняется: echo World (CMD заменен)

$ docker run --entrypoint ls myimage -la
# Выполняется: ls -la (ENTRYPOINT переопределён, CMD игнорируется)

Shell form vs Exec form

Shell form — ОПАСНО для ENTRYPOINT

FROM ubuntu:20.04
ENTRYPOINT echo Hello
CMD World

Проблема: CMD не будет передан как аргумент!

$ docker run myimage
# Выполняется: /bin/sh -c "echo Hello"
# World не используется!

Exec form — ПРАВИЛЬНО

FROM ubuntu:20.04
ENTRYPOINT ["echo"]
CMD ["World"]
$ docker run myimage
# Выполняется: echo World (корректно)

Таблица поведения

Dockerfiledocker runРезультат
CMD echo hello(нет args)/bin/sh -c "echo hello"
CMD echo hellolsls
ENTRYPOINT echo(нет args)echo
ENTRYPOINT echohelloecho hello
ENTRYPOINT echo + CMD hello(нет args)echo hello
ENTRYPOINT echo + CMD helloworldecho world
ENTRYPOINT ["echo"] + CMD ["hello"](нет args)echo hello
ENTRYPOINT ["echo"] + CMD ["hello"]worldecho world

Best Practices

1. Используй Exec form для обоих

# Хорошо
ENTRYPOINT ["python", "/app/app.py"]
CMD ["--config", "/etc/app.conf"]

# Плохо
ENTRYPOINT python /app/app.py
CMD --config /etc/app.conf

2. ENTRYPOINT для основного процесса

# Правильно
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]

# docker run image → nginx -g daemon off;
# docker run image -c /etc/nginx/nginx.conf → nginx -c /etc/nginx/nginx.conf

3. Используй wrapper script если нужна гибкость

FROM python:3.9
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["python", "app.py"]
#!/bin/bash
# docker-entrypoint.sh
set -e

# Pre-startup logic
echo "Starting app..."

# Exec the main command
exec "$@"

4. CMD для параметров, которые часто меняются

FROM ubuntu:20.04
RUN apt-get update && apt-get install -y curl

ENTRYPOINT ["curl", "https://example.com"]
CMD ["-v"]  # verbose по умолчанию
$ docker run myimage
# curl https://example.com -v

$ docker run myimage -i
# curl https://example.com -i

Вывод

Если указаны оба ENTRYPOINT и CMD:

  1. ENTRYPOINT — это команда, которая ВСЕГДА выполняется
  2. CMD — это аргументы/параметры для ENTRYPOINT
  3. docker run image args заменяет CMD, но не ENTRYPOINT
  4. Используй exec form ["cmd", "arg"] для обоих
  5. Это позволяет гибко переопределять параметры при запуске