Shell form и exec form это по сути два стиля написания команд в Dockerfile.
| Форма | Пример | |
|---|---|---|
| Shell form | RUN apt-get update && apt-get install -y curl | оболочечная (shell) |
| Exec form | RUN [“apt-get”, “update”, “&&”, “apt-get”, “install”, “-y”, “curl”] | исполняемая (exec) |
Как видно из таблицы для человека более приятная форма shell, нет никаких разбивок и проще для написания.
Shell form
RUN apt-get update && apt-get install -y curl
Команда выше выполняется через оболочку, т.е. Docker в тайне от вас выполняет эту команду так /bin/sh -c "apt-get update && apt-get install -y curl".
Благодаря такому преобразованию можно использовать в команде &&, |, переменные, перенаправления (>, >>).
Но при выполнении команды в формате Shell процесс внутри контейнера будет не сама команда а оболочка, которая выполняет её (sh). Т.е. при передаче сигнала SIGTERM его получит сама оболочка, а не команда, вызываемая внутри неё.
🦴Dockerfile.shell
FROM ubuntu
CMD sleep 100
docker build -t shell:1.0 -f Dockerfile.shell .
docker run -it --name shellc shell:1.0
В другом терминале я зайду в контейнер и проверю запущенные процессы в контейнере.
docker exec shellc ps
PID TTY TIME CMD
1 ? 00:00:00 sh
6 ? 00:00:00 sleep
7 ? 00:00:00 ps
Exec form
Теперь напишу туже самую команду, только в формате Exec.
🦴Dockerfile.exec
FROM ubuntu
CMD ["sleep", "100"]
docker build -t exec:1.0 -f Dockerfile.exec .
docker run -it --name execc exec:1.0
Теперь также выполню команду, которая выведет запущенные процессы внутри контейнера.
docker exec execc ps
PID USER TIME COMMAND
1 root 0:00 sleep 100
6 root 0:00 ps
Из вывода видно, что тут главный процесс PID 1 — это sleep сам по себе, а не sh как в случае с Shell form, потому что напрямую вызывается команда, а не оборачивается в sh.
Где и что использовать?
На самом деле если разбираться более детально в этой теме, то можно легко запутаться. В целом я не вижу особого смысла делать большой акцент на этой теме, просто возьмите за правило, что:
- Для RUN просто используйте shell вариант, например, RUN apt-get update. Конечно ничто на мешает записать эту команду в EXEC варианте (RUN [“apt-get”, “update”]), но зачем?
- Для ENTRYPOINT наоборот используйте EXEC
- Для CMD также используйте EXEC только если только не вынуждены использовать shell
- Для ENTRYPOINT + EXEC используйте всегда EXEC


Комментарии