Развертывание нескольких веб-проектов на одном сервере с помощью виртуальных хостов приводит к конфликтам версий PHP, Python и Node.js. Docker решает эту проблему через полную изоляцию сред в контейнерах. Вы получите готовые Dockerfile для трех основных стеков, конфигурацию docker-compose.yml для управления сервисами и настройку маршрутизации по доменам через обратный прокси. Инструкции проверены на практике и экономят время при миграции существующих проектов.
Почему виртуальные хосты уступают контейнерам Docker в современной веб-разработке
Классическая архитектура с виртуальными хостами на одном веб-сервере создает проблемы при работе с проектами, требующими разных версий ПО. Docker обеспечивает полную изоляцию зависимостей каждого проекта в отдельном контейнере. Это решает основную боль системных администраторов - невозможность запуска двух приложений с разными требованиями на одной операционной системе.
Конфликт зависимостей: главная боль классической архитектуры
Представьте ситуацию: на сервере работают два проекта. Первый использует PHP 7.4 с устаревшей библиотекой, второй требует PHP 8.2 для современных функций. В архитектуре виртуальных хостов оба проекта используют один установленный в системе PHP. Обновление до версии 8.2 сломает первый проект, сохранение версии 7.4 заблокирует развитие второго.
Аналогичная проблема возникает с Node.js. Инструмент pi-bridge требует Node.js ≥ 18, тогда как старый проект может зависеть от Node.js 16. Виртуальные хосты не решают эту проблему, потому что все проекты работают в одном системном окружении. Docker создает для каждого проекта отдельную среду с точно заданными версиями ПО.
Переносимость и воспроизводимость: от хаоса к контролю
Перенос проекта с виртуальными хостами на новый сервер включает ручные шаги: копирование файлов, установку пакетов через apt или yum, настройку конфигураций веб-сервера. Каждый шаг может привести к ошибкам из-за различий в окружениях.
Docker превращает развертывание в предсказуемый процесс. Вы копируете Dockerfile и docker-compose.yml, затем выполняете команду docker-compose up. Контейнер создает идентичную среду на любой системе с установленным Docker. Dockerfile работает как контракт для среды выполнения приложения, аналогично тому, как спецификация OpenAPI служит контрактом для API в проектах типа UnoCRS.
Архитектура решения: от отдельных контейнеров к единой системе маршрутизации
Контейнерная система состоит из нескольких изолированных компонентов. Каждый проект работает в своем контейнере с собственным веб-сервером (Nginx или Apache). Контейнеры не открывают порты 80 или 443 напрямую. Вместо этого единый обратный прокси nginx-proxy анализирует заголовок Host в HTTP-запросе и направляет трафик на нужный контейнер. Это похоже на то, как SSH-туннель в Hermes WebUI обеспечивает безопасный доступ к интерфейсу по определенному адресу.
Роль обратного прокси (nginx-proxy) как единой точки входа
Nginx-proxy работает как диспетчер трафика. Он автоматически обнаруживает новые контейнеры через переменные окружения и обновляет свою конфигурацию без ручного вмешательства. Когда пользователь обращается к домену project1.local, прокси направляет запрос на контейнер с этим проектом. Для project2.local запрос идет к другому контейнеру. Преимущество - не нужно править конфиги при добавлении новых проектов.
Практика: создание Dockerfile для изолированного окружения вашего проекта
Dockerfile определяет среду выполнения приложения. Используйте официальные образы и фиксируйте версии ПО для воспроизводимости.
Dockerfile для PHP-приложения (Laravel, WordPress)
FROM php:8.2-fpm-alpine
RUN apk add --no-cache \
libpng-dev \
libzip-dev \
postgresql-dev \
&& docker-php-ext-install \
pdo_mysql \
pdo_pgsql \
gd \
zip \
opcache
COPY composer.json composer.lock /var/www/html/
RUN composer install --no-dev --optimize-autoloader --no-scripts
COPY . /var/www/html
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
Этот Dockerfile использует образ php:8.2-fpm-alpine, устанавливает необходимые расширения и настраивает права доступа. Команды composer выполняются до копирования основного кода для кэширования слоев.
Dockerfile для Node.js-приложения
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Многоэтапная сборка уменьшает итоговый размер образа. Первая стадия устанавливает зависимости, вторая копирует только необходимые файлы. Фиксация версии Node.js (18-alpine) гарантирует совместимость, что критично для инструментов вроде pi-bridge.
Dockerfile для Python-приложения (Django, Flask)
FROM python:3.11-slim
WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "wsgi:application"]
Образ использует виртуальное окружение внутри контейнера для изоляции зависимостей. Gunicorn работает как WSGI-сервер для production-среды.
Оркестрация сервисов: настройка docker-compose.yml для полного стека
Файл docker-compose.yml объединяет контейнеры приложения, веб-сервера и базы данных в единую систему.
Связка приложения и веб-сервера: Nginx как фронтенд для PHP-FPM
version: '3.8'
services:
app:
build: .
volumes:
- ./:/var/www/html
environment:
- VIRTUAL_HOST=myproject.local
- LETSENCRYPT_HOST=myproject.local
networks:
- proxy-network
- internal
webserver:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- app
networks:
- proxy-network
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: example
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- internal
networks:
proxy-network:
external: true
internal:
driver: bridge
volumes:
postgres_data:
Контейнер app использует собранный из Dockerfile образ. Контейнер webserver монтирует конфигурацию Nginx, где настроено проксирование на app:9000. Переменные VIRTUAL_HOST и LETSENCRYPT_HOST автоматически настраивают nginx-proxy.
Для управления несколькими проектами создавайте шаблоны docker-compose.yml. Это упрощает развертывание новых приложений. Подробнее о работе с Docker Compose читайте в полном руководстве по Docker для DevOps.
Настройка маршрутизации по доменам через nginx-proxy
Запустите контейнер nginx-proxy один раз на хосте:
docker run -d \
--name nginx-proxy \
--restart always \
-p 80:80 \
-p 443:443 \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
-v nginx-certs:/etc/nginx/certs \
nginxproxy/nginx-proxy
Добавьте в docker-compose.yml каждого проекта переменные окружения:
environment:
- VIRTUAL_HOST=project1.local
- LETSENCRYPT_HOST=project1.local
- LETSENCRYPT_EMAIL=admin@example.com
После запуска контейнеров проекты станут доступны по указанным доменам. Настройте локальный файл hosts или DNS-записи:
127.0.0.1 project1.local project2.local
Nginx-proxy автоматически обновляет конфигурацию при добавлении новых контейнеров. Для production-сред используйте отдельную сеть и настройте SSL-сертификаты через Let's Encrypt.
Миграция без боли: проверенный план перехода с виртуальных хостов
Переход на Docker требует аккуратного планирования, чтобы не нарушить работу существующих проектов.
Резервное копирование данных и конфигураций перед началом
Создайте дампы баз данных и архивируйте файлы:
# Для MySQL/MariaDB
mysqldump -u root -p database_name > backup.sql
# Для PostgreSQL
pg_dump -U postgres database_name > backup.sql
# Архивация загруженных файлов
tar -czf uploads_backup.tar.gz /path/to/uploads
Скопируйте конфигурации виртуальных хостов из /etc/nginx/sites-available/ или /etc/apache2/sites-available/.
Чек-лист миграции:
- Протестируйте Dockerfile и docker-compose на staging-сервере или локально. Убедитесь, что приложение запускается без ошибок.
- Перенесите данные. Для баз данных создайте volume в docker-compose.yml и восстановите дамп. Для файлов смонтируйте директорию в контейнер.
- Запустите контейнер параллельно со старым виртуальным хостом. Назначьте контейнеру порт 8080 для проверки:
ports: - "8080:80". - После успешного тестирования обновите DNS-записи или настройте проксирование с старого порта на новый контейнер.
- Отключите виртуальный хост в конфигурации веб-сервера только после полного переключения трафика.
Этот подход минимизирует риски. Каждый шаг можно откатить при возникновении проблем. Для сложных проектов с высокой нагрузкой рассмотрите blue-green deployment через Docker Swarm или Kubernetes.
Безопасность контейнеров требует отдельного внимания. Используйте non-root пользователей, ограничивайте capabilities и регулярно обновляйте базовые образы. Подробные рекомендации по защите Docker-инфраструктуры найдете в гайде по продвинутому Docker.
Создание production-образов имеет свои особенности. Многоэтапная сборка, сканирование на CVE и фиксация версий пакетов критически важны для стабильной работы. Готовые шаблоны для Python, Node.js и Go смотрите в руководстве по Dockerfile.
Для управления секретами, health checks и мониторингом в production-среде изучите гайд по Docker в production.
Интеграция AI-сервисов в ваши проекты упрощается через агрегаторы API. AiTunnel предоставляет единый интерфейс для более 200 моделей нейросетей, включая GPT, Gemini и Claude, с оплатой в рублях и без необходимости использования VPN.