Docker для сайтов: контейнеризация веб-приложений от А до Я
Для кого эта статья:
- Веб-разработчики, желающие освоить контейнеризацию с помощью Docker
- Специалисты по DevOps, заинтересованные в оптимизации процессов разработки и деплоя
Студенты и новички в области программирования, стремящиеся изучить современные технологии веб-разработки
Создание сайтов с использованием Docker — это не просто модный тренд, а технология, кардинально меняющая процессы разработки и деплоя веб-приложений. Разработчики, осваивающие контейнеризацию, получают решающее преимущество: сайт, работающий стабильно и идентично в любой среде — от локальной машины до промышленного сервера. Docker устраняет извечную проблему "у меня работает, а на проде нет", экономит время на настройке окружения и делает процесс масштабирования приложений предсказуемым. Пройдемся по всем этапам — от базовых принципов до готового к деплою контейнеризованного веб-сайта. 🚀
Хотите быстро освоить не только Docker, но и все ключевые технологии современной веб-разработки? Обучение веб-разработке от Skypro погружает вас в профессию через практику и реальные проекты. Наши выпускники умеют создавать контейнеризованные приложения, масштабируемые сервисы и быстро адаптируются к меняющимся требованиям индустрии. Станьте разработчиком, который решает бизнес-задачи, а не просто пишет код!
Основы контейнеризации для веб-разработки с Docker
Контейнеризация — это метод виртуализации на уровне операционной системы, позволяющий запускать приложения в изолированных средах (контейнерах). Docker реализует эту технологию, делая её доступной и удобной для разработчиков.
В отличие от виртуальных машин, контейнеры используют общее ядро операционной системы хоста, что делает их более легкими и эффективными. Они запускаются за миллисекунды и потребляют значительно меньше ресурсов.
Михаил Дронов, DevOps-инженер
Когда я присоединился к команде, разрабатывающей высоконагруженный новостной портал, первым делом столкнулся с проблемой: каждый разработчик настраивал окружение по-своему. Часто слышалось: "У меня всё работает, не понимаю, почему на тестовом сервере падает".
Внедрение Docker радикально изменило ситуацию. Мы создали единую конфигурацию в docker-compose.yml, описывающую весь стек: NGINX, PHP-FPM, MySQL, Redis и Elasticsearch. Теперь любой член команды или новый сотрудник мог запустить проект одной командой: docker-compose up.
Результат превзошел ожидания. Время на введение новых разработчиков в проект сократилось с недели до нескольких часов. Проблемы с "works on my machine" ушли в прошлое. А когда мы перешли на микросервисную архитектуру, Docker стал фундаментом, на котором мы построили всю инфраструктуру.
Основные компоненты экосистемы Docker:
- Docker Engine — ядро системы, управляющее контейнерами
- Docker Image — шаблон для создания контейнеров, содержащий код, библиотеки и зависимости
- Docker Container — запущенный экземпляр образа, изолированная среда выполнения
- Dockerfile — текстовый файл с инструкциями для сборки образа
- Docker Compose — инструмент для определения и запуска многоконтейнерных приложений
- Docker Hub — репозиторий для хранения и распространения образов
Для веб-разработки контейнеризация предлагает ряд существенных преимуществ:
| Преимущество | Описание | Пример использования |
|---|---|---|
| Идентичность сред | Устранение различий между локальной разработкой и продакшн-окружением | Тестирование на локальной машине с уверенностью, что код будет работать так же в продакшне |
| Быстрая настройка | Устранение "works on my machine" проблемы | Новый разработчик начинает работу над проектом за минуты, а не дни |
| Изоляция сервисов | Каждый компонент работает в собственном окружении | Возможность использовать разные версии PHP для разных микросервисов |
| Масштабируемость | Легкое горизонтальное масштабирование | Запуск дополнительных контейнеров при повышенной нагрузке |
| Управление версиями | Фиксация конкретных версий зависимостей | Избежание проблем совместимости при обновлении библиотек |

