# Dockerfile
DockerFile - набор инструкций по установке и настройке контейнера. Также используется для создания преднастроенных образов. Обычно dockerfile расположен в директории, из которой вызывается команда.
Имя файла: Dockerfile (без расширения).
Контекст создания - набор локальных файлов/каталогов, к которым можно обращаться через copy/add.
/ не стоит использовать как контекст, полностью включается в архив
\# комментарии
При сборке образа попытки использования кэша идут до первого промаха. Затем кэш не проверяется.
.dockerignore - файл исключений из контекста
При сборке компилируемых приложений лучше использовать multi-stage build.
Основная команда | Параметры | Описание |
docker build | | создание образа
Создание образа из docker файла . - контекст создания (текущая папка)
```bash
docker build -t test/cowsay-dockerfile .
```
После этого образ появляется в списке образов
|
| -t | имя слоя |
| -f | расположение слоя |
| --squash | сжимает все слои в один |
docker history | <image> | инструкции создания образа |
docker buildx |
| для компиляции под разные платформы |
**Формат exec и формат командной оболочки**
**Формат exec**
JSON-массив
первый элемент массива: имя выполняемого файла
остальные - параметры, передаваемые при запуске.
**Формат командной оболочки**
строка произвольной формы, передаваемая для интерпретации в /bin/sh -c.
Используйте формат exec, чтобы избежать случайного искажения строк командной оболочки, или в тех случаях, когда образ не содержит /bin/sh.
Команды файла:
Основная команда | Параметры | Описание |
FROM | <name> | название базового образа |
MAINTAINER | <name> | имя поддерживающего пользователя |
USER | <name> | !Всегда определять! Задает пользователя (по имени или по идентификатору UID) для использования во всех последующих инструкциях RUN, CMD, ENTRYPOINT. |
WORKDIR |
| рабочий каталог для последующих RUN, CMD, ENTRYPOINT, ADD, COPY. можно использовать несколько раз можно относительные пути, итоговый путь относительно предыдущего WORKDIR. |
RUN | <commands> | команды при инициализации образа, обычно установка пакетов каждая создает новый слой |
CMD {''} |
| команда с аргументами, выполняемая после запуска контейнера. Аргументы могут быть переопределены при запуске контейнера. В файле может присутствовать лишь одна инструкция CMD. |
ENTRYPOINT | <program name> | Выполняемый файл, который будет вызываться для обработки аргументов, переданных в команду docker run ```
ENTRYPOINT ["/usr/games/cowsay", "-k"]
```
|
COPY | <> <> | копирование файла из ФС ОС в ФС образа COPY . /src копирует все из текущей папки в папку /src |
VOLUME | <> | Том в ФС |
ARG |
| Определяет переменные среды, доступные внутри образа при сборке. Неизменяемые. |
ENV |
| Определяет переменные среды внутри образа, но могут изменяться. На эти переменные можно ссылаться в последующих инструкциях.* ```yaml
ENV MY_VERSION 1.3
RUN apt-get install -y mypackage=$MY_VERSION
```
Переменные среды со значением по умолчанию
Файл first.sh
```
echo $NODE_ENV
```
Dockerfile
```yaml
FROM alpine:latest
ARG NODE_ENV=production2
ENV NODE_ENV=${NODE_ENV}
RUN mkdir /var/www
COPY first.sh /var/www/first.sh
CMD ["sh", "/var/www/first.sh"]
```
Собираем образ
```
docker build -t bobrobot:1.0 .
```
docker-compose.yml
```
services:
bobrobot:
image: bobrobot:1.0
environment:
NODE_ENV: "first2"
```
В итоге при указании NODE\_ENV выводится first2, иначе production2
|
EXPOSE |
| Сообщает механизму Docker, что в контейнере будет процесс, прослушивающий порт(ы) не оказывает воздействия на сетевую среду нужно для аргумента -p в docker run |
ONBUILD |
| инструкция, выполняемая когда образ будет использоваться как основной уровень для другого образа. Полезным при обработке данных, добавляемых в образ-потомок (например, инструкция копирования дополнительного кода из заданного каталога и запуска скрипта сборки, обрабатывающего скопированные данные). |
* Для различных образов могут использоваться доп. переменные, иногда обязательные. Детали нужно уточнять для конкретного образа.
При сборке команды исполняются однократно. Затем при запуске образа они не повторяют исполнение. Поэтому для
```
FROM alpine:latest
ARG NODE_ENV=production2
ENV NODE_ENV=${NODE_ENV}
RUN mkdir /var/www
RUN echo $NODE_ENV > /var/www/first.txt
CMD ["cat", "/var/www/first.txt"]
```
вывод всегда будет production2.
**Многошаговая сборка (Multi-stage building)**
**Создание одного образа с участием нескольких временных**
Необходима если нужно при помощи временного образа скомпилировать исходники и результат сохранить в финальный образ. Временный образ удаляется.
```
FROM golang:1.20-alpine AS base
WORKDIR /src
COPY go.mod go.sum .
RUN go mod download
COPY . .
FROM base AS build-client
RUN go build -o /bin/client ./cmd/client
FROM base AS build-server
RUN go build -o /bin/server ./cmd/server
FROM scratch AS prod
COPY --from=build-client /bin/client /bin/
COPY --from=build-server /bin/server /bin/
ENTRYPOINT [ "/bin/server" ]
```
Сборка образа:
```
docker build -t multi:stage .
```
**Создание нескольких образов**
Также можно создать несколько образов при помощи одного Dockerfile. Отличие в последней стадии:
```
...
FROM scratch AS prod-client
COPY --from=build-client /bin/client /bin/
ENTRYPOINT [ "/bin/client" ]
FROM scratch AS prod-server
COPY --from=build-server /bin/server /bin/
ENTRYPOINT [ "/bin/server" ]
```
Сборка образов:
```
docker build -t multi:client --target prod-client -f Dockerfile-final .
docker build -t multi:server --target prod-server -f Dockerfile-final .
```
**Мультиплатформенная сборка**
Возможно, но пока не интересно
**Использование условий для создания разных образов**
Условия можно использовать только в конструкции RUN и CMD
```yaml
RUN if [ "$TARGET" = "test" ]; then \
cp -r /files/src/tests .; \
fi
# Разные команды для production и тестов
CMD if [ "$TARGET" = "production" ]; then \
exec gunicorn app.main:app --bind 0.0.0.0:8000; \
else \
exec pytest -v; \
fi
```
Затем собирается образ с указанной переменной окружения
```
docker build --build-arg TARGET=production -t myapp:prod .
```
Полный пример:
```
FROM alpine:latest
ARG BUILD_ENV
RUN mkdir /var/www
WORKDIR /var/www
COPY test.txt .
COPY prod.txt .
RUN if [ "$BUILD_ENV" = "test" ]; then \
cat test.txt > first.txt; \
else \
cat prod.txt > first.txt; \
fi
CMD ["cat", "/var/www/first.txt"]
```
**Использование multistage сборки для ограничения копирования**
if не работает в команде COPY. Но иногда бывает нужен образ для тестирования без содержимого директории, а в prod с содержимым. Пример:
```
# Общая стадия для подготовки файлов
FROM alpine:latest as base
COPY common_files /app/common_files
# Стадия для prod (копирует папку)
FROM base as prod
COPY prod_folder /app/prod_folder
# Стадия для test (не копирует папку)
FROM base as test
RUN echo "Running in test mode, no prod_folder copied"
# Выбираем финальную стадию через ARG
ARG TARGET_ENV=prod
FROM ${TARGET_ENV} as final
# Остальные инструкции...
```
**Сжатие итогового образа (многоуровневого) в один уровень**
Не рекомендуется, но если надо: --squash флаг при build
**Разное**
При apt-get install использовать no-install-recommends - сильно снижает объем.