Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Senior: питання на співбесіді з теми «Продакшен і оркестрація»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

4 питання

Тег - змінне посилання: власник реєстру (чи будь-хто з правом запису) може перемістити app:1.4.2 на інший образ. Дайджест - SHA-256 від маніфесту образу:

docker pull ghcr.io/acme/app@sha256:4f8e0a...b21c
docker image ls --digests
docker buildx imagetools inspect ghcr.io/acme/app:1.4.2   # дайджест і платформи

Той самий дайджест завжди означає ті самі байти. Змінити вміст, не змінивши дайджесту, неможливо.

Що дає деплой за дайджестом:

  • відтворюваність: усі сервери, нові вузли при масштабуванні й перезапуски отримують точно той самий образ;
  • захист від підміни: скомпрометований чи помилково перезаписаний тег у реєстрі не змінить того, що розгортається;
  • точний аудит і відкат: у конфігурації деплою записаний конкретний образ, а не мітка, яка могла змінитися;
  • кешування: якщо дайджест не змінився, завантажувати нічого.

Мультиплатформні образи: для образу з кількома архітектурами (amd64, arm64) тег вказує на індекс (manifest list), а кожна платформа має свій дайджест. Зазвичай фіксують дайджест індексу - і кожен сервер сам обере потрібну архітектуру.

Практичний підхід - тег для людей, дайджест для машин:

  • CI збирає образ з тегами sha-a1b2c3d і 1.4.2, отримує дайджест і записує його в маніфест деплою (Kubernetes, Helm values, Compose-файл);
  • інструменти на кшталт Renovate оновлюють зафіксовані дайджести автоматично pull-request-ами.

Базові образи в Dockerfile теж можна фіксувати дайджестом:

FROM php:8.5-fpm-alpine@sha256:...

Тег лишається для читабельності, але використовується дайджест. Без цього той самий Dockerfile сьогодні й через місяць може зібрати різні образи - з іншою версією PHP чи системних бібліотек.

Ціна: дайджести нечитабельні, а оновлення базового образу (зокрема з виправленнями безпеки) перестає бути автоматичним - його треба робити свідомо, найкраще інструментом автоматичних оновлень залежностей.

Докладніше в документації: docker image pull: завантаження за дайджестом

Образ, що потрапляє на сервер, - результат довгого ланцюжка: базовий образ, системні пакети, залежності Composer і npm, CI, реєстр. Атака на будь-яку ланку (скомпрометований CI, підмінений образ у реєстрі, шкідливий пакет) дає зловмиснику код у продакшені. Захист - перевірювані відомості про образ.

Атестації BuildKit - метадані, прикріплені до образу під час збирання:

docker buildx build --sbom=true --provenance=mode=max -t ghcr.io/acme/app:1.4.2 --push .
  • provenance - як і з чого зібрано образ: репозиторій і коміт, параметри збирання, базові образи, середовище CI. За замовчуванням buildx додає мінімальну provenance-атестацію; mode=max - детальну;
  • SBOM (Software Bill of Materials) - перелік усіх пакетів і бібліотек в образі з версіями.
docker buildx imagetools inspect ghcr.io/acme/app:1.4.2 --format '{{ json .SBOM }}'

Навіщо SBOM: коли виходить критична вразливість у бібліотеці, за SBOM можна за хвилини знайти всі образи, що її містять, замість сканування кожного вручну. Сканери (Docker Scout, Trivy, Grype) використовують SBOM для пошуку CVE.

Підпис образів - криптографічне підтвердження, що образ зібрав саме ваш CI і він не змінювався:

cosign sign ghcr.io/acme/app@sha256:...
cosign verify ghcr.io/acme/app@sha256:... --certificate-identity=... --certificate-oidc-issuer=https://token.actions.githubusercontent.com

Cosign (проєкт Sigstore) підтримує «безключовий» підпис: CI отримує короткоживучий сертифікат через OIDC (наприклад, GitHub Actions), тож не треба зберігати довгоживучий приватний ключ.

Де це перевіряється:

  • політики допуску в Kubernetes (Kyverno, Sigstore policy-controller) - кластер не запустить непідписаний образ чи образ не з вашого репозиторію;
  • CI перед деплоєм - перевірка підпису й відсутності критичних вразливостей у SBOM.

Підписують дайджест, а не тег - тег можна перемістити, а підпис має стосуватися конкретного вмісту.

Рамки: SLSA описує рівні гарантій ланцюжка збирання; provenance BuildKit - крок до вищих рівнів.

Мінімум для невеликого проєкту: збирання лише в CI (не з ноутбуків), SBOM і сканування вразливостей, деплой за дайджестом. Підписи й політики допуску - наступний крок.

Докладніше в документації: Docker Build: атестації