Настройка окружения: установка Docker и требования
Перед началом работы с Docker необходимо установить и настроить базовые компоненты на вашей системе. Требования различаются в зависимости от операционной системы. 🛠️
Системные требования для работы Docker:
- Windows: Windows 10 64-bit (сборка 19041 или новее) с включенной функцией WSL 2 (Windows Subsystem for Linux)
- macOS: macOS 10.14 (Mojave) или новее
- Linux: Ядро версии 3.10 или новее, 64-разрядная система
Процесс установки Docker:
- Для Windows и macOS: Скачайте и установите Docker Desktop с официального сайта Docker.
- Для Linux (Ubuntu/Debian):
# Обновление пакетов
sudo apt-get update
# Установка необходимых пакетов для работы с HTTPS репозиториями
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
# Добавление официального GPG-ключа Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Добавление стабильного репозитория Docker
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Установка Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# Установка Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.12.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
После установки проверьте корректность работы Docker командами:
# Проверка версии Docker
docker --version
# Проверка версии Docker Compose
docker-compose --version
# Тестовый запуск контейнера
docker run hello-world
Если все команды выполняются без ошибок и вы видите приветственное сообщение от контейнера hello-world, ваша среда готова к работе с Docker.
Дополнительные настройки, улучшающие работу с Docker:
- Добавьте вашего пользователя в группу docker, чтобы выполнять команды без sudo (для Linux):
sudo usermod -aG docker $USER
После этого требуется перезайти в систему
- Настройте автозапуск Docker при старте системы:
sudo systemctl enable docker
- Выделите достаточно ресурсов для Docker Desktop (Windows/macOS):
- Рекомендуется минимум 4GB RAM
- 2-4 CPU ядра
- 20GB свободного места для образов
Сравнение производительности Docker на разных операционных системах:
| Операционная система | Особенности работы Docker | Производительность | Совместимость |
|---|---|---|---|
| Linux | Нативная поддержка, прямой доступ к ядру | Высокая | Полная |
| macOS | Работает через HyperKit, легковесный гипервизор | Средняя | Хорошая |
| Windows с WSL 2 | Использует WSL 2 для запуска Linux-контейнеров | Средняя | Хорошая |
| Windows без WSL 2 | Использует Hyper-V для виртуализации | Низкая | Ограниченная |
Создание Dockerfile для компонентов вашего сайта
Dockerfile — это текстовый файл с инструкциями для создания образа Docker. Каждая строка в Dockerfile представляет собой слой в итоговом образе. Правильное создание Dockerfile критически важно для оптимизации размера образа, безопасности и производительности. 📝
Рассмотрим создание Dockerfile для типичных компонентов веб-сайта:
Веб-сервер (NGINX)
# Используем официальный образ NGINX
FROM nginx:1.23-alpine
# Копируем нашу конфигурацию
COPY ./config/nginx/site.conf /etc/nginx/conf.d/default.conf
# Копируем статические файлы
COPY ./public /var/www/html/public
# Настраиваем права доступа
RUN chown -R nginx:nginx /var/www/html
# Открываем порты
EXPOSE 80
# Запускаем NGINX в фоновом режиме
CMD ["nginx", "-g", "daemon off;"]
PHP-приложение
# Используем официальный образ PHP-FPM
FROM php:8.1-fpm-alpine
# Устанавливаем необходимые расширения PHP
RUN apk add --no-cache $PHPIZE_DEPS \
&& docker-php-ext-install pdo_mysql mysqli opcache \
&& pecl install redis \
&& docker-php-ext-enable redis
# Оптимизируем конфигурацию PHP для продакшена
COPY ./config/php/php.ini /usr/local/etc/php/conf.d/php-custom.ini
# Копируем код приложения
COPY ./src /var/www/html
# Устанавливаем Composer и зависимости
COPY --from=composer:2.4 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
RUN composer install --no-dev --optimize-autoloader
# Устанавливаем правильные права
RUN chown -R www-data:www-data /var/www/html
# Запускаем PHP-FPM
CMD ["php-fpm"]
База данных (MySQL)
# Используем официальный образ MySQL
FROM mysql:8.0
# Копируем скрипты инициализации
COPY ./database/init.sql /docker-entrypoint-initdb.d/
# Настраиваем конфигурацию MySQL
COPY ./config/mysql/my.cnf /etc/mysql/conf.d/custom.cnf
# Контрольная точка для проверки готовности сервера
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD mysqladmin ping -h localhost -u root -p"${MYSQL_ROOT_PASSWORD}" || exit 1
# Данные хранятся во внешнем томе, монтируемом через docker-compose
VOLUME /var/lib/mysql
Ключевые принципы оптимизации Dockerfile:
- Многоступенчатая сборка — для уменьшения размера итогового образа
- Минимальные базовые образы — предпочтение Alpine-версиям образов
- Группировка команд RUN — для уменьшения количества слоев
- Удаление ненужных файлов — после завершения установки зависимостей
- Использование .dockerignore — для исключения ненужных файлов из контекста сборки
- Явное указание версий — вместо тегов latest для предсказуемости
Алексей Воронцов, Full Stack разработчик
В прошлом году мы с командой переводили на Docker крупный интернет-магазин с миллионами посещений в месяц. Сайт работал на "зоопарке" технологий: PHP-бэкенд, Node.js для обработки платежей, Python для аналитики и рекомендаций.
Первая проблема возникла при создании Dockerfile для PHP-части. Мы сделали всё "по книжке" — установили все расширения, скопировали код и запустили. Образ вышел огромным — почти 2 ГБ! При масштабировании это создавало серьезные задержки.
Ключевым решением стала многоступенчатая сборка. В первом этапе мы устанавливали все инструменты для компиляции и зависимости Composer, во втором — только копировали готовый код и минимальный набор расширений. Размер образа уменьшился до 180 МБ.
Еще один урок мы извлекли, забыв добавить файл .dockerignore. При каждом билде Docker отправлял в контекст сборки гигабайты данных из папок node_modules и vendor. Добавление .dockerignore сократило время сборки с 15 минут до 30 секунд.
После оптимизации всех Dockerfile деплой стал занимать не 25-30 минут, как раньше, а всего 2-3 минуты, что позволило нам внедрить CI/CD и доставлять новые функции значительно быстрее.
Пример файла .dockerignore для типичного веб-проекта:
# Системные файлы
.git
.gitignore
.env
.DS_Store
# Зависимости
node_modules
vendor
**/node_modules
**/vendor
# Кеши и логи
var/cache/*
var/log/*
*.log
npm-debug.log
# Инструменты разработки
Dockerfile*
docker-compose*
.dockerignore
README.md
phpunit.xml
tests/
docs/
Организация структуры проекта с docker-compose
Docker Compose — это инструмент для определения и запуска многоконтейнерных приложений. С его помощью вы можете описать всю инфраструктуру вашего сайта в одном YAML-файле и запустить её одной командой. 🔄
Типичная структура проекта с использованием Docker Compose:
project-root/
├── docker-compose.yml # Основной файл конфигурации
├── docker-compose.override.yml # Переопределения для локальной разработки
├── .env # Переменные окружения для docker-compose
├── docker/ # Папка с Dockerfile и конфигурациями
│ ├── nginx/
│ │ ├── Dockerfile
│ │ └── config/
│ ├── php/
│ │ ├── Dockerfile
│ │ └── config/
│ └── mysql/
│ ├── Dockerfile
│ └── config/
├── src/ # Исходный код приложения
└── public/ # Публичные файлы
Пример комплексного файла docker-compose.yml для типичного веб-проекта:
version: '3.8'
services:
nginx:
build:
context: ./docker/nginx
ports:
- "80:80"
volumes:
- ./public:/var/www/html/public:ro
depends_on:
- php
networks:
- frontend
restart: unless-stopped
php:
build:
context: ./docker/php
volumes:
- ./src:/var/www/html:rw
- ./docker/php/config/php.ini:/usr/local/etc/php/conf.d/php-custom.ini:ro
depends_on:
- mysql
- redis
networks:
- frontend
- backend
restart: unless-stopped
env_file:
- .env
mysql:
build:
context: ./docker/mysql
volumes:
- mysql_data:/var/lib/mysql
networks:
- backend
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
redis:
image: redis:6-alpine
volumes:
- redis_data:/data
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
networks:
frontend:
backend:
volumes:
mysql_data:
redis_data:
Ключевые секции и концепции docker-compose.yml:
- services — определяет контейнеры, которые составляют ваше приложение
- networks — изолированные сети для коммуникации между контейнерами
- volumes — постоянные хранилища данных, не удаляемые при перезапуске контейнеров
- depends_on — определяет зависимости между сервисами для правильного порядка запуска
- env_file — подключает файл с переменными окружения
- restart — политика перезапуска контейнеров при сбоях
Для разделения конфигураций между разработкой и продакшеном рекомендуется использовать несколько файлов docker-compose:
# docker-compose.yml – базовая конфигурация
# docker-compose.override.yml – автоматически подключается, используется для разработки
# docker-compose.prod.yml – конфигурация для продакшена
# Запуск в режиме разработки (используется override автоматически):
docker-compose up -d
# Запуск для продакшена:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Пример docker-compose.override.yml для разработки:
version: '3.8'
services:
nginx:
ports:
- "8080:80" # Другой порт для избежания конфликтов
volumes:
- ./docker/nginx/config/site.dev.conf:/etc/nginx/conf.d/default.conf:ro
php:
build:
args:
- WITH_XDEBUG=true
volumes:
- ./docker/php/config/php-dev.ini:/usr/local/etc/php/conf.d/php-custom.ini:ro
environment:
- PHP_IDE_CONFIG=serverName=docker
- XDEBUG_MODE=debug
- XDEBUG_CONFIG=client_host=host.docker.internal client_port=9003
mysql:
ports:
- "3306:3306" # Открываем порт для подключения из IDE
adminer: # Дополнительный сервис только для разработки
image: adminer
restart: always
ports:
- "8888:8080"
depends_on:
- mysql
networks:
- backend
Пример docker-compose.prod.yml для продакшена:
version: '3.8'
services:
nginx:
image: ${REGISTRY}/project-nginx:${TAG}
deploy:
replicas: 2
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
php:
image: ${REGISTRY}/project-php:${TAG}
deploy:
replicas: 4
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
mysql:
volumes:
- ./docker/mysql/config/my-prod.cnf:/etc/mysql/conf.d/custom.cnf:ro
deploy:
resources:
limits:
cpus: '2'
memory: 4G
Развертывание и управление сайтом в контейнерах
После подготовки всех необходимых конфигураций наступает этап развертывания и управления контейнеризированным веб-сайтом. Этот процесс включает в себя запуск контейнеров, мониторинг их состояния и выполнение операций обслуживания. 🚢
Основные команды для управления контейнерами:
# Запуск всех сервисов в фоновом режиме
docker-compose up -d
# Проверка статуса запущенных контейнеров
docker-compose ps
# Просмотр логов
docker-compose logs -f [service_name]
# Остановка всех контейнеров без удаления
docker-compose stop
# Остановка и удаление контейнеров
docker-compose down
# Перезапуск отдельного сервиса
docker-compose restart [service_name]
# Выполнение команды внутри запущенного контейнера
docker-compose exec [service_name] [command]
Для непрерывной интеграции и доставки (CI/CD) с Docker рекомендуется следующий пайплайн:
- Сборка и тестирование образов при каждом коммите
- Автоматическая публикация образов в приватный Docker Registry
- Развертывание в тестовое окружение для QA
- Развертывание в продакшн после одобрения
Пример скрипта для CI/CD в GitLab:
stages:
- build
- test
- publish
- deploy
variables:
REGISTRY: registry.example.com
TAG: $CI_COMMIT_SHORT_SHA
build:
stage: build
script:
- docker-compose -f docker-compose.yml build
- docker tag myproject-nginx:latest $REGISTRY/myproject-nginx:$TAG
- docker tag myproject-php:latest $REGISTRY/myproject-php:$TAG
test:
stage: test
script:
- docker-compose -f docker-compose.yml -f docker-compose.test.yml up -d
- docker-compose exec php vendor/bin/phpunit
- docker-compose down
publish:
stage: publish
script:
- docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD $REGISTRY
- docker push $REGISTRY/myproject-nginx:$TAG
- docker push $REGISTRY/myproject-php:$TAG
deploy_staging:
stage: deploy
script:
- ssh deploy@staging.example.com "cd /opt/myproject && export TAG=$TAG && docker-compose -f docker-compose.yml -f docker-compose.staging.yml pull && docker-compose -f docker-compose.yml -f docker-compose.staging.yml up -d"
deploy_production:
stage: deploy
when: manual
script:
- ssh deploy@prod.example.com "cd /opt/myproject && export TAG=$TAG && docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull && docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d"
Мониторинг и обслуживание Docker-контейнеров в продакшене:
| Инструмент | Описание | Применение |
|---|---|---|
| Prometheus | Система мониторинга и оповещения | Сбор метрик о производительности контейнеров и хостов |
| Grafana | Платформа для визуализации данных | Создание информативных дашбордов на основе метрик Prometheus |
| cAdvisor | Анализатор ресурсов и производительности контейнеров | Детальный мониторинг использования ресурсов каждым контейнером |
| Portainer | Графический интерфейс для управления Docker | Упрощенное управление контейнерами, сетями и томами через веб-интерфейс |
| Watchtower | Автоматическое обновление контейнеров | Отслеживание новых версий образов и автоматическое обновление контейнеров |
Резервное копирование и восстановление данных:
- Резервное копирование томов:
docker run --rm -v myproject_mysql_data:/source -v $(pwd)/backups:/backup alpine tar -czf /backup/mysql-backup-$(date +%Y%m%d).tar.gz -C /source .
- Восстановление данных:
docker run --rm -v myproject_mysql_data:/target -v $(pwd)/backups:/backup alpine sh -c "rm -rf /target/* && tar -xzf /backup/mysql-backup-20221010.tar.gz -C /target"
- Дамп базы данных:
docker-compose exec mysql mysqldump -u root -p --all-databases > backups/full-dump-$(date +%Y%m%d).sql
Рекомендации по оптимизации производительности контейнеров в продакшене:
- Используйте ограничения ресурсов (cpulimit, memorylimit) для каждого контейнера
- Настройте healthcheck для отслеживания работоспособности сервисов
- Применяйте restart_policy для автоматического восстановления после сбоев
- Используйте сети типа overlay для межхостовой коммуникации в кластере
- Применяйте Docker Swarm или Kubernetes для оркестрации контейнеров в больших инсталляциях
- Регулярно обновляйте базовые образы для получения исправлений безопасности
- Используйте многоэтапную сборку для минимизации размера финальных образов
Масштабирование веб-приложения:
# Горизонтальное масштабирование сервиса php до 5 реплик
docker-compose up -d --scale php=5
# При использовании Docker Swarm:
docker service update --replicas 5 mystack_php
Docker превратил процесс развертывания веб-сайтов из сложной головоломки в предсказуемый и надежный процесс. Контейнеризация не только упрощает работу команды разработки, но и радикально меняет подход к масштабированию и поддержке приложений. Освоив принципы, описанные в этом руководстве, вы сможете создавать надежные, масштабируемые и повторяемые инфраструктуры для сайтов любой сложности. Технология не стоит на месте — Docker становится стандартом индустрии, который нельзя игнорировать современному веб-разработчику.