Docker vs виртуальные хосты: практический переход к изолированным контейнерам для веб-проектов | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Docker vs виртуальные хосты: практический переход к изолированным контейнерам для веб-проектов

04 мая 2026 6 мин. чтения

Развертывание нескольких веб-проектов на одном сервере с помощью виртуальных хостов приводит к конфликтам версий 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/.

Чек-лист миграции:

  1. Протестируйте Dockerfile и docker-compose на staging-сервере или локально. Убедитесь, что приложение запускается без ошибок.
  2. Перенесите данные. Для баз данных создайте volume в docker-compose.yml и восстановите дамп. Для файлов смонтируйте директорию в контейнер.
  3. Запустите контейнер параллельно со старым виртуальным хостом. Назначьте контейнеру порт 8080 для проверки: ports: - "8080:80".
  4. После успешного тестирования обновите DNS-записи или настройте проксирование с старого порта на новый контейнер.
  5. Отключите виртуальный хост в конфигурации веб-сервера только после полного переключения трафика.

Этот подход минимизирует риски. Каждый шаг можно откатить при возникновении проблем. Для сложных проектов с высокой нагрузкой рассмотрите 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.

Поделиться:
Сохранить гайд? В закладки браузера