Вступление
Есть несколько способов повысить гибкость и безопасность вашего приложенияNode.js. Использованиеreverse proxy, напримерNginx, дает вам возможность загружать запросы балансировки, кэшировать статический контент и реализовыватьTransport Layer Security (TLS). Включение зашифрованного HTTPS на вашем сервере гарантирует, что связь с вашим приложением остается безопасной.
Реализация обратного прокси с TLS / SSL для контейнеров включает в себя другой набор процедур, нежели работа непосредственно в операционной системе хоста. Например, если вы получали сертификаты отLet’s Encrypt для приложения, работающего на сервере, вы должны установить необходимое программное обеспечение прямо на свой хост. Контейнеры позволяют использовать другой подход. ИспользуяDocker Compose, вы можете создавать контейнеры для вашего приложения, вашего веб-сервера иCertbot client, которые позволят вам получить ваши сертификаты. Следуя этим шагам, вы можете воспользоваться модульностью и переносимостью контейнерного рабочего процесса.
В этом руководстве вы развернете приложение Node.js с обратным прокси-сервером Nginx с помощью Docker Compose. Вы получите сертификаты TLS / SSL для домена, связанного с вашим приложением, и убедитесь, что оно получит высокий рейтинг безопасности отSSL Labs. Наконец, вы настроите заданиеcron
для обновления сертификатов, чтобы ваш домен оставался безопасным.
Предпосылки
Чтобы следовать этому уроку, вам понадобится:
-
Сервер Ubuntu 18.04, пользователь без полномочий root с привилегиями
sudo
и активный брандмауэр. Инструкции по их настройке см. ВInitial Server Setup guide. -
Docker и Docker Compose установлены на вашем сервере. Чтобы получить инструкции по установке Docker, выполните шаги 1 и 2 изHow To Install and Use Docker on Ubuntu 18.04. Чтобы получить указания по установке Compose, следуйте шагу 1How To Install Docker Compose on Ubuntu 18.04.
-
Зарегистрированное доменное имя. В этом руководстве будет использоватьсяexample.com. Вы можете получить его бесплатно наFreenom или воспользоваться услугами регистратора доменов по вашему выбору.
-
Обе следующие записи DNS настроены для вашего сервера. Вы можете следить заthis introduction to DigitalOcean DNS, чтобы узнать, как добавить их в учетную запись DigitalOcean, если это то, что вы используете:
-
Запись A с
example.com
, указывающая на общедоступный IP-адрес вашего сервера. -
Запись A с
www.example.com
, указывающая на общедоступный IP-адрес вашего сервера.
-
[[step-1 -—- cloning-and-testing-the-node-application]] == Шаг 1. Клонирование и тестирование приложения узла
В качестве первого шага мы клонируем хранилище с кодом приложения Node, который включает в себя Dockerfile, который мы будем использовать для создания образа приложения с помощью Compose. Сначала мы можем протестировать приложение, собрав и запустив его сdocker run
command, без обратного прокси или SSL.
В домашнем каталоге пользователя без полномочий root клонируйтеnodejs-image-demo
repository изDigitalOcean Community GitHub account. Этот репозиторий включает код из настройки, описанной вHow To Build a Node.js Application with Docker.
Клонируйте репозиторий в каталог с именемnode_project
:
git clone https://github.com/do-community/nodejs-image-demo.git node_project
Перейдите в каталогnode_project
:
cd node_project
В этом каталоге находится файл Dockerfile, содержащий инструкции по созданию приложения Node с использованиемDocker node:10
image и содержимого текущего каталога проекта. Вы можете посмотреть содержимое Dockerfile, набрав:
cat Dockerfile
OutputFROM node:10-alpine
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 8080
CMD [ "node", "app.js" ]
Эти инструкции создают образ узла, копируя код проекта из текущего каталога в контейнер и устанавливая зависимости с помощьюnpm install
. Они также используют Dockercaching and image layering, отделяя копиюpackage.json
иpackage-lock.json
, содержащую перечисленные зависимости проекта, от копии остальной части кода приложения. Наконец, в инструкциях указано, что контейнер будет запускаться от имени пользователяnode без полномочий root с соответствующими разрешениями, установленными для кода приложения и каталоговnode_modules
.
Для получения дополнительной информации об этом Dockerfile и передовых методах создания образов узлов см. Полное обсуждение вStep 3 of How To Build a Node.js Application with Docker.
Чтобы протестировать приложение без SSL, вы можете создать и пометить изображение, используяdocker build
и флаг-t
. Мы назовем изображениеnode-demo
, но вы можете назвать его как-нибудь иначе:
docker build -t node-demo .
После завершения процесса сборки вы можете перечислить свои изображения с помощьюdocker images
:
docker images
Вы увидите следующий вывод, подтверждающий сборку образа приложения:
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
node-demo latest 23961524051d 7 seconds ago 73MB
node 10-alpine 8a752d5af4ce 3 weeks ago 70.7MB
Затем создайте контейнер сdocker run
. Мы включим три флага с этой командой:
-
-p
: публикует порт на контейнере и сопоставляет его с портом на нашем хосте. Мы будем использовать порт80
на хосте, но вы можете изменить его при необходимости, если у вас есть другой процесс, работающий на этом порту. Для получения дополнительной информации о том, как это работает, см. Это обсуждение в документации Docker поport binding. -
-d
: запускает контейнер в фоновом режиме. -
--name
: позволяет дать контейнеру запоминающееся имя.
Выполните следующую команду, чтобы построить контейнер:
docker run --name node-demo -p 80:8080 -d node-demo
Осмотрите свои запущенные контейнеры с помощьюdocker ps
:
docker ps
Вы увидите вывод, подтверждающий, что ваш контейнер приложения работает:
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4133b72391da node-demo "node app.js" 17 seconds ago Up 16 seconds 0.0.0.0:80->8080/tcp node-demo
Теперь вы можете посетить свой домен, чтобы проверить настройку:http://example.com
. Не забудьте заменитьexample.com
своим собственным доменным именем. Ваше приложение отобразит следующую целевую страницу:
Теперь, когда вы протестировали приложение, вы можете остановить контейнер и удалить изображения. Снова используйтеdocker ps
, чтобы получитьCONTAINER ID
:
docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4133b72391da node-demo "node app.js" 17 seconds ago Up 16 seconds 0.0.0.0:80->8080/tcp node-demo
Остановите контейнер с помощьюdocker stop
. Не забудьте заменить перечисленные здесьCONTAINER ID
на свое собственное приложениеCONTAINER ID
:
docker stop 4133b72391da
Теперь вы можете удалить остановленный контейнер и все изображения, включая неиспользуемые и оборванные изображения, с помощьюdocker system prune
и флага-a
:
docker system prune -a
Введитеy
в ответ на запрос в выводе, чтобы подтвердить, что вы хотите удалить остановленный контейнер и изображения. Имейте в виду, что это также удалит ваш кеш сборки.
Протестировав образ приложения, вы можете перейти к созданию остальной части вашей установки с помощью Docker Compose.
[[шаг-2 -—- определение-конфигурации-веб-сервера]] == Шаг 2 - Определение конфигурации веб-сервера
С нашим приложением Dockerfile мы можем создать файл конфигурации для запуска нашего контейнера Nginx. Мы начнем с минимальной конфигурации, которая будет включать наше доменное имя,document root, информацию о прокси и блок местоположения для направления запросов Certbot в каталог.well-known
, где он поместит временный файл для проверки этого DNS для нашего домена разрешается на наш сервер.
Сначала создайте каталог в текущем каталоге проекта для файла конфигурации:
mkdir nginx-conf
Откройте файл с помощьюnano
или вашего любимого редактора:
nano nginx-conf/nginx.conf
Добавьте следующий блок сервера для прокси-запросов пользователей к контейнеру приложения Node и для направления запросов Certbot в каталог.well-known
. Обязательно заменитеexample.com
на свое собственное доменное имя:
~/node_project/nginx-conf/nginx.conf
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
proxy_pass http://nodejs:8080;
}
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
}
Этот блок сервера позволит нам запустить контейнер Nginx в качестве обратного прокси-сервера, который будет передавать запросы нашему контейнеру приложений Node. Это также позволит нам использовать Certbotwebroot plugin для получения сертификатов для нашего домена. Этот плагин зависит отHTTP-01 validation method, который использует HTTP-запрос, чтобы доказать, что Certbot может получить доступ к ресурсам с сервера, который отвечает на заданное доменное имя.
Как только вы закончите редактирование, сохраните и закройте файл. Чтобы узнать больше о сервере Nginx и алгоритмах блокировки местоположения, обратитесь к этой статье оUnderstanding Nginx Server and Location Block Selection Algorithms.
Имея подробные сведения о конфигурации веб-сервера, мы можем перейти к созданию нашего файлаdocker-compose.yml
, который позволит нам создавать наши службы приложений и контейнер Certbot, который мы будем использовать для получения наших сертификатов.
[[step-3 -—- created-the-docker-compose-file]] == Шаг 3. Создание файла Docker Compose
Файлdocker-compose.yml
будет определять наши службы, включая приложение Node и веб-сервер. Он будет указывать такие детали, как именованные тома, которые будут иметь решающее значение для совместного использования учетных данных SSL между контейнерами, а также информации о сети и порте. Это также позволит нам указать конкретные команды, которые будут выполняться при создании наших контейнеров. Этот файл является центральным ресурсом, который определит, как наши сервисы будут работать вместе.
Откройте файл в вашем текущем каталоге:
nano docker-compose.yml
Сначала определим службу приложения:
~/node_project/docker-compose.yml
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
Определение службыnodejs
включает следующее:
-
build
: определяет параметры конфигурации, включаяcontext
иdockerfile
, которые будут применяться, когда Compose строит образ приложения. Если вы хотите использовать существующий образ из реестра, напримерDocker Hub, вы можете вместо этого использоватьimage
instruction с информацией о вашем имени пользователя, репозитории и теге изображения. -
context
: определяет контекст сборки для сборки образа приложения. В данном случае это текущий каталог проекта. -
dockerfile
: указывает Dockerfile, который Compose будет использовать для сборки - Dockerfile, который вы просматривали вStep 1. -
image
,container_name
: они применяют имена к изображению и контейнеру. -
restart
: определяет политику перезапуска. По умолчанию этоno
, но мы настроили перезапуск контейнера, если он не остановлен.
Обратите внимание, что мы не включаем bind mounts с этим сервисом, поскольку наша установка ориентирована на развертывание, а не на разработку. Для получения дополнительной информации см. Документацию Docker поbind mounts иvolumes.
Чтобы обеспечить связь между приложением и контейнерами веб-сервера, мы также добавим мостовую сеть под названиемapp-network
под определением перезапуска:
~/node_project/docker-compose.yml
services:
nodejs:
...
networks:
- app-network
Определяемая пользователем мостовая сеть, подобная этой, обеспечивает связь между контейнерами на одном хосте демона Docker. Это оптимизирует трафик и обмен данными в вашем приложении, поскольку оно открывает все порты между контейнерами в одной и той же мостовой сети, не открывая порты для внешнего мира. Таким образом, вы можете выборочно открывать только те порты, которые необходимы для предоставления ваших услуг веб-интерфейса.
Затем определите службуwebserver
:
~/node_project/docker-compose.yml
...
webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
depends_on:
- nodejs
networks:
- app-network
Некоторые параметры, которые мы определили для службыnodejs
, остались прежними, но мы также внесли следующие изменения:
-
image
: это указывает Compose на получение последнихAlpine-basedNginx image из Docker Hub. Для получения дополнительной информации об изображенияхalpine
см. Шаг 3How To Build a Node.js Application with Docker. -
ports
: открывает порт80
для включения параметров конфигурации, которые мы определили в нашей конфигурации Nginx.
Мы также указали следующие именованные тома и привязываемые монтирования:
-
web-root:/var/www/html
: это добавит статические ресурсы нашего сайта, скопированные на том с именемweb-root
, в каталог/var/www/html
в контейнере. -
./nginx-conf:/etc/nginx/conf.d
: это свяжет монтируемый каталог конфигурации Nginx на хосте с соответствующим каталогом в контейнере, гарантируя, что любые изменения, которые мы вносим в файлы на хосте, будут отражены в контейнере. -
certbot-etc:/etc/letsencrypt
: это подключит соответствующие сертификаты и ключи Let's Encrypt для нашего домена в соответствующий каталог в контейнере. -
certbot-var:/var/lib/letsencrypt
: монтирует рабочий каталог Let’s Encrypt по умолчанию в соответствующий каталог в контейнере.
Затем добавьте параметры конфигурации для контейнераcertbot
. Обязательно замените информацию о домене и электронной почте своим доменным именем и контактным адресом электронной почты:
~/node_project/docker-compose.yml
...
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --staging -d example.com -d www.example.com
Это определение сообщает Compose, что нужно извлечьcertbot/certbot image из Docker Hub. Он также использует именованные тома для совместного использования ресурсов с контейнером Nginx, включая сертификаты домена и ключ вcertbot-etc
, рабочий каталог Let’s Encrypt вcertbot-var
и код приложения вweb-root
.
Опять же, мы использовалиdepends_on
, чтобы указать, что контейнерcertbot
должен запускаться после запуска службыwebserver
.
Мы также включили параметрcommand
, который указывает команду, которая будет запускаться при запуске контейнера. Он включает подкомандуcertonly
со следующими параметрами:
-
--webroot
: это указывает Certbot использовать подключаемый модуль webroot для размещения файлов в папке webroot для аутентификации. -
--webroot-path
: указывает путь к корневому веб-каталогу. -
--email
: Ваш предпочтительный адрес электронной почты для регистрации и восстановления. -
--agree-tos
: это означает, что вы согласны сACME’s Subscriber Agreement. -
--no-eff-email
: это сообщает Certbot, что вы не хотите делиться своей электронной почтой сElectronic Frontier Foundation (EFF). Не стесняйтесь опустить это, если вы предпочитаете. -
--staging
: это сообщает Certbot, что вы хотите использовать промежуточную среду Let’s Encrypt для получения тестовых сертификатов. Использование этого параметра позволяет протестировать параметры конфигурации и избежать возможных ограничений на количество запросов домена. Для получения дополнительной информации об этих ограничениях см. Let's Encrypt’srate limits documentation. -
-d
: позволяет указать имена доменов, которые вы хотите применить к вашему запросу. В этом случае мы включилиexample.com
иwww.example.com
. Обязательно замените их собственными настройками домена.
На последнем этапе добавьте определения тома и сети. Обязательно замените здесь имя пользователя своим собственным пользователем без полномочий root:
~/node_project/docker-compose.yml
...
volumes:
certbot-etc:
certbot-var:
web-root:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/views/
o: bind
networks:
app-network:
driver: bridge
Наши именованные тома включают в себя наш сертификат Certbot и тома рабочего каталога, а также том для статических ресурсов нашего сайта,web-root
. В большинстве случаев драйвером по умолчанию для томов Docker является драйверlocal
, который в Linux принимает параметры, аналогичныеmount
command. Благодаря этому мы можем указать список параметров драйвера с помощьюdriver_opts
, которые монтируют каталогviews
на хосте, который содержит статические ресурсы нашего приложения, на том во время выполнения. Содержимое каталога затем может быть разделено между контейнерами. Для получения дополнительных сведений о содержимом каталогаviews
см.Step 2 of How To Build a Node.js Application with Docker.
После завершения файлdocker-compose.yml
будет выглядеть так:
~/node_project/docker-compose.yml
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
networks:
- app-network
webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
depends_on:
- nodejs
networks:
- app-network
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --staging -d example.com -d www.example.com
volumes:
certbot-etc:
certbot-var:
web-root:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/views/
o: bind
networks:
app-network:
driver: bridge
После определения сервисов вы готовы запускать контейнеры и тестировать запросы на сертификаты.
[[шаг-4 -—- получение-ssl-сертификатов и учетных данных]] == Шаг 4 - Получение сертификатов и учетных данных SSL
Мы можем запустить наши контейнеры с помощьюdocker-compose up
, который будет создавать и запускать наши контейнеры и службы в указанном нами порядке. Если наши запросы к домену будут успешными, мы увидим правильный статус выхода в наших выходных данных и правильные сертификаты, смонтированные в папке/etc/letsencrypt/live
в контейнереwebserver
.
Создайте службы сdocker-compose up
и флагом-d
, которые будут запускать контейнерыnodejs
иwebserver
в фоновом режиме:
docker-compose up -d
Вы увидите вывод, подтверждающий, что ваши услуги были созданы:
OutputCreating nodejs ... done
Creating webserver ... done
Creating certbot ... done
Используяdocker-compose ps
, проверьте статус ваших сервисов:
docker-compose ps
Если все прошло успешно, ваши службыnodejs
иwebserver
должны бытьUp
, а контейнерcertbot
будет завершен с сообщением о состоянии0
:
Output Name Command State Ports
------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
nodejs node app.js Up 8080/tcp
webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp
Если вы видите что-либо, кромеUp
в столбцеState
для службnodejs
иwebserver
, или статус выхода, отличный от0
дляcertbot
) s, обязательно проверьте журналы службы с помощью командыdocker-compose logs
:
docker-compose logs service_name
Теперь вы можете проверить, что ваши учетные данные были подключены к контейнеруwebserver
с помощьюdocker-compose exec
:
docker-compose exec webserver ls -la /etc/letsencrypt/live
Если ваш запрос был успешным, вы увидите вывод:
Outputtotal 16
drwx------ 3 root root 4096 Dec 23 16:48 .
drwxr-xr-x 9 root root 4096 Dec 23 16:48 ..
-rw-r--r-- 1 root root 740 Dec 23 16:48 README
drwxr-xr-x 2 root root 4096 Dec 23 16:48 example.com
Теперь, когда вы знаете, что ваш запрос будет успешным, вы можете отредактировать определение службыcertbot
, чтобы удалить флаг--staging
.
Открытьdocker-compose.yml
:
nano docker-compose.yml
Найдите раздел файла с определением службыcertbot
и замените флаг--staging
в опцииcommand
на флаг--force-renewal
, который сообщит Certbot, что вы хотите запросить новый сертификат с теми же доменами, что и существующий сертификат. Определение службыcertbot
теперь должно выглядеть так:
~/node_project/docker-compose.yml
...
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com
...
Теперь вы можете запуститьdocker-compose up
, чтобы воссоздать контейнерcertbot
и соответствующие ему тома. Мы также включим параметр--no-deps
, чтобы сообщить Compose, что он может пропустить запуск службыwebserver
, поскольку она уже запущена:
docker-compose up --force-recreate --no-deps certbot
Вы увидите вывод, указывающий, что ваш запрос сертификата был успешным:
Outputcertbot | IMPORTANT NOTES:
certbot | - Congratulations! Your certificate and chain have been saved at:
certbot | /etc/letsencrypt/live/example.com/fullchain.pem
certbot | Your key file has been saved at:
certbot | /etc/letsencrypt/live/example.com/privkey.pem
certbot | Your cert will expire on 2019-03-26. To obtain a new or tweaked
certbot | version of this certificate in the future, simply run certbot
certbot | again. To non-interactively renew *all* of your certificates, run
certbot | "certbot renew"
certbot | - Your account credentials have been saved in your Certbot
certbot | configuration directory at /etc/letsencrypt. You should make a
certbot | secure backup of this folder now. This configuration directory will
certbot | also contain certificates and private keys obtained by Certbot so
certbot | making regular backups of this folder is ideal.
certbot | - If you like Certbot, please consider supporting our work by:
certbot |
certbot | Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
certbot | Donating to EFF: https://eff.org/donate-le
certbot |
certbot exited with code 0
С вашими сертификатами вы можете перейти к изменению конфигурации Nginx для включения SSL.
[[step-5 -—- modifying-the-web-server-configuration-and-service-definition]] == Шаг 5. Изменение конфигурации веб-сервера и определения службы
Включение SSL в нашей конфигурации Nginx будет включать добавление перенаправления HTTP к HTTPS и указание нашего SSL-сертификата и расположения ключей. Это также потребует указания нашей группы Диффи-Хеллмана, которую мы будем использовать дляPerfect Forward Secrecy.
Поскольку вы собираетесь воссоздать сервисwebserver
, чтобы включить эти дополнения, вы можете остановить его сейчас:
docker-compose stop webserver
Затем создайте каталог в вашем текущем каталоге проекта для вашего ключа Диффи-Хеллмана:
mkdir dhparam
Создайте свой ключ с помощьюopenssl
command:
sudo openssl dhparam -out /home/sammy/node_project/dhparam/dhparam-2048.pem 2048
Генерация ключа займет несколько минут.
Чтобы добавить соответствующую информацию Diffie-Hellman и SSL в вашу конфигурацию Nginx, сначала удалите созданный ранее файл конфигурации Nginx:
rm nginx-conf/nginx.conf
Откройте другую версию файла:
nano nginx-conf/nginx.conf
Добавьте следующий код в файл, чтобы перенаправить HTTP на HTTPS и добавить учетные данные SSL, протоколы и заголовки безопасности. Не забудьте заменитьexample.com
своим собственным доменом:
~/node_project/nginx-conf/nginx.conf
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
try_files $uri @nodejs;
}
location @nodejs {
proxy_pass http://nodejs:8080;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
}
Блок HTTP-сервера указывает корневой веб-сайт для запросов обновления Certbot в каталог.well-known/acme-challenge
. Он также включаетrewrite directive, который направляет HTTP-запросы в корневой каталог на HTTPS.
Блок сервера HTTPS включаетssl
иhttp2
. Чтобы узнать больше о том, как HTTP / 2 выполняет итерацию по протоколам HTTP, и о преимуществах, которые он может иметь для производительности веб-сайта, см. Введение вHow To Set Up Nginx with HTTP/2 Support on Ubuntu 18.04. Этот блок также включает в себя ряд параметров, обеспечивающих использование самых современных SSL-протоколов и шифров и включение сшивания OSCP. Сшивание OSCP позволяет вам предлагать ответ с отметкой времени от вашегоcertificate authority в течение начальногоTLS handshake, что может ускорить процесс аутентификации.
В блоке также указываются ваши учетные данные SSL и Diffie-Hellman и ключевые местоположения.
Наконец, мы переместили информацию о проходе прокси в этот блок, включая блок местоположения с директивойtry_files
, указывающий запросы на наш контейнер приложения Node.js с псевдонимом, и блок местоположения для этого псевдонима, который включает заголовки безопасности. это позволит нам получать рейтингиA на таких сайтах, как серверные тестовые сайтыSSL Labs иSecurity Headers. Эти заголовки включаютX-Frame-Options
,X-Content-Type-Options
,Referrer Policy
,Content-Security-Policy
иX-XSS-Protection
. ЗаголовокHTTP Strict Transport Security
(HSTS) закомментирован - включите это, только если вы понимаете последствия и оценили его“preload” functionality.
Как только вы закончите редактирование, сохраните и закройте файл.
Перед воссозданием службыwebserver
вам нужно будет добавить несколько вещей в определение службы в вашем файлеdocker-compose.yml
, включая соответствующую информацию о портах для HTTPS и определение тома Диффи-Хеллмана.
Откройте файл:
nano docker-compose.yml
В определении службыwebserver
добавьте следующее сопоставление портов и именованный томdhparam
:
~/node_project/docker-compose.yml
...
webserver:
image: nginx:latest
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- dhparam:/etc/ssl/certs
depends_on:
- nodejs
networks:
- app-network
Затем добавьте томdhparam
к вашим определениямvolumes
:
~/node_project/docker-compose.yml
...
volumes:
...
dhparam:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/dhparam/
o: bind
Аналогично томуweb-root
, томdhparam
будет монтировать ключ Диффи-Хеллмана, хранящийся на хосте, в контейнерwebserver
.
Сохраните и закройте файл, когда вы закончите редактирование.
Воссоздайте сервисwebserver
:
docker-compose up -d --force-recreate --no-deps webserver
Проверьте свои услуги с помощьюdocker-compose ps
:
docker-compose ps
Вы должны увидеть вывод, указывающий, что ваши службыnodejs
иwebserver
работают:
Output Name Command State Ports
----------------------------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
nodejs node app.js Up 8080/tcp
webserver nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
Наконец, вы можете посетить свой домен, чтобы убедиться, что все работает как положено. Перейдите в браузере кhttps://example.com
, не забудьте заменитьexample.com
своим собственным доменным именем. Вы увидите следующую целевую страницу:
Вы также должны увидеть значок замка в индикаторе безопасности вашего браузера. Если хотите, вы можете перейти кSSL Labs Server Test landing page илиSecurity Headers server test landing page. Включенные нами параметры конфигурации должны обеспечить вашему сайту рейтингA по обоим параметрам.
[[шаг-6 -—- возобновление-сертификатов]] == Шаг 6 - Продление сертификатов
Сертификаты Let Encrypt действительны в течение 90 дней, поэтому вам нужно настроить автоматический процесс обновления, чтобы они не истекли. Один из способов сделать это - создать задание с помощью утилиты планированияcron
. В этом случае мы запланируем заданиеcron
с помощью сценария, который обновит наши сертификаты и перезагрузит нашу конфигурацию Nginx.
Откройте скрипт с именемssl_renew.sh
в каталоге вашего проекта:
nano ssl_renew.sh
Добавьте следующий код в скрипт, чтобы обновить сертификаты и перезагрузить конфигурацию веб-сервера:
~/node_project/ssl_renew.sh
#!/bin/bash
/usr/local/bin/docker-compose -f /home/sammy/node_project/docker-compose.yml run certbot renew --dry-run \
&& /usr/local/bin/docker-compose -f /home/sammy/node_project/docker-compose.yml kill -s SIGHUP webserver
Помимо указания местоположения нашего двоичного файлаdocker-compose
, мы также указываем местоположение нашего файлаdocker-compose.yml
для выполнения командdocker-compose
. В этом случае мы используемdocker-compose run
для запуска контейнераcertbot
и переопределенияcommand
, предоставленного в нашем определении службы, другим: подкомандойrenew
, которая обновляет сертификаты. срок действия близок к истечению. Мы включили здесь параметр--dry-run
, чтобы протестировать наш скрипт.
Затем сценарий используетdocker-compose kill
для отправкиSIGHUP
signal в контейнерwebserver
для перезагрузки конфигурации Nginx. Дополнительные сведения об использовании этого процесса для перезагрузки конфигурации Nginx см. Вthis Docker blog post on deploying the official Nginx image with Docker.
Закройте файл, когда вы закончите редактирование. Сделайте его исполняемым:
chmod +x ssl_renew.sh
Затем откройте файлrootcrontab
, чтобы запустить сценарий обновления с указанным интервалом:
sudo crontab -e
Если вы впервые редактируете этот файл, вам будет предложено выбрать редактор:
кронтаб
no crontab for root - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/ed
2. /bin/nano <---- easiest
3. /usr/bin/vim.basic
4. /usr/bin/vim.tiny
Choose 1-4 [2]:
...
В нижней части файла добавьте следующую строку:
кронтаб
...
*/5 * * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1
Это позволит установить интервал между заданиями каждые пять минут, чтобы вы могли проверить, работает ли ваш запрос на обновление должным образом. Мы также создали файл журнала,cron.log
, для записи соответствующих выходных данных задания.
Через пять минут проверьтеcron.log
, чтобы узнать, был ли запрос на обновление успешно выполнен:
tail -f /var/log/cron.log
Вы должны увидеть вывод, подтверждающий успешное обновление:
Output- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates below have not been saved.)
Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Killing webserver ... done
Теперь вы можете изменить файлcrontab
, чтобы установить дневной интервал. Например, чтобы запускать скрипт каждый день в полдень, вы должны изменить последнюю строку файла так, чтобы она выглядела следующим образом:
кронтаб
...
0 12 * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1
Вы также можете удалить опцию--dry-run
из вашего скриптаssl_renew.sh
:
~/node_project/ssl_renew.sh
#!/bin/bash
/usr/local/bin/docker-compose -f /home/sammy/node_project/docker-compose.yml run certbot renew \
&& /usr/local/bin/docker-compose -f /home/sammy/node_project/docker-compose.yml kill -s SIGHUP webserver
Ваша работаcron
гарантирует, что ваши сертификаты Let’s Encrypt не истекут, обновляя их, когда они соответствуют требованиям. Вы также можетеset up log rotation with the Logrotate utility вращать и сжимать файлы журнала.
Заключение
Вы использовали контейнеры для настройки и запуска приложения Node с обратным прокси-сервером Nginx. Вы также защитили сертификаты SSL для домена своего приложения и настроили заданиеcron
для обновления этих сертификатов при необходимости.
Если вы хотите узнать больше о плагинах Let's Encrypt, ознакомьтесь с нашими статьями об использованииNginx plugin илиstandalone plugin.
Вы также можете узнать больше о Docker Compose, обратившись к следующим ресурсам:
Compose documentation также является отличным ресурсом для получения дополнительных сведений о многоконтейнерных приложениях.