Как запустить веб-приложение на Nginx в Docker 🐳👨🏽💻
Инструкция по настройке совместной работы веб-приложения и сервера Nginx в Docker-контейнере, а также о том, как создать их общий Docker-образ для использования в других контейнерах.

Nginx – это хорошо известный высокопроизводительный HTTP-сервер и обратный прокси-сервер. Nginx предоставляет балансировку нагрузки, кэширование, поддержку SSL/TLS, журналирование и ротацию логов. В статье мы будем использовать Nginx для сервера одностраничного приложения (SPA). На этом примере мы поймём, как создавать и запускать Docker-образ с веб-приложением и NGINX.
Небольшие приготовления: создаём веб-приложение
Для начала нам нужно какое-то веб-приложение, которое будет обслуживаться сервером Nginx. Вы можете использовать любой JavaScript-фреймворк, в нашем примере мы используем демо-проект Angular:
ng new angular-nginx-docker --minimal cd angular-nginx-docker ng build --prod
В результате выполнения указанных команд будет создано новое приложение Angular, находящееся в папке $PWD/dist/angular-nginx-docker
. Этот каталог содержит файл index.html
и несколько типичных для одностраничного приложения JavaScript и CSS файлов. Приложение, весь код и команды из этой статьи находятся в GitHub-репозитории.
Запускаем приложение на Nginx в Docker-контейнере
Nginx и Docker на удивление хорошо работают вместе. Вместо того чтобы устанавливать Nginx на нашу машину напрямую, мы будем запускать его в Docker на примере nginx:alpine.
Образ nginx:alpine
очень производителен, хотя занимает лишь около 20 Мб дискового пространства. Для интерактивного запуска образа nginx: alpine
в контейнере мы выполняем следующую команду:
docker run -it -p 80:80 \ -v /$PWD/dist/angular-nginx-docker://usr/share/nginx/html:ro \ nginx:alpine
Приведённая команда монтирует том в Docker-контейнер в режиме read only
(устанавливается с помощью флага: ro
). Том отображает наше приложение в дефолтную корневую папку веб-контента Nginx. Команда также сопоставляет порт 80
в контейнере с портом 80
в хосте, чтобы мы могли увидеть наше приложение на http://localhost
. Когда клиент запрашивает содержимое приложения, мы видим в консоли логи Nginx.
Без дополнительных настроек Nginx использует дефолтные файлы конфигурации веб-сервера. Если вам интересно, вы можете использовать следующие команды для их изучения в Docker-образе:
docker run -it nginx:alpine sh cd etc/nginx/
Исходная конфигурация NGINX уже может обслуживать наше приложение. Но мы можем оптимизировать веб-сервер, создав папку .nginx
и поместив в нее конфигурационный файл nginx.conf
со следующим содержимым:
# Запускать в качестве менее привилегированного пользователя по соображениям безопасности.. user nginx; # Значение auto устанавливает число максимально доступных ядер CPU, # чтобы обеспечить лучшую производительность. worker_processes auto; events { worker_connections 1024; } http { server { # Hide nginx version information. server_tokens off; listen 80; root /usr/share/nginx/html; include /etc/nginx/mime.types; location / { try_files $uri $uri/ /index.html; } gzip on; gzip_vary on; gzip_http_version 1.0; gzip_comp_level 5; gzip_types application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component; gzip_proxied no-cache no-store private expired auth; gzip_min_length 256; gunzip on; } }
Каталог .nginx
используется для организации файлов конфигурации для Nginx. По большей части файл конфигурации не требует пояснений, стоит упомянуть лишь о двух моментах:
- Инструкция
try_files
используется для определения запасных маршрутов, когда у сервера запрашивается неизвестный ему файл. Конфигурационные инструкцииtry_files
обычно можно увидеть в веб-приложениях с паттерном Front Controller. - Во второй половине файла описывается
gzip
-сжатие и распаковка HTTP-ответов.
Мы также можем использовать другие параметры конфигурации, которые повысят производительность, безопасность и масштабируемость Nginx. К примеру, для реальных приложений в файле nginx.conf
понадобится настроить SSL-сертификат. Чтобы узнать больше о конфигурациях Nginx, ознакомьтесь с руководством для новичков в Nginx.
Чтобы Nginx мог использовать настроенный файл nginx.conf
, запускаем следующую команду:
docker run -it -p 80:80 \ -v /$PWD/dist/angular-nginx-docker://usr/share/nginx/html:ro \ -v /$PWD/.nginx/nginx.conf://etc/nginx/nginx.conf:ro \ nginx:alpine
Эта команда подключает два read-only-тома к контейнеру Docker. Один том соответствует нашему приложению с контейнером, а другой – сопоставит файл nginx.conf
в качестве файла конфигурации.
Как понять, что Nginx использует наш файл nginx.conf
? Достаточно проверить заголовок ответа HTTP. На следующем скриншоте показано сравнение заголовков ответов при использовании конфигураций по умолчанию (слева) и пользовательской конфигурации (справа).
Когда Nginx использует кастомный файл конфигурации, HTTP-ответ скрывает номер версии Nginx и кодирует содержимое в режиме gzip
.
Докеризация веб-приложения с Nginx
В предыдущем разделе мы научились работать с нашим одностраничным приложением, используя Nginx в контейнере. Мы также можем отправлять наше приложение вкупе с Nginx в виде Docker-образа в контейнеры других сред. Контейнерные приложения дают ряд преимуществ: простота обновления, локализация сбоев, простая смена технологии. Так что теперь мы создадим Docker-образ, содержащий и веб-приложение, и сервер Nginx, который при запуске Docker-образа будет его автоматически обслуживать.
Чтобы получить Docker-образ, создаём следующий Dockerfile
:
# 1. Создаем приложение Angular FROM node:alpine as builder WORKDIR /app COPY package.json package-lock.json ./ ENV CI=1 RUN npm ci COPY . . RUN npm run build -- --prod --output-path=/dist # 2. Развертываем приложение Angular на NGINX FROM nginx:alpine # Заменяем дефолтную страницу nginx соответствующей веб-приложению RUN rm -rf /usr/share/nginx/html/* COPY --from=builder /dist /usr/share/nginx/html COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf ENTRYPOINT ["nginx", "-g", "daemon off;"]
Этот Dockerfile
включает две фазы создания Docker-образа. Сначала он стягивает образ node:alpine
для создания приложения Angular, которое публикуется по выходному пути /dist
. Далее он переключается на образ nginx:alpine
, заменяет дефолтный корень приложения Nginx приложением Angular и копирует кастомный файл nginx.conf
в систему Nginx
.
В последней строке указывается точка входа образа для команды: nginx -g daemon off;
. Это гарантирует, что Nginx останется «на переднем плане», так что Docker сможет правильно отслеживать процесс (в противном случае контейнер остановится сразу после запуска).
node_modules
, можно добавить файл .dockerignore
.С помощью описанного Dockerfile
мы можем создать образ Docker и запустить его в контейнере, используя следующие команды:
docker build -t angular-nginx-docker . docker run -d -p 80:80 angular-nginx-docker
Готово! В этой статье мы продемонстрировали, как обслуживать простые веб-приложения с использованием Nginx в контейнере, кратко рассказали о файле конфигурации для Nginx, а также о том, как можно вместе упаковать в один образ и приложение сервера, и frontend-часть.
Читайте также другие наши статьи о технологии Docker:
- «Контейнер дал течь»: проверьте безопасность Docker-образа
- Понятные видеоуроки по Docker для начинающих
- 12 друзей Docker-а – опенсорсные инструменты в помощь разработке
- Как использовать docker-compose для Python и Jupyter