Між «запускаю docker compose up по SSH» і «маємо кластер Kubernetes» є проміжний клас інструментів - PaaS для самостійного хостингу поверх Docker.

Kamal (від 37signals, творців Basecamp):

  • конфігурація в одному YAML, деплой командою kamal deploy по SSH на звичайні сервери;
  • збирає образ, завантажує в реєстр, запускає на серверах;
  • деплой без простою через власний проксі kamal-proxy: новий контейнер запускається, проходить перевірку стану, і лише тоді на нього перемикається трафік;
  • допоміжні сервіси (accessories) - база, Redis - як окремі контейнери;
  • без вебінтерфейсу й без «панелі» - інструмент командного рядка.

Coolify і Dokploy - самостійно розміщувані аналоги Heroku/Vercel з вебінтерфейсом:

  • деплой з Git-репозиторію чи образу, автоматичні збирання з Dockerfile чи Nixpacks/Buildpacks;
  • TLS-сертифікати, домени, змінні оточення, бази даних «в один клік», резервні копії;
  • кілька серверів (Dokploy використовує Docker Swarm для розподілу між вузлами).

Коли такого інструменту достатньо:

  • один чи кілька серверів, кілька застосунків;
  • команда без окремого DevOps-інженера;
  • потрібні деплой без простою, TLS, перезапуски, базові резервні копії - але не автомасштабування й складні мережеві політики;
  • важлива ціна: свої сервери (Hetzner, DigitalOcean) значно дешевші за керовані платформи.

Обмеження й ризики:

  • панель - теж частина інфраструктури: її треба оновлювати, захищати (доступ до панелі = доступ до всіх застосунків і секретів), резервувати;
  • відмовостійкість обмежена кількістю серверів і можливостями інструменту;
  • «магія» налаштувань: коли щось ламається, доводиться розбиратися, що саме панель згенерувала (Compose-файли, конфігурації проксі);
  • залежність від проєкту: розвиток і підтримка залежать від невеликої команди.

Порівняно з Kubernetes: значно менше понять і супроводу, але й менше гнучкості. Для більшості невеликих і середніх Laravel-застосунків такого рівня достатньо надовго.

Порівняно з керованими PaaS (Laravel Cloud, Render, Fly.io): дешевше й більше контролю, але відповідальність за сервери, оновлення ОС і безпеку - на вас.

Докладніше в документації: Документація Kamal

Контейнери одноразові, а томи - ні: там бази даних, завантажені файли, дані Redis. Резервна копія контейнерної інфраструктури - це насамперед копія томів і конфігурації.

Копія тому через тимчасовий контейнер (з документації Docker):

docker run --rm \
  -v app_storage:/data:ro \
  -v "$PWD":/backup \
  alpine tar czf /backup/storage-$(date +%F).tar.gz -C /data .

Відновлення - зворотна операція в новий том.

Бази даних - не копіювати файли працюючої бази. Копія каталогу даних PostgreSQL чи MySQL під час роботи може бути неузгодженою й непридатною до відновлення. Правильно:

  • логічний дамп засобами бази: docker exec db pg_dump -Fc app > app.dump, mysqldump --single-transaction;
  • фізичні бекапи з WAL/binlog (pgBackRest, WAL-G, Percona XtraBackup) - для великих баз і відновлення на момент часу;
  • або зупинка бази на час копіювання файлів - якщо простій допустимий.

Що ще входить у «відновити все»:

  • конфігурація: Compose-файли, змінні оточення, секрети (у сховищі секретів, а не лише на сервері);
  • образи: у реєстрі за незмінними тегами - щоб розгорнути ту саму версію;
  • файли користувачів: краще одразу в об'єктному сховищі (S3, R2) з версіонуванням, а не в томі на одному сервері;
  • інфраструктура як код: як заново створити сервер, мережу, DNS.

Правило 3-2-1: щонайменше 3 копії, на 2 різних типах носіїв, 1 - поза основною площадкою (інший провайдер чи регіон). Плюс незмінні копії (object lock), які не може видалити зловмисник чи програма-вимагач із доступом до сервера.

Плануючи відновлення, визначають:

  • RPO - скільки даних допустимо втратити (година? хвилина?) - визначає частоту копій;
  • RTO - за скільки часу треба відновитися - визначає підхід (запасний сервер, автоматизація).

Найважливіше - перевіряти відновлення. Регулярно (наприклад, щомісяця) розгортати копію в окремому середовищі й перевіряти, що застосунок працює. Неперевірена резервна копія часто виявляється порожньою, неповною чи без ключа розшифрування саме тоді, коли вона потрібна.

Моніторинг бекапів: сповіщення, якщо копія не створилася чи її розмір різко змінився.

Докладніше в документації: Томи: резервне копіювання й відновлення