Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124


Якщо ви працюєте з PHP вже якийсь час, напевно стикалися з проблемою “у мене працює, а в колеги ні”. Різні версії PHP, налаштування операційних систем, розширення — все це створює головний біль під час командної розробки. Docker вирішує цю проблему раз і назавжди, створюючи однакові ізольовані середовища для всіх учасників проєкту. У цій статті я розповім, як я використовую Docker для PHP розробки — від локального середовища до повноцінного продакшену.
Коли я тільки почав використовувати Docker для PHP проєктів, найбільше мене вразила простота налаштування нового середовища. Замість того, щоб встановлювати Apache або Nginx, PHP потрібної версії, MySQL, Redis та інші залежності вручну, я просто запускаю одну команду — і все готове до роботи.
Docker створює контейнери — легкі віртуальні середовища, які містять все необхідне для роботи додатка. На відміну від повноцінних віртуальних машин, контейнери не емулюють апаратне забезпечення, а використовують ядро операційної системи хоста. Це робить їх швидкими та економними щодо ресурсів.
Плюси Docker у PHP розробці:
Мінуси та підводні камені:
Перш ніж почати працювати з Docker, потрібно встановити Docker Desktop (для Windows та macOS) або Docker Engine (для Linux). Я рекомендую завжди використовувати останню стабільну версію. Процес встановлення простий — завантажуєте інсталятор з офіційного сайту Docker і слідуєте інструкціям майстра встановлення.
Після встановлення перевірте, чи все працює правильно, виконавши команду в терміналі:
# Перевірка версії Docker
docker --version
# Перевірка версії Docker Compose
docker-compose --version
# Тестовий запуск контейнера
docker run hello-worldCode language: PHP (php)Якщо все встановлено коректно, ви побачите привітальне повідомлення від Docker. Тепер можемо переходити до створення власного PHP середовища.
Dockerfile — це текстовий файл з інструкціями, як побудувати Docker образ. Для PHP проєкту базовий Dockerfile може виглядати так:
# Використовуємо офіційний PHP образ з Apache
FROM php:8.2-apache
# Встановлюємо системні залежності
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Очищаємо кеш apt
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Встановлюємо PHP розширення
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Встановлюємо Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Встановлюємо робочу директорію
WORKDIR /var/www/html
# Копіюємо файли проєкту
COPY . /var/www/html
# Встановлюємо залежності через Composer
RUN composer install --no-dev --optimize-autoloader
# Налаштовуємо права доступу
RUN chown -R www-data:www-data /var/www/html
# Відкриваємо порт 80
EXPOSE 80Code language: PHP (php)Цей Dockerfile створює образ з PHP 8.2, Apache, необхідними розширеннями та Composer. Важливий момент — я завжди використовую офіційні образи PHP як базу, оскільки вони регулярно оновлюються та оптимізовані для продакшену.
Один з найбільших помилок початківців — створення надто великих образів. Я навчився використовувати multi-stage builds для зменшення розміру фінального образу. Ось приклад оптимізованого Dockerfile:
# Стадія 1: Збірка залежностей
FROM composer:latest AS composer-build
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --optimize-autoloader
# Стадія 2: Фінальний образ
FROM php:8.2-apache-alpine
WORKDIR /var/www/html
# Копіюємо тільки потрібні файли з попередньої стадії
COPY --from=composer-build /app/vendor ./vendor
COPY . .
# Налаштовуємо Apache
RUN sed -i 's!/var/www/html!/var/www/html/public!g' /etc/apache2/sites-available/000-default.conf
RUN a2enmod rewrite
EXPOSE 80Code language: PHP (php)Використання Alpine Linux як базового образу може зменшити розмір на 70-90% порівняно зі стандартним Debian-based образом. Це критично для продакшену, де кожен мегабайт впливає на швидкість деплою.
Реальні PHP додатки рідко складаються з одного контейнера. Зазвичай потрібен веб-сервер, база даних, Redis для кешування, можливо черги. Docker Compose дозволяє описати всю інфраструктуру в одному файлі docker-compose.yml і запускати все однією командою.
version: '3.8'
services:
# PHP + Apache сервіс
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:80"
volumes:
- ./:/var/www/html
depends_on:
- db
- redis
environment:
- DB_HOST=db
- DB_DATABASE=myapp
- DB_USERNAME=root
- DB_PASSWORD=secret
- REDIS_HOST=redis
# MySQL база даних
db:
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: myapp
MYSQL_ROOT_PASSWORD: secret
volumes:
- db-data:/var/lib/mysql
# Redis для кешування
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
db-data:Code language: PHP (php)Тепер запустити всю інфраструктуру можна однією командою docker-compose up -d. Параметр -d запускає контейнери в фоновому режимі. Щоб зупинити — виконайте docker-compose down.
Одне з питань, яке часто задають — як налагоджувати PHP код у Docker контейнерах. Я використовую Xdebug, який чудово працює з контейнерами. Потрібно лише додати кілька рядків у Dockerfile:
# Встановлюємо Xdebug
RUN pecl install xdebug && docker-php-ext-enable xdebug
# Налаштовуємо Xdebug
RUN echo "xdebug.mode=debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo "xdebug.client_port=9003" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.iniCode language: PHP (php)Після цього налаштуйте ваше IDE (PHPStorm або VS Code) для роботи з Xdebug на порту 9003, і можете ставити breakpoints як зазвичай. Важливо — використовуйте host.docker.internal замість localhost для з’єднання з IDE на хості.
За роки роботи з Docker я склав список команд, які використовую щодня:
# Запустити команду всередині контейнера
docker-compose exec app php artisan migrate
# Переглянути логи контейнера
docker-compose logs -f app
# Зайти в bash контейнера
docker-compose exec app bash
# Перебудувати образ після змін у Dockerfile
docker-compose build --no-cache app
# Очистити невикористовувані образи та контейнери
docker system prune -a
# Переглянути запущені контейнери
docker ps
# Зупинити всі контейнери
docker-compose down -vCode language: PHP (php)Використання Docker для PHP розробки локально — це одне, а продакшн — зовсім інше. Тут критично важливі безпека, продуктивність та надійність. Я завжди створюю окремий Dockerfile для продакшену з додатковими оптимізаціями.
По-перше, ніколи не використовуйте тег latest для продакшн образів. Завжди вказуйте конкретну версію — наприклад, php:8.2.15-apache. Це забезпечує передбачуваність та усуває ризик несподіваних оновлень.
# Production Dockerfile
FROM php:8.2.15-apache-alpine AS production
# Встановлюємо тільки необхідні залежності
RUN apk add --no-cache \
mysql-client \
libpng-dev \
oniguruma-dev \
libxml2-dev
# Встановлюємо PHP розширення
RUN docker-php-ext-install pdo_mysql opcache
# Налаштовуємо OPcache для продакшену
RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.memory_consumption=256" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.max_accelerated_files=20000" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.validate_timestamps=0" >> /usr/local/etc/php/conf.d/opcache.ini
# Копіюємо код додатку
COPY --chown=www-data:www-data . /var/www/html
# Встановлюємо залежності
RUN composer install --no-dev --optimize-autoloader --no-scripts
# Вимикаємо небезпечні функції PHP
RUN echo "disable_functions=exec,passthru,shell_exec,system,proc_open,popen" >> /usr/local/etc/php/conf.d/security.ini
EXPOSE 80
USER www-dataCode language: PHP (php)Зверніть увагу на кілька важливих моментів: вимкнено валідацію timestamps для OPcache (оскільки на продакшені код не змінюється), заборонено небезпечні PHP функції, та контейнер запускається від непривілейованого користувача www-data.
Для продакшн середовищ Docker Compose вже недостатньо. Потрібна повноцінна система оркестрації — Kubernetes або Docker Swarm. Я зазвичай використовую Kubernetes для великих проєктів та Docker Swarm для менших, де Kubernetes був би надмірним.
Kubernetes надає автоматичне масштабування, self-healing, rolling updates та багато інших корисних можливостей. Проте налаштування Kubernetes складніше, ніж Docker Compose. Для PHP додатків я рекомендую використовувати готові Helm charts, які спрощують деплой.
Безпека Docker контейнерів — це окрема велика тема. Основні правила, яких я дотримуюсь: завжди використовуйте офіційні образи або перевірені образи з Docker Hub, регулярно оновлюйте базові образи, не зберігайте чутливі дані в образах, та запускайте контейнери від непривілейованих користувачів.
# Приклад використання .dockerignore
.git
.gitignore
.env
.env.example
node_modules
vendor
storage/logs/*
storage/framework/cache/*
tests
README.md
docker-compose.ymlCode language: PHP (php)Файл .dockerignore працює як .gitignore, але для Docker. Він запобігає копіюванню непотрібних файлів в образ, що зменшує його розмір та покращує безпеку. Особливо важливо виключити .env файли з чутливими даними.
Також рекомендую використовувати інструменти сканування безпеки для Docker образів. Trivy або Snyk можуть автоматично виявляти вразливості у ваших контейнерах:
# Сканування образу на вразливості
docker run aquasec/trivy image your-php-app:latest
# Або використовуйте Docker Scout (вбудований в Docker Desktop)
docker scout cves your-php-app:latestCode language: PHP (php)Коли ваші PHP додатки працюють у Docker контейнерах на продакшені, критично важливо мати належний моніторинг. Я використовую комбінацію Prometheus для метрик та ELK stack (Elasticsearch, Logstash, Kibana) для централізованого логування.
Docker має вбудовану підтримку різних драйверів логування. За замовчуванням використовується json-file, але для продакшену краще налаштувати відправку логів у централізовану систему:
version: '3.8'
services:
app:
image: your-php-app:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Або використовуйте syslog для централізованого логування
# logging:
# driver: "syslog"
# options:
# syslog-address: "tcp://logs.example.com:514"Code language: PHP (php)Обов’язково налаштуйте ротацію логів, щоб вони не забивали диск. Я завжди обмежую розмір файлу логу до 10MB та зберігаю максимум 3 останні файли.


Одне з найпоширеніших питань — чи не сповільнює Docker PHP додатки. Відповідь — залежить від налаштувань. На Linux продуктивність практично ідентична нативному запуску. На macOS та Windows можуть бути проблеми через віртуалізацію файлової системи.
Основна рекомендація для покращення продуктивності на Mac та Windows — використовуйте named volumes замість bind mounts для папок, до яких додаток часто звертається (наприклад, vendor або node_modules). Це радикально покращує швидкість роботи:
version: '3.8'
services:
app:
volumes:
# Код проєкту як bind mount
- ./:/var/www/html
# Vendor як named volume для швидкості
- vendor-volume:/var/www/html/vendor
- node-modules-volume:/var/www/html/node_modules
volumes:
vendor-volume:
node-modules-volume:Code language: PHP (php)Також важливо правильно налаштувати ресурси для Docker Desktop. Виділіть достатньо CPU та RAM — я рекомендую мінімум 4 CPU cores та 8GB RAM для комфортної роботи з PHP проєктами.
Docker ідеально інтегрується з CI/CD системами. Я використовую GitHub Actions для автоматизації тестування та деплою PHP додатків. Ось приклад базового workflow:
name: Docker Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Run tests in container
run: |
docker run myapp:${{ github.sha }} php vendor/bin/phpunit
- name: Push to registry
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker tag myapp:${{ github.sha }} username/myapp:latest
docker push username/myapp:latestCode language: HTTP (http)Цей workflow автоматично будує Docker образ при кожному push до main гілки, запускає тести всередині контейнера, та відправляє успішний образ до Docker Hub або іншого registry.
Docker кардинально змінив мій підхід до PHP розробки. Те, що раніше займало години налаштування — тепер справа кількох хвилин. Командна робота стала набагато простішою, оскільки всі працюють в ідентичних середовищах. А деплой на продакшн перестав бути головним болем.
Так, Docker має свою криву навчання. Перші кілька днів або тижнів можуть здаватися складними. Але інвестиція часу окупається багаторазово. Почніть з простого — базовий Dockerfile та docker-compose.yml для локальної розробки. Поступово додавайте оптимізації, налаштування безпеки та автоматизацію.
Найважливіше — не бійтеся експериментувати. Docker дозволяє швидко створювати та видаляти контейнери без ризику пошкодити вашу систему. Це ідеальний інструмент для навчання та експериментів з різними конфігураціями PHP середовищ.