Поясніть концепцію immutable infrastructure з Docker.
Immutable infrastructure це deployment-філософія: як runtime-instance deployed, він ніколи не модифікується in place. Update, patch і config-зміни відбуваються через build нового artifact (новий image, нова VM, новий container) і заміну старого. Docker enforce'ить це natural'но, бо image read-only, а container'и дешеві для recreate. Результат: reproducible, predictable-infrastructure.
Теорія
TL;DR
- Mutable: patch running-server in place (SSH,
apt upgrade, edit-config). State кожного сервера розходиться з часом. «Snowflake-server». - Immutable: build новий artifact (image), deploy, retire старий. Кожен instance identical. «Phoenix-server».
- Docker робить immutable легким: image = artifact, container = instance, redeploy = stop+start.
- State має бути external: DB на managed-сервісі або persistent-volume, file у object-storage, session у Redis. Сам container disposable.
- Rollback це просто «deploy попередній tag».
- Натурально комбінується з blue-green, canary, rolling-update.
Mental shift
Mutable mindset:
- «Сервер
prod-1крутиться 3 роки. Ми застосували 47 patch». - Config живе на disk; всі мають SSH-access; з часом, ні два сервера не identical.
- Нова версія = SSH-in, run installer, restart service.
- Drift між staging і production constant fight.
Immutable mindset:
- «Цей release це image-tag
1.7.3. Кожен running-container з того самого digest». - Config приходять з env-var або mounted-файлів на start-time.
- Нова версія = новий image, новий container, той самий image крутиться в dev/staging/prod.
- Drift impossible, бо нічого не модифікує running-instance.
Що йде поза container
Щоб immutable працював, все, що потребує change at runtime має жити поза:
| Concern | Де живе |
|---|---|
| Application-binary, lib, runtime | Всередині image (immutable). |
| Static-config, що варіюються by env | Env-var або mounted-file. |
| Secrets | Mounted з secret-manager (Vault, AWS Secrets Manager, Docker Secrets). |
| User-data, DB-state | External DB / managed-service / persistent-volume. |
| Uploaded-file | Object-storage (S3) або shared-volume. |
| Logі | Streaming у log-aggregator (Loki, ELK, CloudWatch). |
| Session | Redis, JWT або signed-cookie, ніколи in-memory, прив'язаний до single-container. |
Якщо щось з цього на writable-layer container, immutable зламано: заміна container втрачає дані.
Чому immutable виграє
- Reproducibility. Даний image-tag, run де завгодно, behave однаково. Dev = staging = prod.
- Легкий rollback. «Deploy
1.7.2знову». Одна команда. Без restoration system-state. - Без config-drift. Кожен container того ж tag bit-identical.
- Auditability. Що крутиться?
docker inspectпоказує image-digest. Trace до git-SHA через build-label. - Forces good hygiene. Не можеш SSH і «just fix it», pushing назад у image-build-process виробляє permanent-fix.
- Pair з deployment-патернами. Blue-green, canary, rolling, всі припускають identical-replica, які можна swap.
Trade-off
- Ціна externalization-state. Setup Postgres, Redis, S3 тощо більше upfront-work, ніж slap data на local-disk.
- Build-pipeline має бути solid. Якщо твій CI flaky, кожна зміна коштує.
- Image-size. 2 GB-image OK у mutable-land, але сповільнює immutable-redeploy. Оптимізуй image-size агресивно.
- Cold-start-ціна. Новий container starts cold; warm-cache gone. Мітигуй через startup-warmup або readiness-probe.
Приклади
Mutable vs Immutable: та сама зміна
Фікс: підняти max-body-size API з 1 MB до 5 MB.
Mutable workflow:
ssh prod-1 "sudo vi /etc/api/config.yaml"
# (edit max_body_size: 5MB)
ssh prod-1 "sudo systemctl restart api"
# Повторити на prod-2, prod-3...
# Забув prod-4. Тепер prod-4 має 1 MB-limit. Drift.Immutable workflow:
# Edit config у repo
git checkout -b bump-body-size
vi config/api.yaml # max_body_size: 5MB
git commit -am "Bump body size" && git push
# CI build'ить image myorg/api:1.7.4
# Deploy:
kubectl set image deployment/api api=myorg/api:1.7.4
# Або:
docker compose pull && docker compose up -d
# Кожен container підбирає новий image. Drift impossible.Externalization state
Добре:
# docker-compose.yaml
services:
app:
image: myorg/app:1.0
environment:
DATABASE_URL: ${DATABASE_URL}
REDIS_URL: ${REDIS_URL}
S3_BUCKET: my-uploads
# Нота: без «db»-сервісу. DB це RDS/Cloud SQL/тощо.Погано (state всередині container):
services:
app:
image: myorg/app:1.0
# Якщо втратимо цей container, втратимо дані!Immutable + blue-green
# Image v1 крутиться
docker run -d --name app-blue myorg/app:1.0
# Build і push v2
docker build -t myorg/app:2.0 .
docker push myorg/app:2.0
# Підняти green з нового image
docker run -d --name app-green myorg/app:2.0
# Traffic flip через load-balancer
# Підтверди, що v2 healthy
# Прибери blue
docker stop app-blue && docker rm app-blueBlue і green обидва immutable: blue крутить 1.0, green крутить 2.0, ні один не мутується mid-flight.
Immutable + canary
# 9 копій v1, 1 копія v2, load-balancer шле 10% на v2
# Дивись метрики. Якщо хороше, поступово заміни більше v1 на v2.Кожна копія immutable; rollout це серія замін, не in-place upgrade.
Immutable + rolling-update (Swarm)
docker service update --image myorg/app:2.0 myapp
# Swarm заміняє task one at a time, кожен task свіжий container з нового image.Pinning by digest для true immutability
image: myorg/app@sha256:abc123def456...Tag типу myorg/app:1.0 може бути re-pushed (хтось міг overwrite). Digest не може. Для максимальної reproducibility (і security), pin by digest у production.
# Знайди digest після push
docker inspect myorg/app:1.0 --format='{{.Id}}'
# sha256:abc...Build-system може lock digest у deploy-manifest:
image: myorg/app:1.0@sha256:abc123...Реальне застосування
- Microservice на Kubernetes: кожен Pod це container з конкретного image; без kubectl exec для fix bug у prod.
- Serverless / containers-as-a-service (Cloud Run, Fargate): platform enforce'ить immutability, не можеш SSH-in.
- Compose-managed dev-environment: redeploy на кожну зміну; container throwaway.
- CI build-agent: кожен job крутиться у fresh-container.
- Hardened production-environment: container-image підписані і scanned, deployed через GitOps (Argo CD, Flux). Уся pipeline immutable end-to-end.
Anti-patterns to avoid
SSH-in у running-container, щоб fix щось
docker exec -it api bash
# vi /etc/api/config.yaml ← ПОГАНОFix живе до restart container, потім gone. Гірше, відрізняється від твого image. Push fix у repo, rebuild, redeploy.
Зберігати дані у writable-layer container
Коли container заміщений, ці дані gone. Завжди бери volume або external-сервіси.
Re-use того ж tag для нових build
docker build -t myorg/app:latest .
docker push myorg/app:latest
# Тепер що це «:latest»? Вчорашній? Сьогоднішній?Бери meaningful-tag (semver, git-SHA, timestamp). Резервуй latest для dev-зручності; ніколи не deploy з latest у prod.
Treating host як immutable, а container як mutable
Якщо docker exec у container, щоб patch'ити, ти небагато виграв. Весь стек має слідувати дисципліні.
Типові помилки
Забувати, що volume ламає модель
Volume це mutable-state. Це OK, це externalized-data. Але розумій: коли redeploy, новий container reuse той самий volume. Якщо deploy-migration corrupt'ить дані, наступний deploy inherit corruption. Treat volume (і DB-schema) обережно.
Config запечений у image
COPY config/prod.yaml /etc/api/config.yamlТепер той самий image не portable через environment. Mount або env-inject config на run-time.
Long-lived container з hot-reload
Якщо твій dev-workflow це docker exec api npm run reload, ти зробив container mutable. Для dev це OK. Для prod, ніколи.
Питання для поглиблення
Q: Чи immutable infrastructure досяжна лише з container?
A: Ні. AMI, Packer-built-image, terraform-recreated-сервери всі enable. Container'и роблять дешевше, бо rebuild + redeploy швидкий.
Q: Що з secret, що змінюються без redeploy?
A: Mount їх з secret-manager (Vault, AWS, GCP). Container читає на startup або refresh периодично. Сам image без secret.
Q: Чи immutable значить, що я не можу restart container?
A: Restart OK, не модифікує image, лише re-run. «Immutable» referring до image і on-disk filesystem running-container, не його lifecycle.
Q: (Senior) Як reason'ити про довгий in-memory-state (cache-warmup, leader-election) під immutable?
A: Дві стратегії. (1) Make state externally-durable: leader-election через shared-сервіс (etcd, ZooKeeper); cache backed Redis. (2) Embrace cold-start: кожен новий container warmup from cold. Combine з rolling-deploy, щоб traffic shift поступово, без thundering-herd. Реальні системи беруть обидва: warm-cache коли важливо, externalize коли correctness залежить.
Q: (Senior) Як immutable infrastructure взаємодіє з regulated-environment (PCI, HIPAA)?
A: Прекрасно. Аудитори обожнюють. Кожна running-version мапиться назад до signed-image (cosign/Notary), який мапиться до CI-build, який мапиться до git-commit. Provenance end-to-end. Patching це code-change з PR, review і CI-artifact, не хтось SSH-in у prod і edit config. Більшість compliance-framework тепер явно favor immutable + GitOps як сильніший control-surface за mutable patch-management.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.
Коментарі
Ще немає коментарів