Контейнеризація на хостингу: як Docker перетворює хаос деплою на конвеєр, що працює без сюрпризів
Уявіть: ви зібрали проєкт локально, все працює ідеально. Натискаєте деплой - і на хостингу вилітає помилка, якої ви ніколи не бачили. Версія PHP не та. Бібліотека не встановлена. Конфіг nginx десь загубився між staging і production. Знайоме? Це класична проблема "works on my machine", і щороку вона з'їдає тисячі людино-годин у командах від фрілансерів до корпорацій. Docker вирішує це елегантно - він пакує ваш застосунок разом з усім його оточенням у контейнер, який однаково працює скрізь. Але як саме запустити контейнери на реальному хостингу, а не тільки на ноутбуці? Давайте розберемо покроково.
Чому "просто залити файли на сервер" більше не працює
Традиційний деплой - це як переїзд у нову квартиру, де ви перевозите речі, але забуваєте розетки, водопровід і навіть стіни. Ви копіюєте код, але середовище на сервері живе своїм життям: інша версія MySQL, інші розширення PHP, інші права на папки. Кожен деплой перетворюється на лотерею.
Docker усуває цю лотерею повністю. Контейнер - це не віртуальна машина. Це ізольований процес, який використовує ядро хост-системи, але має власну файлову систему, мережу і залежності. Результат? Контейнер стартує за секунди, споживає мінімум ресурсів і гарантовано працює однаково на вашому ноутбуці, на staging-сервері та на продакшн-VPS.
Ось що це дає на практиці:
- Відтворюваність - збірка з однаковим результатом хоч на 1, хоч на 100 серверах
- Ізоляція - один контейнер впав, інші навіть не помітили
- Швидкість деплою - замість 20 хвилин ручного налаштування за 30 секунд
- Легкий відкат - попередня версія образу доступна миттєво

Що потрібно на хостингу для запуску Docker
Не кожен хостинг дозволить вам запустити контейнери. Shared-хостинг - відразу ні. Вам потрібен як мінімум VPS або виділений сервер з root-доступом. Ось мінімальні вимоги, щоб все працювало без болю:
| Параметр | Мінімум для старту | Рекомендовано для продакшну |
|---|---|---|
| ОС | Ubuntu 22.04 / Debian 12 | Ubuntu 24.04 LTS |
| RAM | 1 GB | 4 GB+ |
| CPU | 1 ядро | 2+ ядра |
| Диск | 20 GB SSD | 50 GB+ NVMe |
| Docker версія | 24.x | 27.x (остання стабільна) |
| Docker Compose | v2.20+ | v2.30+ |
Деякі хостинг-провайдери вже пропонують VPS з попередньо встановленим Docker. Це зручно, але я рекомендую ставити самостійно - так ви точно знатимете, яка версія і з якими параметрами працює. Інсталяція займає буквально 5 хвилин.
Перший Dockerfile: від нуля до робочого контейнера
Dockerfile - це рецепт вашого контейнера. Простий текстовий файл, який описує, що всередині. Ось мінімальний приклад для типового PHP-проєкту з Nginx:
Крок перший - створіть Dockerfile у корені проєкту:
- Оберіть базовий образ - наприклад,
php:8.3-fpm-alpine. Alpine-версії важать 50-80 MB замість 400+ MB у стандартних. Менше вага - швидше деплой. - Встановіть залежності - через
RUN apt-get installабоapk addдля Alpine. Кожна команда RUN створює новий шар образу, тому об'єднуйте їх через&&. - Скопіюйте код - інструкція
COPY . /var/www/htmlперенесе ваш проєкт у контейнер. - Відкрийте порт -
EXPOSE 9000для PHP-FPM абоEXPOSE 80для веб-серверу. - Задайте команду запуску -
CMD ["php-fpm"]. Це те, що виконається при старті контейнера.
"Найгірше, що ви можете зробити з Docker - це ставитися до контейнера як до віртуальної машини. Не входьте в нього через SSH, не ставте туди cron, не зберігайте дані всередині. Контейнер має бути одноразовим - зупинив, видалив, запустив новий." - Kelsey Hightower, Google Cloud
Після створення Dockerfile збираєте образ командою docker build -t myapp:1.0 . і запускаєте через docker run -d -p 80:80 myapp:1.0. Ваш застосунок працює у контейнері. Точка.

