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
Комментарии
Зачем ангуляр, ожидал видеть что-то максимально простое, но даже репа angular-nginx. Может стоит назвать "Как запустить веб-приложение Angular на Nginx в Docker". Потому что вместо приложения можно было бы просто сделать js файл с hello world и было бы куда лучше. Время не вернуть(
Первая же команда не работает - "ng new angular-nginx-docker --minimal". Вероятно есть какой-то способ её использовать, но альтернативно одаренный автор подумал, что и так всё понятно будет. Не будет
Какая ошибка была в терминале?
ng команда которая идёт в пакете с Angular, 1.устанавливаете Node.js чтоб пользоваться командой npm 2.npm install -g /cli устанавливаем сам ангулар чтоб пользоваться командой ng.