This commit is contained in:
chase
2026-05-04 11:07:31 +03:00
commit 52280c721f
44 changed files with 991 additions and 0 deletions
@@ -0,0 +1,162 @@
## Зачем нужен Dockerfile
`Dockerfile` — это **рецепт** сборки образа: от какого базового образа начать, какие пакеты установить, какие файлы скопировать, какую команду запускать по умолчанию. Команда сборки:
```
docker build -t my-app:1.0 -f Dockerfile /path/to/context
```
**Контекст сборки** — каталог, который вы передаёте последним аргументом (часто `.`). В образ попадают только файлы из контекста (по правилам `.dockerignore`).
---
## Минимальный Dockerfile и сборка
Готовый вариант каталога **web** лежит в репозитории: `docker/examples/multi-service/web/` — можно собирать оттуда (`docker build -t my-web:1.0 ./web` из корня `multi-service`). Ниже — пошагово «с нуля»:
```
mkdir -p ~/learn-docker/web && cd ~/learn-docker/web
```
Содержимое `Dockerfile` (ниже — максимально «говорящий» вариант с комментариями; в реальном файле комментарии допустимы):
```dockerfile
# Синтаксис Dockerfile (опционально, для BuildKit features)
# syntax=docker/dockerfile:1
# Базовый образ: лучше фиксировать мажорную версию и по возможности slim/alpine
FROM nginx:1.27-alpine
# Метаданные (удобно в docker inspect / реестрах)
LABEL org.opencontainers.image.title="Demo static site"
LABEL org.opencontainers.image.description="Nginx with baked-in HTML from COPY"
# Переменные на этапе сборки (не попадают в runtime автоматически как ENV)
ARG BUILD_DATE=unknown
LABEL build-date="${BUILD_DATE}"
# Переменные окружения внутри контейнера при запуске
ENV NGINX_ENTRYPOINT_QUIET_LOGS=1
# Рабочая директория для последующих инструкций
WORKDIR /usr/share/nginx/html
# Копирование файлов ИЗ контекста сборки В образ (ключевой способ «положить файлы в образ»)
COPY ./html/ /usr/share/nginx/html/
# Права (nginx в alpine часто от uid 101 — для продакшена уточняйте образ)
RUN chown -R nginx:nginx /usr/share/nginx/html
# Документируем порт (не открывает его само по себе на хосте — это метаданные)
EXPOSE 80
# Healthcheck — Docker помечает контейнер unhealthy при ошибках (оркестраторы могут рестартовать)
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`:
```html
<!DOCTYPE html>
<html lang="ru">
<head><meta charset="utf-8"><title>Docker COPY demo</title></head>
<body><h1>Файл попал в образ через COPY</h1></body>
</html>
```
Сборка и запуск:
```
docker build -t my-web:1.0 .
docker run -d --name from-dockerfile -p 8090:80 my-web:1.0
```
**Скриншот:** этапы сборки `Step ...` и успешное `Successfully tagged my-web:1.0`.
<img src="./assets/docker_build_steps_tagged.png" width="auto">
**Скриншот:** браузер на порту 8090 с вашим заголовком.
<img src="./assets/docker_browser_copy_demo.png" width="auto">
---
## `.dockerignore` — что не отправлять в демон при сборке
В корне контекста создайте `.dockerignore`, чтобы не копировать мусор и секреты:
```
.git
.env
*.log
node_modules
__pycache__
```
**Скриншот:** сравнение размера контекста в логе сборки до/после добавления `.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 history my-web:1.0
```
**Скриншот:** список слоёв и размеров.
<img src="./assets/docker_history_layers.png" width="auto">
---
## Связь с Compose
В `docker-compose.yml` можно указать `build: .` для сервиса — Compose вызовет `docker build` с нужным контекстом. Полный стек — в части **4** и в каталоге `docker/examples/multi-service/`.