Контейнеризация для PHP‑приложений стала стандартом в разработке и эксплуатации: ускоряется доставка релизов, упрощается воспроизводимость окружений, повышается управляемость зависимостей. На практике команды выбирают между двумя распространёнными подходами: Docker‑Compose и Kubernetes‑манифестами. Первый часто закрывает задачи разработки и небольших контуров, второй — обеспечивает масштабирование, управляемость и стандартизацию для сложных систем.
В этой статье разберём различия, архитектурные паттерны, типовые сценарии, и как встроить контейнеризацию в процесс с учётом актуальных требований российского законодательства (включая требования к обработке персональных данных, информационной безопасности и документированию процессов).
Контекст: что именно «контейнеризуем» в PHP
Под «PHP‑приложением» обычно понимают набор сервисов:
- web‑контур: PHP‑FPM или Apache/Nginx с PHP (часто связка Nginx + PHP‑FPM);
- приложение: codebase, зависимости (Composer), кэш (opcache), фоновые задачи;
- хранилище: MySQL/PostgreSQL, иногда Redis;
- очереди/события: например, RabbitMQ/Redis Streams;
- наблюдаемость: логи, метрики, трассировки;
- секреты: переменные окружения, токены, пароли, сертификаты.
Ключевой момент: контейнер — это не «инфраструктура вместо безопасности», а механизм упаковки. Поэтому архитектура контейнеров должна учитывать требования к доступам, журналированию, защите секретов и контролю изменений.
Docker‑Compose: когда он уместен
Docker‑Compose — это удобный инструмент для описания многоконтейнерного окружения в одном файле (YAML) и запуска через одну команду. Его сила — скорость старта и прозрачность для разработчиков.
Плюсы Docker‑Compose
- Быстрое локальное воспроизведение: единый контур «как у команды»;
- Низкий порог входа: понятные сервисы, сети и тома;
- Лучшая воспроизводимость для интеграционных тестов;
- Простое документирование: один compose‑файл как «истина для окружения».
Ограничения Docker‑Compose
- Скалирование обычно ограничено возможностями Docker‑хоста и настройками оркестрации;
- Управление жизненным циклом (rollout/rollback, autoscaling) требует ручной дисциплины;
- Сетевая политика и сегментация обычно менее формализованы;
- Стандартизация на уровне организации сложнее: разные команды могут держать разные практики.
Kubernetes: когда нужны манифесты
Kubernetes обеспечивает оркестрацию контейнеров в кластере: управление репликами, обновлениями, отказоустойчивостью, секретами и конфигурациями. Манифесты дают декларативный подход: инфраструктура описывается версионно и воспроизводимо.
Плюсы Kubernetes‑подхода
- Управляемые обновления (rolling updates, управляемые пайплайны релизов);
- Отказоустойчивость за счёт реплик и стратегий;
- Горизонтальное масштабирование (HPA/VPA по метрикам);
- Стандартизация инфраструктуры и доступов (RBAC, admission policies);
- Сетевая сегментация (NetworkPolicies) для уменьшения площади атаки.
Ограничения Kubernetes
- Более высокая сложность в эксплуатации и обучении;
- Нужны процессы для безопасного выпуска изменений (CI/CD, контроль образов, секреты);
- Дополнительная стоимость (инфраструктура кластера, мониторинг, поддержку).
Сравнение по ключевым критериям
- Разработка и тестирование: Compose — быстрее старт, Kubernetes — если нужен максимально «боевой» контур для e2e.
- Производственная эксплуатация: Kubernetes чаще предпочтительнее из‑за управляемости и масштабирования.
- Безопасность: Kubernetes позволяет выстроить RBAC/NetworkPolicies/admission control более формально; в Compose это проще только на уровне локального контура.
- Аудит изменений: манифесты и GitOps‑подход облегчают трассировку «кто/когда/что изменил».
- Стоимость владения: Compose дешевле и проще для небольших систем.
Архитектурные практики для PHP‑контейнеров
Независимо от инструмента оркестрации, для PHP‑контейнеров важно:
- Разделить build и runtime: многослойные Docker‑образы, минимальный runtime‑слой;
- Исключить запуск от root и обеспечить корректные права на рабочие директории;
- Вынести конфигурацию через env/ConfigMap (в Kubernetes) или env‑файлы (в Compose);
- Обеспечить хранение секретов через секреты (Kubernetes Secrets/внешнее хранилище) и исключить их из образов;
- Настроить PHP‑FPM под лимиты ресурсов контейнера;
- Контроль логирования: stdout/stderr для централизованного сбора логов;
- Версионность зависимостей: lock‑файл Composer, запрет «непредсказуемых» установок в продакшене.
Пример: Dockerfile для PHP‑приложения (под Compose и Kubernetes)
# Пример Dockerfile (упрощённый, требует адаптации под ваш проект)
FROM php:8.3-fpm-alpine AS base
# Важно: минимизация зависимостей и защита от выполнения лишнего
RUN set -eux;
apk add --no-cache --virtual .build-deps $PHPIZE_DEPS;
apk add --no-cache git zip unzip;
# Рабочая директория
WORKDIR /var/www/app
# Composer install в отдельном слое
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
COPY composer.json composer.lock ./
RUN set -eux;
composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader;
# Копируем исходники
COPY . .
# Права на директории, где требуется запись (адаптируйте под фреймворк)
RUN set -eux;
mkdir -p var/cache var/log;
chown -R www-data:www-data /var/www/app
# Переключаемся на непривилегированного пользователя
USER www-data
# PHP‑FPM по умолчанию
CMD ["php-fpm", "-F"]Docker‑Compose: пример compose‑сценария
Compose обычно описывает окружение для разработки/интеграции: web + db + redis. Пример ниже демонстрирует общий подход: конфигурация через переменные окружения, тома для данных, отдельная сеть.
version: "3.9"
services:
app:
build: .
container_name: php-app
environment:
APP_ENV: "dev"
DATABASE_URL: "mysql://app:app@db:3306/app"
REDIS_URL: "redis://redis:6379/0"
depends_on:
- db
- redis
networks:
- app-net
web:
image: nginx:1.27-alpine
container_name: nginx
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app
networks:
- app-net
db:
image: mysql:8.4
container_name: mysql
environment:
MYSQL_DATABASE: app
MYSQL_USER: app
MYSQL_PASSWORD: app
MYSQL_ROOT_PASSWORD: root-password-change-me
volumes:
- db-data:/var/lib/mysql
networks:
- app-net
redis:
image: redis:7.4-alpine
container_name: redis
volumes:
- redis-data:/data
networks:
- app-net
networks:
app-net:
volumes:
db-data:
redis-data:Практический совет для безопасности в Compose: не храните реальные секреты в репозитории. Используйте .env вне git, secret‑механизмы CI или локальные хранилища.
Kubernetes: манифесты для PHP‑приложения
В Kubernetes для PHP‑приложения обычно создают:
- Deployment — нужное число реплик и стратегия обновлений;
- Service — адресация внутри кластера;
- Ingress — маршрутизация HTTP;
- ConfigMap/Secret — конфигурация и секреты;
- NetworkPolicy — ограничение сетевого доступа;
- PodSecurity (или политики уровня кластера) — запрет небезопасных режимов.
Пример: Deployment + Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-app
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: php-app
template:
metadata:
labels:
app: php-app
spec:
# Принцип минимальных привилегий
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: registry.local/php-app:1.0.0
ports:
- containerPort: 9000 # php-fpm (пример)
env:
- name: APP_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: DATABASE_URL
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
readinessProbe:
# Проба зависит от вашей архитектуры (HTTP/fastcgi/скрипт)
exec:
command: ["sh","-c","php -v >/dev/null 2>&1"]
initialDelaySeconds: 10
periodSeconds: 10
livenessProbe:
exec:
command: ["sh","-c","php -v >/dev/null 2>&1"]
initialDelaySeconds: 30
periodSeconds: 20
---
apiVersion: v1
kind: Service
metadata:
name: php-app
spec:
selector:
app: php-app
ports:
- name: fpm
port: 9000
targetPort: 9000
type: ClusterIPIngress/маршрутизация и TLS
На уровне Kubernetes обеспечьте HTTPS, используйте управляемые сертификаты (например, через Ingress‑контроллер) и запретите слабые протоколы. Важно: сертификаты и ключи — это тоже секреты, их нельзя закладывать в образ.
Соответствие требованиям РФ: что учесть при внедрении
Контейнеризация сама по себе не является «юридическим объектом», но она влияет на исполнение обязанностей по информационной безопасности и обработке данных. Ниже — практические точки, которые обычно необходимы в проектах, работающих с персональными данными и/или в значимых инфраструктурах.
1) Персональные данные (152‑ФЗ): безопасность и контроль обработки
Если PHP‑приложение обрабатывает персональные данные, то вы обязаны обеспечить условия, исключающие неправомерный доступ, уничтожение, блокирование и иные нарушения. На уровне контейнеров это означает:
- Разграничение доступа к данным и интерфейсам (минимальные права, RBAC, отдельные namespaces);
- Шифрование трафика (TLS) и контроль каналов обмена;
- Защита секретов (секреты в хранилищах, ротация, отсутствие в образах/логах);
- Журналирование действий (доступы, изменения, ошибки авторизации);
- Контроль целостности образов и манифестов (версионность, подпись/происхождение артефактов при наличии требований);
- Ограничение перемещений в сети (NetworkPolicy) и принцип «запрет по умолчанию».
В организационном плане это дополняется регламентами: кто и как разворачивает релизы, кто имеет доступ к инфраструктуре, как осуществляется аудит и реагирование на инциденты.
2) Информационная безопасность: процессы и меры защиты
Для систем, где применимы требования по ИБ, обычно критичны:
- Сегментация сетей и ограничение взаимодействий между сервисами;
- Управление доступами (учётные записи, роли, минимизация прав);
- Безопасный жизненный цикл образов (сканирование зависимостей и уязвимостей, контроль версий);
- Контроль конфигураций (immutable infra или дисциплина изменений);
- Обеспечение корректного логирования и сохранности журналов.
Docker‑Compose может служить только как инструмент разработки/локальных контуров. Для контуров с повышенными требованиями чаще выбирают Kubernetes, потому что там легче формализовать политики (RBAC, admission, NetworkPolicy) и создать повторяемый безопасный процесс.
3) Документирование и прослеживаемость
Юридически значимая часть проектов — доказуемость: как вы реализовали меры, как контролировали изменения и как проверяли соблюдение требований. Манифесты Kubernetes и GitOps‑подход помогают связать:
- артефакты (образы) → манифесты → среда → релиз;
- изменения в инфраструктуре → журнал действий (audit logs);
- события безопасности → логи и метрики.
Практический выбор: Compose или Kubernetes
Выбирайте Docker‑Compose, если:
- нужен быстрый старт для разработки, стагинга или обучения команды;
- масштаб ограничен и отказоустойчивость не критична;
- выстраивается базовая автоматизация интеграционных тестов;
- есть требования к минимальной сложности сопровождения.
Выбирайте Kubernetes, если:
- нужна масштабируемость и управляемый rollout;
- важны политики безопасности и стандартизация доступа;
- проект растёт и требуется единый подход в нескольких командах;
- есть требования к наблюдаемости и операционной дисциплине;
- нужна повторяемость контуров и доказуемость изменений.
Компромиссный подход (часто самый эффективный)
Во многих проектах применяют гибрид:
- локально/в CI — Docker‑Compose для быстрых интеграционных тестов;
- для предбоевого/боевого контура — Kubernetes с манифестами и политиками;
- одинаковая модель конфигурации (env/конфиги) и стандарты образов.
Наблюдаемость и эксплуатация: одинаково важно для обоих подходов
Независимо от Compose или Kubernetes убедитесь, что у вас реализованы:
- Централизованные логи (aggregation) и единый формат;
- Метрики: latency, error rate, загрузка CPU/RAM, состояние очередей;
- Трейсинг (по возможности) для микросервисов;
- Алертинг по бизнес‑сигналам (а не только по инфраструктуре).
Если приложение работает с персональными данными, внимательно относитесь к логированию: персональные данные не должны попадать в логи без необходимости и защиты.
Типовые ошибки при контейнеризации PHP
- Секреты в репозитории (env‑файлы или ARG в Dockerfile);
- Запуск контейнера от root без необходимости;
- Отсутствие лимитов ресурсов (OOM/нестабильность);
- Непредсказуемые зависимости (нет lock‑файла или не фиксируются версии);
- Логи в файлы внутри контейнера без агрегации (потеря следов и невозможность аудит‑выборок);
- Нет проверок readiness/liveness и нет контролируемых rollout‑стратегий в продакшене.
Заключение
Docker‑Compose и Kubernetes‑манифесты решают разные задачи в жизненном цикле PHP‑приложений. Compose — оптимален для разработки и локальных контуров благодаря простоте и скорости, а Kubernetes — предпочтителен для производственной эксплуатации, когда требуется управляемость, безопасность и стандартизация. При внедрении особенно важно учитывать обязанности по обработке персональных данных и требованиям информационной безопасности: минимальные привилегии, защита секретов, контроль сети и доказуемость изменений.
Если вы выбираете стратегию внедрения, практичный путь — начать с Compose для тестов и разработки, затем перенести в Kubernetes для боевых контуров с декларативными манифестами, наблюдаемостью и политиками безопасности.
РыбинскЛАБ предоставляет услуги по разработке и внедрению контейнерных платформ для PHP‑приложений — от проектирования Docker‑образов и конфигураций до Kubernetes‑манифестов, CI/CD и сопровождения в продуктивной эксплуатации.