Dockerfile
Редактировать на GitHubВопросы
Какие инструкции есть у Dockerfile?
| Инструкция | Описание |
|---|---|
| FROM | Задаёт базовый (родительский) образ. |
| LABEL | Описывает метаданные. Например — сведения о том, кто создал и поддерживает образ. |
| ENV | Устанавливает постоянные переменные среды. |
| RUN | Выполняет команду и создаёт слой образа. Используется для установки в контейнер пакетов. |
| COPY | Копирует в контейнер файлы и директории. |
| ADD | Копирует файлы и директории в контейнер, может распаковывать локальные .tar-файлы. |
| CMD | Описывает команду с аргументами, которую нужно выполнить когда контейнер будет запущен. Аргументы могут быть переопределены при запуске контейнера. В файле может присутствовать лишь одна инструкция CMD. |
| WORKDIR | Задаёт рабочую директорию для следующей инструкции. |
| ARG | Задаёт переменные для передачи Docker во время сборки образа. |
| ENTRYPOINT | Предоставляет команду с аргументами для вызова во время выполнения контейнера. Аргументы не переопределяются. |
| EXPOSE | Указывает на необходимость открыть порт. |
| VOLUME | Создаёт точку монтирования для работы с постоянным хранилищем. |
Чем отличается CMD от ENTRYPOINT в Dockerfile?
Эти инструкции Dockerfile задают команду, исполняемую при запуске контейнера. При их использовании есть несколько правил, например:
- Должна быть минимум одна из них, CMD или ENTRYPOINT, в Dockerfile.
- Если контейнер используется как исполняемый файл — ENTRYPOINT должна быть определена.
- Если контейнер запускается с другими аргументами — CMD будет переопределена. Инструкция RUN позволяет вам установить ваше приложение и необходимые для него пакеты. Он выполняет любые команды поверх текущего изображения и создает новый слой, фиксируя результаты. Часто в Dockerfile вы найдете несколько инструкций RUN.
Хорошей иллюстрацией инструкции RUN может быть установка нескольких пакетов систем контроля версий:
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversionОбратите внимание, что apt-get updateи apt-get installвыполняются в одной инструкции RUN. Это делается для того, чтобы убедиться, что будут установлены самые последние пакеты. Если бы apt-get installэто была отдельная инструкция RUN, то она бы повторно использовала слой, добавленный apt-get update, который мог быть создан давным-давно.
Инструкция CMD позволяет вам установить команду по умолчанию , которая будет выполняться только тогда, когда вы запускаете контейнер без указания команды. Если контейнер Docker запускается с командой, команда по умолчанию будет игнорироваться. Если Dockerfile содержит более одной инструкции CMD, все инструкции CMD, кроме последней, игнорируются.
CMD имеет три формы:
CMD ["executable","param1","param2"](исполнительная форма, предпочтительнее)CMD ["param1","param2"]exec (устанавливает дополнительные параметры по умолчанию для ENTRYPOINT в формеCMD command param1 param2(форма оболочки)docker run -it <image> /bin/bash- тут при наличии CMD он будет проигнорирован, и будет запущен баш Инструкция ENTRYPOINT позволяет настроить контейнер, который будет работать как исполняемый файл. Он похож на CMD, потому что также позволяет указать команду с параметрами. Разница заключается в том, что команда ENTRYPOINT и параметры не игнорируются, когда контейнер Docker запускается с параметрами командной строки. (Есть способ игнорировать ENTTRYPOINT, но вряд ли вы это сделаете.)
Докерфайл
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]когда контейнер запускается, как docker run -it <image>будет производиться вывод
Hello worldно когда контейнер запускается, docker run -it <image> Johnэто приведет к
Hello John- Краткий ответ cmd подставится после entrypoint при запуске. Тем самым можно запускать контейнер с нужными параметрами. То есть в entrypoint можно передать бинарь, а в cmd передать параметры. CMD может перетереться просто.
Что происходит когда пишешь ENTRYPOINT?
Точка входа в приложение.
Это инструкция в докерфайле, которая всегда будет выполняться при запуске контейнера. Она часто используется для определения основной команды для запуска контейнера. Например для запуска веб-сервера или какой-либо иной службы.
Что происходит пошагово:
Инструкция ENTRYPOINT в Dockerfile задает команду, которая всегда будет выполняться при запуске контейнера. Она часто используется для задания основной команды для запуска контейнера, например, для запуска веб-сервера, базы данных или службы.
Вот что происходит шаг за шагом:
-
В процессе сборки образа Docker читает Dockerfile строка за строкой, сверху вниз. Когда Docker встречает инструкцию ENTRYPOINT, он записывает команду и ее аргументы.
-
После сборки образа, при запуске контейнера из этого образа Docker выполняет команду, указанную в инструкции ENTRYPOINT.
-
Если команда Docker run также включает в себя команду, то она передается в качестве аргумента команде ENTRYPOINT.
Например, если у вас есть Dockerfile со следующим ENTRYPOINT:
ENTRYPOINT ["/app/start.sh"]И запускается контейнер из этого образа с помощью команды:
docker run -it my_image echo "Hello, World!"Докер выполнит команду ENTRYPOINT с командой run в качестве аргумента:
/app/start.sh echo "Hello, World!"Обратите внимание, что команду ENTRYPOINT можно отменить при запуске контейнера, используя флаг --entrypoint в команде docker run.
В этом основной смысл, что можно переопределить аргумент, или вообще его отменить.
В чем разница между ADD и COPY
В Dockerfile, инструкции ADD и COPY обе используются для копирования файлов и директорий из локальной файловой системы в образ контейнера, но между ними есть несколько важных различий:
- COPY поддерживает только базовое копирование локальных файлов в контейнер
- ADD имеет дополнительный функционал, к примеру, может извлекать архивы (напр, .tar, .tar.gz, .zip и другие форматы) и загружать файлы по URL. Но если, например, копировать через него архив, то он распакуется как каталог. Это уменьшает размер образа
В большинстве случаев предпочтительнее использовать COPY, так как это более предсказуемо и ясно, а ADD стоит использовать только тогда, когда вам действительно нужны её дополнительные возможности, такие как извлечение архивов или загрузка файлов по URL.
В чем отличие ARG от ENV?
ENV позволяет создавать переменные окружения, которые будут работать во время работы контейнера.
ARG позволяет закинуть переменные, которые будут доступны во время сборки. Но они недоступны в контейнере. Однако через ARG можно задавать значения переменных по умолчанию для ENV
Какие есть best practices для написания Dockerfile?
- Запускать только один процесс на контейнер.
- Стараться объединять несколько команд RUN в одну для уменьшения количества слоёв образа.
- Частоизменяемые слои образа необходимо располагать ниже по уровню, чтобы ускорить процесс сборки, т.к. при изменении верхнего слоя, все нижеследующие слои будут пересобираться.
- Указывать явные версии образов в инструкции FROM, чтобы избежать случая, когда выйдет новая версия образа с тегом latest.
- При установке пакетов указывать версии пакетов.
- Очищать кеш пакетного менеджера и удалять ненужные файлы после выполненной инструкции.
- Использовать multistage build для сборки артифакта в одном контейнере и размещении его в другом.
Что такое Docker squash?
Это утилита на питоне, которая позволяет объединить слои в один. Также это экспериментальный параметр с помощью которого можно создать сжатый образ.
Как уменьшить размер образа докера? У нас много COPY, RUN
- Использовать специальные облегченные базовые версии докер-образов.
- Уменьшать размер слоев, запуская RUN нечасто, объединив команды в одну
- Не устанавливать рекомендованные пакеты. И удалять содержимое
/var/lib/apt/lists/* - Docker-multistage-build. Тут указываем несколько
FROM. И можно копировать результат одногоFROM-ав другой
Пример
# 1 =====================================
# специальный образ, который содержит все необходимые
# для сборки библиотеки и приложения
# размер образа ~730mb
FROM diproart/ruby:2.6.4-alpine3.10 AS builder
# полный набор пакетов
ENV COMMON_PACKAGES \
tzdata \
...
ENV ..
RUN set -xe \
&& apk update \
&& apk upgrade \
&& apk add --no-cache --update ${COMMON_PACKAGES} \
&& rm -rf /var/cache/apk/* /tmp/* /var/tmp/*
# additional clean
#RUN rm -rf /usr/local/bundle/cache/*gem
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . .
RUN
# 2 =====================================
# чистый образ, в который добавим только самое необходимое
# размер образа ~51mb
FROM ruby:2.6.4-alpine3.10
# только необходимые для работы
# в production пакеты
ENV PRODUCTION_PACKAGES \
tzdata \
...
ENV ...
RUN set -xe \
&& apk update \
&& apk upgrade \
&& apk add --no-cache --update ${PRODUCTION_PACKAGES} \
&& rm -rf /var/cache/apk/* /tmp/* /var/tmp/*
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
WORKDIR /usr/src/app
# копируем скомпилированное приложение
# и пакеты в напрямую в образ из предыдущего шага
COPY --from=builder /usr/src/app .
COPY --from=builder /usr/local/bundle/ /usr/local/bundle/
EXPOSE 3000
ENTRYPOINT [ "bundle", "exec" ]
CMD [ "rails", "s", "-b", "0.0.0.0" ]Последнее обновление: 11 сент. 2025 г., 14:56:43