Docker Compose: коли одного контейнера замало
Реальний проєкт - це не один контейнер. Це PHP-FPM + Nginx + MySQL + Redis + може ще якийсь воркер для черг. Запускати кожен окремо через docker run - це як мити посуд у річці, коли вдома є посудомийка.
Docker Compose дозволяє описати всю інфраструктуру в одному файлі docker-compose.yml. Ось що він робить за вас:
- Створює ізольовану мережу між контейнерами - вони бачать одне одного за іменами сервісів
- Керує volumes - щоб дані MySQL не зникали після перезапуску
- Визначає порядок запуску - база раніше за застосунок
- Дозволяє масштабувати -
docker compose up - scale worker=3і у вас три воркери
Типовий docker-compose.yml для веб-проєкту містить 40-60 рядків і замінює години ручного конфігурування. Одна команда docker compose up -d - і весь стек піднімається за секунди. Запам'ятайте це: вся інфраструктура проєкту має жити у коді, а не в голові одного девопса.
Безпека контейнерів: те, про що забувають 70% команд
Docker не робить вас захищеним автоматично. Навпаки - неправильно налаштований контейнер може стати ширшою дірою, ніж звичайний сервер. Ось ключові правила, які я виніс з реальних інцидентів:
- Ніколи не запускайте процеси від root всередині контейнера. Додайте
USER appuserу Dockerfile. Якщо контейнер зламають - зловмисник отримає мінімальні привілеї. - Не використовуйте тег
:latestу продакшні. Сьогодні latest - це 8.3, а завтра - 9.0 з breaking changes. Фіксуйте версії:php:8.3.12-fpm-alpine3.20. - Скануйте образи на вразливості. Інструменти на кшталт Trivy або Docker Scout знаходять CVE у базових образах до того, як їх знайдуть хакери.
- Обмежуйте ресурси. Параметри
- memory=512m - cpus=1не дозволять одному контейнеру з'їсти весь сервер. - Секрети - тільки через Docker Secrets або змінні оточення, а не хардкод у Dockerfile. Ніколи.
Якщо ваш Docker-сокет (/var/run/docker.sock) доступний ззовні або змонтований у контейнер без потреби - це еквівалент root-доступу до хоста. Перевірте це прямо зараз.

Автоматичний деплой: від git push до оновленого сайту за 90 секунд
Руками заходити на сервер і писати docker compose pull && docker compose up -d - нормально для хобі-проєкту. Для чогось серйозного потрібен CI/CD-пайплайн. І з Docker це реалізувати простіше, ніж здається.
Схема виглядає так: ви пушите код у Git - GitHub Actions (або GitLab CI, або навіть простий вебхук) збирає новий Docker-образ - публікує його в реєстрі (Docker Hub, GitHub Container Registry, приватний) - підключається до сервера по SSH - виконує docker compose pull та docker compose up -d. Все. Даунтайм - менше 5 секунд завдяки тому, що новий контейнер стартує раніше, ніж зупиняється старий.
Порада з власного досвіду: тримайте docker-compose.yml і Dockerfile в тому ж репозиторії, що й код. Інфраструктура і застосунок мають версіонуватися разом. Якщо щось зламалося - ви просто відкочуєте один комміт, а не гадаєте, яка комбінація коду і конфігу працювала минулого четверга.
Де Docker не потрібен - і це теж нормально
Я не з тих, хто каже "Docker всюди". Є випадки, коли контейнеризація додає складності без реальної користі:
- Одна проста WordPress-сторінка на shared-хостингу - серйозно, не треба
- Команда з однієї людини без досвіду Linux - крива навчання з'їсть час, який краще витратити на продукт
- Легасі-проєкт, що тримається на магії і молитвах - контейнеризація не виправить архітектуру, вона тільки законсервує хаос
Але якщо ваш проєкт росте, команда більше двох людей, і ви хоча б раз чули фразу "у мене локально все працює" - Docker не просто корисний. Він необхідний.
Питання до вас: скільки разів за останній місяць ви витратили більше 10 хвилин на деплой через розбіжність середовищ? Якщо хоча б раз - ви знаєте, що робити. А якщо жодного - або ви вже використовуєте Docker, або вам просто поки що щастить.