push
This commit is contained in:
@@ -54,6 +54,7 @@ docker run -it --rm debian:bookworm-slim bash
|
|||||||
```
|
```
|
||||||
|
|
||||||
Установка образа:
|
Установка образа:
|
||||||
|
|
||||||
<img src="./assets/image_1777877203794.jpg" width="auto">
|
<img src="./assets/image_1777877203794.jpg" width="auto">
|
||||||
|
|
||||||
Мы указали `bash` в команде, по этому зашли в интерактивный терминал:
|
Мы указали `bash` в команде, по этому зашли в интерактивный терминал:
|
||||||
@@ -123,6 +124,7 @@ docker exec -it my-nginx sh
|
|||||||
<img src="./assets/image_1777878325863.jpg" width="auto">
|
<img src="./assets/image_1777878325863.jpg" width="auto">
|
||||||
|
|
||||||
Обновим страницу в браузере - должен отобразиться новый html.
|
Обновим страницу в браузере - должен отобразиться новый html.
|
||||||
|
|
||||||
<img src="./assets/image_1777878360584.jpg" width="auto">
|
<img src="./assets/image_1777878360584.jpg" width="auto">
|
||||||
|
|
||||||
Скопировать **из** контейнера на хост:
|
Скопировать **из** контейнера на хост:
|
||||||
@@ -151,6 +153,7 @@ docker exec nginx-vol sh -c 'echo vol > /usr/share/nginx/html/index.html'
|
|||||||
`docker exec nginx-vol sh -c 'echo vol > /usr/share/nginx/html/index.html'` - выполняем команду ВНУТРИ контейнера `nginx-vol` через "sh -c" и передать ему команду `echo`.
|
`docker exec nginx-vol sh -c 'echo vol > /usr/share/nginx/html/index.html'` - выполняем команду ВНУТРИ контейнера `nginx-vol` через "sh -c" и передать ему команду `echo`.
|
||||||
|
|
||||||
<img src="./assets/image_1777879323365.jpg" width="auto">
|
<img src="./assets/image_1777879323365.jpg" width="auto">
|
||||||
|
|
||||||
<img src="./assets/image_1777879337998.jpg" width="auto">
|
<img src="./assets/image_1777879337998.jpg" width="auto">
|
||||||
|
|
||||||
Коротко, что мы сделали:
|
Коротко, что мы сделали:
|
||||||
@@ -185,6 +188,7 @@ docker run -d --name nginx-bind -p 8082:80 -v ~/docker-html:/usr/share/nginx/htm
|
|||||||
<img src="./assets/image_1777880623434.jpg" width="auto">
|
<img src="./assets/image_1777880623434.jpg" width="auto">
|
||||||
|
|
||||||
Теперь поменяем в нашей локальной папке файл и посмотрим что будет:
|
Теперь поменяем в нашей локальной папке файл и посмотрим что будет:
|
||||||
|
|
||||||
<img src="./assets/image_1777880680918.jpg" width="auto">
|
<img src="./assets/image_1777880680918.jpg" width="auto">
|
||||||
|
|
||||||
Всё работает.
|
Всё работает.
|
||||||
|
|||||||
@@ -1,162 +1,316 @@
|
|||||||
## Зачем нужен Dockerfile
|
## Зачем нужен Dockerfile
|
||||||
|
|
||||||
`Dockerfile` — это **рецепт** сборки образа: от какого базового образа начать, какие пакеты установить, какие файлы скопировать, какую команду запускать по умолчанию. Команда сборки:
|
`Dockerfile` - текстовый файл с инструкциями (по одной на строку, логически сверху вниз). Демон Docker читает их и строит образ **слоями**, почти каждая инструкция добавляет слой.
|
||||||
|
|
||||||
|
Сборка:
|
||||||
```
|
```
|
||||||
docker build -t my-app:1.0 -f Dockerfile /path/to/context
|
docker build -t имя:тег -f Dockerfile /путь/к/контексту
|
||||||
```
|
```
|
||||||
|
|
||||||
**Контекст сборки** — каталог, который вы передаёте последним аргументом (часто `.`). В образ попадают только файлы из контекста (по правилам `.dockerignore`).
|
**Контекст** - каталог, из которого разрешено брать файлы для `COPY`/`ADD` (часто `.`). Список исключений — в `.dockerignore` в корне контекста.
|
||||||
|
|
||||||
---
|
## Общие правила файла
|
||||||
|
|
||||||
## Минимальный Dockerfile и сборка
|
1. **Имя по умолчанию** - `Dockerfile` в корне контекста; другой файл: `docker build -f ./docker/prod.Dockerfile .`
|
||||||
|
2. **Комментарии** - строка, начинающаяся с `#`.
|
||||||
|
3. **Продолжение строки** - обратный слэш `\` в конце строки.
|
||||||
|
4. **Регистр** - инструкции принято писать **ЗАГЛАВНЫМИ** (`FROM`, `RUN`…), Docker это не требует, просто читается легче.
|
||||||
|
5. **Первый этап** должен начинаться с **`FROM`** (кроме редких случаев с `ARG` до первого `FROM`).
|
||||||
|
|
||||||
Готовый вариант каталога **web** лежит в репозитории: `docker/examples/multi-service/web/` — можно собирать оттуда (`docker build -t my-web:1.0 ./web` из корня `multi-service`). Ниже — пошагово «с нуля»:
|
## Parser directives (только в самом верху файла)
|
||||||
|
|
||||||
```
|
Их максимум две, только **до** любых комментариев и инструкций (после пустых строк тоже нельзя вставлять мусор сверху).
|
||||||
mkdir -p ~/learn-docker/web && cd ~/learn-docker/web
|
|
||||||
```
|
|
||||||
|
|
||||||
Содержимое `Dockerfile` (ниже — максимально «говорящий» вариант с комментариями; в реальном файле комментарии допустимы):
|
`# syntax=docker/dockerfile:1` - Включить современный фронтенд Dockerfile (BuildKit, расширенный синтаксис `RUN --mount=...`).
|
||||||
|
|
||||||
|
## Сводная таблица инструкций
|
||||||
|
|
||||||
|
| Инструкция | Назначение (кратко) |
|
||||||
|
|------------|---------------------|
|
||||||
|
| `FROM` | Базовый образ (начало этапа / stage). |
|
||||||
|
| `RUN` | Выполнить команду **при сборке** (новый слой). |
|
||||||
|
| `CMD` | **По умолчанию** команда/аргументы при **запуске** контейнера (переопределяется `docker run ...`). |
|
||||||
|
| `ENTRYPOINT` | «Точка входа» при запуске; с `CMD` задаёт аргументы по умолчанию. |
|
||||||
|
| `COPY` | Копирование из контекста (или из другого stage) в образ. |
|
||||||
|
| `ADD` | Как `COPY` + tar и URL (реже нужен). |
|
||||||
|
| `WORKDIR` | Текущий каталог для последующих инструкций. |
|
||||||
|
| `ENV` | Переменные окружения в образе (и при сборке для следующих строк). |
|
||||||
|
| `ARG` | Переменные **только на время сборки** (`docker build --build-arg`). |
|
||||||
|
| `EXPOSE` | Документация портов (не публикует на хост само по себе). |
|
||||||
|
| `VOLUME` | Объявить точку монтирования тома по умолчанию. |
|
||||||
|
| `USER` | Пользователь для следующих `RUN` и для процесса при запуске. |
|
||||||
|
| `LABEL` | Метаданные ключ=значение. |
|
||||||
|
| `STOPSIGNAL` | Какой сигнал послать при `docker stop`. |
|
||||||
|
| `HEALTHCHECK` | Как проверять живость контейнера. |
|
||||||
|
| `SHELL` | Какая оболочка для **shell-формы** `RUN`/`CMD`/`ENTRYPOINT`. |
|
||||||
|
| `ONBUILD` | Зарегистрировать инструкцию «выполнить позже», когда от этого образа соберут дочерний (редко). |
|
||||||
|
|
||||||
|
Ниже - что писать, какие есть параметры и на что обратить внимание.
|
||||||
|
|
||||||
|
## `FROM` - базовый образ
|
||||||
|
|
||||||
|
**Синтаксис:**
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM [--platform=linux/amd64] image[:tag|@digest] [AS name]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Элемент | Смысл |
|
||||||
|
|---------|--------|
|
||||||
|
| `image:tag` | Репозиторий и тег (`nginx:1.27-alpine`). Лучше фиксировать тег или digest. |
|
||||||
|
| `AS name` | Имя этапа для **multi-stage** и для `COPY --from=name`. |
|
||||||
|
| `--platform=...` | Целевая платформа образа (multi-arch / кросс-сборка). |
|
||||||
|
|
||||||
|
Каждый новый `FROM` начинает **новый этап**; предыдущие слои остаются в цепочке сборки, в финальный образ попадает только последний этап (если не копировать из предыдущих через `COPY --from`).
|
||||||
|
|
||||||
|
## `RUN` - команды на этапе сборки
|
||||||
|
|
||||||
|
Две формы записи:
|
||||||
|
|
||||||
|
**Shell-форма** (через `/bin/sh -c` в Linux, если не переопределён `SHELL`):
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exec-форма** (без оболочки, нет подстановок `$VAR` шелла, если не передать через оболочку явно):
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
RUN ["apt-get", "update"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Часто объединяют команды в **одну** строку `&&`, чтобы меньше слоёв и не оставлять кэш пакетов в отдельном слое.
|
||||||
|
|
||||||
|
**BuildKit:** кэш зависимостей, секреты, примонтировать каталог хоста только на время `RUN`:
|
||||||
|
|
||||||
```dockerfile
|
```dockerfile
|
||||||
# Синтаксис Dockerfile (опционально, для BuildKit features)
|
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
# Базовый образ: лучше фиксировать мажорную версию и по возможности slim/alpine
|
Типы `type=` включают `cache`, `bind`, `secret`, `ssh` и др. [документация BuildKit mounts](https://docs.docker.com/build/buildkit/).
|
||||||
FROM nginx:1.27-alpine
|
|
||||||
|
|
||||||
# Метаданные (удобно в docker inspect / реестрах)
|
## `WORKDIR` - рабочий каталог
|
||||||
LABEL org.opencontainers.image.title="Demo static site"
|
|
||||||
LABEL org.opencontainers.image.description="Nginx with baked-in HTML from COPY"
|
|
||||||
|
|
||||||
# Переменные на этапе сборки (не попадают в runtime автоматически как ENV)
|
```dockerfile
|
||||||
ARG BUILD_DATE=unknown
|
WORKDIR /app
|
||||||
LABEL build-date="${BUILD_DATE}"
|
```
|
||||||
|
|
||||||
# Переменные окружения внутри контейнера при запуске
|
Создаёт каталог, если его нет. Влияет на последующие `RUN`, `COPY`, `CMD`, `ENTRYPOINT` в **exec-форме** относительно пути (часть команд всё равно лучше указывать абсолютно).
|
||||||
ENV NGINX_ENTRYPOINT_QUIET_LOGS=1
|
Можно несколько раз - каждый раз новый путь.
|
||||||
|
|
||||||
# Рабочая директория для последующих инструкций
|
## `COPY` - файлы в образ
|
||||||
WORKDIR /usr/share/nginx/html
|
|
||||||
|
|
||||||
# Копирование файлов ИЗ контекста сборки В образ (ключевой способ «положить файлы в образ»)
|
```dockerfile
|
||||||
COPY ./html/ /usr/share/nginx/html/
|
COPY [--chown=user:group] [--chmod=755] <src> ... <dest>
|
||||||
|
COPY ["--chown=user:group", "src с пробелом", "/dest/"]
|
||||||
|
```
|
||||||
|
|
||||||
# Права (nginx в alpine часто от uid 101 — для продакшена уточняйте образ)
|
| Параметр | Смысл |
|
||||||
RUN chown -R nginx:nginx /usr/share/nginx/html
|
|----------|--------|
|
||||||
|
| `src` | Путь **относительно контекста** сборки (не выше контекста). |
|
||||||
|
| `dest` | Файл или каталог в образе (обычно абсолютный путь). |
|
||||||
|
| `--chown` | Владелец скопированных файлов (uid:gid или имя). |
|
||||||
|
| `--chmod` | Права на файлы (новые версии BuildKit). |
|
||||||
|
| `--from=stage\|index` | Копировать не из контекста, а из **другого этапа** или **именованного образа** (`COPY --from=nginx:alpine /etc/nginx/nginx.conf /tmp/`). |
|
||||||
|
|
||||||
# Документируем порт (не открывает его само по себе на хосте — это метаданные)
|
Несколько `src` - последний аргумент должен быть **каталогом** с `/` на конце.
|
||||||
|
|
||||||
|
## `ADD` - расширенное копирование
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ADD [--chown=user:group] [--chmod=755] <src> ... <dest>
|
||||||
|
```
|
||||||
|
|
||||||
|
Поведение как у `COPY`, плюс:
|
||||||
|
|
||||||
|
- локальный **`src` в виде tar** - может **распаковаться** в `dest`.
|
||||||
|
- **`src` как URL** — скачать файл.
|
||||||
|
|
||||||
|
Для обычных файлов предпочитают **`COPY`**.
|
||||||
|
|
||||||
|
## `ENV` - переменные окружения
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ENV KEY=value
|
||||||
|
ENV KEY=value OTHER=val2
|
||||||
|
ENV KEY="значение с пробелами"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Доступны в последующих инструкциях Dockerfile и **в запущенном контейнере**.
|
||||||
|
- Одна форма `ENV A=B C=D` задаёт несколько переменных.
|
||||||
|
- Значения можно подставлять в строках как `$KEY` или `${KEY}`.
|
||||||
|
|
||||||
|
## `ARG` - переменные только при сборке
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ARG VERSION=1.0
|
||||||
|
ARG GIT_COMMIT
|
||||||
|
```
|
||||||
|
|
||||||
|
- Значение снаружи: `docker build --build-arg GIT_COMMIT=$(git rev-parse HEAD)`.
|
||||||
|
- **`ARG` до первого `FROM`** может участвовать только в самом `FROM` (версия базового образа).
|
||||||
|
- После `FROM` переменные `ARG` нужно **объявить снова**, если они нужны в этом этапе.
|
||||||
|
- **Не храните секреты в `ARG`** без BuildKit secrets: значения могут попасть в историю слоёв (`docker history`).
|
||||||
|
|
||||||
|
## `EXPOSE` - какие порты «слушает» приложение
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
EXPOSE 80/tcp 443/tcp
|
||||||
# Healthcheck — Docker помечает контейнер unhealthy при ошибках (оркестраторы могут рестартовать)
|
EXPOSE 53/udp
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
||||||
CMD wget -qO- http://127.0.0.1/ || exit 1
|
|
||||||
|
|
||||||
# Команда по умолчанию наследуется от nginx; при необходимости переопределяем:
|
|
||||||
# CMD ["nginx", "-g", "daemon off;"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Папка `html/index.html`:
|
Это **метаданные** и подсказка для `docker run -P`. Порт на хост не открывается, пока не укажете `-p` или Compose `ports:`.
|
||||||
|
|
||||||
```html
|
## `VOLUME` - каталог для данных вне слоя записи
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ru">
|
```dockerfile
|
||||||
<head><meta charset="utf-8"><title>Docker COPY demo</title></head>
|
VOLUME ["/data"]
|
||||||
<body><h1>Файл попал в образ через COPY</h1></body>
|
VOLUME /var/log/app
|
||||||
</html>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Сборка и запуск:
|
Объявляет точку, куда при запуске без явного `-v` Docker может подставить **анонимный том**. Часто для данных БД или логов. **Не путать** с явным монтированием в `docker run -v`.
|
||||||
|
|
||||||
```
|
## `USER` - под каким UID/GID работать
|
||||||
docker build -t my-web:1.0 .
|
|
||||||
docker run -d --name from-dockerfile -p 8090:80 my-web:1.0
|
```dockerfile
|
||||||
|
USER nginx
|
||||||
|
USER 1000:1000
|
||||||
```
|
```
|
||||||
|
|
||||||
**Скриншот:** этапы сборки `Step ...` и успешное `Successfully tagged my-web:1.0`.
|
Все последующие `RUN` и процесс по умолчанию при старте — от этого пользователя (если не переопределить в `docker run -u`).
|
||||||
|
|
||||||
<img src="./assets/docker_build_steps_tagged.png" width="auto">
|
## `LABEL` - метаданные образа
|
||||||
|
|
||||||
**Скриншот:** браузер на порту 8090 с вашим заголовком.
|
```dockerfile
|
||||||
|
LABEL maintainer="you@example.com"
|
||||||
|
LABEL version="1.0" description="My app"
|
||||||
|
```
|
||||||
|
|
||||||
<img src="./assets/docker_browser_copy_demo.png" width="auto">
|
Пары ключ–значение; удобно для OCI-аннотаций (`org.opencontainers.image.*`), реестров, политик.
|
||||||
|
|
||||||
---
|
## `CMD` - что выполнять при запуске по умолчанию
|
||||||
|
|
||||||
## `.dockerignore` — что не отправлять в демон при сборке
|
Три формы:
|
||||||
|
|
||||||
В корне контекста создайте `.dockerignore`, чтобы не копировать мусор и секреты:
|
```dockerfile
|
||||||
|
CMD ["executable", "param1", "param2"]
|
||||||
|
CMD ["param1", "param2"]
|
||||||
|
CMD command param1 param2
|
||||||
|
```
|
||||||
|
|
||||||
|
| Форма | Смысл |
|
||||||
|
| ----------------------------------- | --------------------------------------------------------------------------------------- |
|
||||||
|
| **Exec** `["exe", "a"]` | Прямой запуск, PID 1 = `exe`, сигналы доходят нормально. |
|
||||||
|
| **Exec как аргументы к ENTRYPOINT** | Если задан `ENTRYPOINT`, `CMD` даёт только аргументы по умолчанию. |
|
||||||
|
| **Shell** `CMD a && b` | Через `sh -c`; PID 1 = shell - для сигналов и таймаутов остановки хуже, чем exec-форма. |
|
||||||
|
|
||||||
|
**Переопределение:** `docker run image ls` заменит `CMD` на `ls` (если не трогать `ENTRYPOINT`).
|
||||||
|
В файле допустима **одна** инструкция `CMD` (если несколько, то последняя выполняется).
|
||||||
|
|
||||||
|
## `ENTRYPOINT` - фиксированная «обёртка» запуска
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||||
|
ENTRYPOINT exec java -jar app.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Exec-форма** — как с `CMD`, хорошо для PID 1.
|
||||||
|
- **Shell-форма** — через `sh -c`.
|
||||||
|
|
||||||
|
Частый паттерн: `ENTRYPOINT` = скрипт или бинарник, `CMD` = аргументы по умолчанию. Тогда `docker run myimage --help` передаёт `--help` в entrypoint.
|
||||||
|
|
||||||
|
## `STOPSIGNAL` - сигнал остановки
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
STOPSIGNAL SIGTERM
|
||||||
|
```
|
||||||
|
|
||||||
|
Какой сигнал послать процессу при `docker stop` (по умолчанию обычно `SIGTERM`, потом `SIGKILL`). Нужен редко (например, для JVM или nginx с graceful shutdown).
|
||||||
|
|
||||||
|
## `HEALTHCHECK` - проверка «жив ли» контейнер
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
HEALTHCHECK [OPTIONS] CMD command
|
||||||
|
```
|
||||||
|
|
||||||
|
**OPTIONS:**
|
||||||
|
|
||||||
|
| Опция | Смысл |
|
||||||
|
|--------|--------|
|
||||||
|
| `--interval=DURATION` | Как часто (по умолчанию 30s). |
|
||||||
|
| `--timeout=DURATION` | Таймаут одной проверки (default 30s). |
|
||||||
|
| `--start-period=DURATION` | «Прогрев»: неудачи не считаются failure (default 0s). |
|
||||||
|
| `--retries=N` | Сколько подряд неуспехов → `unhealthy` (default 3). |
|
||||||
|
|
||||||
|
`CMD` здесь - команда проверки (часто `curl`/`wget` к localhost или скрипт).
|
||||||
|
`HEALTHCHECK NONE` - отключить наследованный healthcheck от базового образа.
|
||||||
|
|
||||||
|
## `SHELL` - оболочка для shell-форм
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
SHELL ["powershell", "-command"]
|
||||||
|
SHELL ["/bin/bash", "-c"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Меняет команду для **shell-формы** `RUN`, `CMD`, `ENTRYPOINT` на Windows/Linux.
|
||||||
|
|
||||||
|
## `ONBUILD` - отложенная инструкция для «дочерних» образов
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ONBUILD COPY . /app/src
|
||||||
|
```
|
||||||
|
|
||||||
|
Выполнится **не при сборке этого образа**, а когда **другой** Dockerfile сделает `FROM` этого образа. Сейчас редко используют (Compose/build args проще отследить).
|
||||||
|
|
||||||
|
## Многоэтапная сборка (`FROM ... AS` + `COPY --from`)
|
||||||
|
|
||||||
|
Несколько блоков `FROM ... AS builder` / `FROM ... AS production`. Из «тяжёлого» этапа в «лёгкий» переносят только артефакты:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM node:22-alpine AS build
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
```
|
||||||
|
|
||||||
|
Имена этапов - в `AS`; копирование - `COPY --from=build` или `--from=0` (индекс этапа).
|
||||||
|
|
||||||
|
## `COPY` vs `ADD` — что выбрать
|
||||||
|
|
||||||
|
| Задача | Инструкция |
|
||||||
|
| ----------------------------------- | --------------------------------------------------------------- |
|
||||||
|
| Файлы/папки из контекста в образ | **`COPY`** |
|
||||||
|
| Распаковать локальный `.tar` в слой | `ADD` (или `COPY` + `RUN tar`) |
|
||||||
|
| Скачать по URL | лучше `RUN curl`/`wget` с проверкой checksum; `ADD URL` — редко |
|
||||||
|
|
||||||
|
## `.dockerignore`
|
||||||
|
|
||||||
|
В корне **контекста** — шаблоны путей, которые **не отправляются** демону при сборке и недоступны для `COPY`/`ADD`:
|
||||||
|
|
||||||
```
|
```
|
||||||
.git
|
.git
|
||||||
.env
|
|
||||||
*.log
|
|
||||||
node_modules
|
node_modules
|
||||||
__pycache__
|
.env
|
||||||
|
*.md
|
||||||
```
|
```
|
||||||
|
|
||||||
**Скриншот:** сравнение размера контекста в логе сборки до/после добавления `.dockerignore` (если делали большую папку).
|
## Сборка и просмотр слоёв
|
||||||
|
|
||||||
<img src="./assets/docker_dockerignore_context_smaller.png" width="auto">
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## COPY vs ADD
|
|
||||||
|
|
||||||
- **`COPY`** — только копирование из контекста (предсказуемо, предпочтительно).
|
|
||||||
- **`ADD`** — то же плюс распаковка локальных tar и загрузка по URL (URL почти не используют; для tar — редко).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Многоэтапная сборка (multi-stage)
|
|
||||||
|
|
||||||
Первый этап — сборка (тяжёлые компиляторы), финальный образ — только артефакт. Пример идеи: этап `builder` с Node, финальный — `nginx` со статикой.
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
# syntax=docker/dockerfile:1
|
|
||||||
FROM node:22-alpine AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package.json package-lock.json ./
|
|
||||||
RUN npm ci
|
|
||||||
COPY src ./src
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
FROM nginx:1.27-alpine
|
|
||||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
|
||||||
EXPOSE 80
|
|
||||||
```
|
|
||||||
|
|
||||||
**Скриншот:** `docker images` — финальный образ заметно меньше, чем образ с полным Node (сравните REPOSITORY/TAG и SIZE).
|
|
||||||
|
|
||||||
<img src="./assets/docker_multistage_image_size.png" width="auto">
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Передача секретов при сборке (обзорно)
|
|
||||||
|
|
||||||
Не кладите пароли в `Dockerfile` в открытом виде. Варианты:
|
|
||||||
|
|
||||||
- BuildKit **secret mount**: `RUN --mount=type=secret ...` и `docker build --secret id=mysecret,src=.env`.
|
|
||||||
- **ARG** для некритичных параметров; помните, что значения ARG могут остаться в истории слоёв, если не обнулить.
|
|
||||||
|
|
||||||
Подробности — в [Dockerfile reference](https://docs.docker.com/reference/dockerfile/).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Прослойка образов: `docker history`
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
docker build -t my-web:1.0 -f Dockerfile .
|
||||||
docker history my-web:1.0
|
docker history my-web:1.0
|
||||||
```
|
```
|
||||||
|
## Готовый пример в репозитории
|
||||||
|
|
||||||
**Скриншот:** список слоёв и размеров.
|
Рабочие `Dockerfile` с `COPY`, `EXPOSE`, `HEALTHCHECK` и т.д. — в `docker/examples/multi-service/` (`web`, `api`, `proxy`). Связка с Compose — в части **4**.
|
||||||
|
|
||||||
<img src="./assets/docker_history_layers.png" width="auto">
|
## Документация
|
||||||
|
Полный список инструкций, edge cases и актуальные флаги [Dockerfile reference](https://docs.docker.com/reference/dockerfile/).
|
||||||
---
|
|
||||||
|
|
||||||
## Связь с Compose
|
|
||||||
|
|
||||||
В `docker-compose.yml` можно указать `build: .` для сервиса — Compose вызовет `docker build` с нужным контекстом. Полный стек — в части **4** и в каталоге `docker/examples/multi-service/`.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user