如何为docker中的nginx配置https

准备环境

在 azure 上创建 ubuntu 类型的虚机事件非常容易的事情,安装 docker 也无须赘言。比较容易忽略的是配置合适的网络安全组规则,比如打开 80 和 443 端口:

还有就是配置 dns:

创建一个普通的 http 站点

简单起见,直接使用一个镜像中的 nodejs 应用作为 web 站点:

$ docker pull ljfpower/nodedemo
$ docker network create -d bridge webnet
$ docker run -d --restart=always --expose=3000 \
--network=webnet --name=myweb \
ljfpower/nodedemo

在用户的家目录下创建 nginx 目录及其子目录 conf.d、conf.crt 和 html,创建 logs 目录及其子目录 nginx 和 letsencrypt:

$ mkdir -p nginx/{conf.d,conf.crt,html}
$ mkdir -p logs/{nginx,letsencrypt}

说明,本文演示的示例中需要我们手动创建的文件和目录结构如下:

创建 nginx/nginx.conf 文件,内容如下:

user nginx;

如何为Docker中的Nginx配置HTTPS



worker_processes auto;


error_log /var/log/nginx/error.log warn;

pid /var/run/nginx.pid;


events {
worker_connections 2048;

}

http {
include /etc/nginx/mime.types;

default_type application/octet-stream;


sendfile on;

keepalive_timeout 65;

client_max_body_size 10m;


include /etc/nginx/conf.d/*.conf;

}

然后创建 nginx/conf.d/default.conf 文件,内容如下:

upstream web{
server myweb:3000;

}
server {
listen 80;

listen [::]:80;

server_name filterinto.com www.filterinto.com;


location ^~ /.well-known/acme-challenge/ {
default_type "
text/plain"
;

root /usr/share/nginx/html;

}
location = /.well-known/acme-challenge/ {
return 404;

}
location / {
proxy_pass http://web;

}
}

其中 /.well-known/acme-challenge/ 目录是 certbot 工具在生成证书时创建的。接下来创建文件 nginx/html/index.html 文件,内容如下:

<
!doctype html>

<
html>

<
head>

<
meta charset="
utf-8"
/>

<
title>
let'
s encrypt first time cert issue site<
/title>

<
/head>

<
body>

<
h1>
hello https!<
/h1>

<
p>

just used for the very first time ssl certificates are issued by let'
s encrypt'
s
certbot.
<
/p>

<
/body>

<
/html>

这个页面也是 certbot 在生成证书时需要用到的。最后让我们启动容器(在用户的家目录下执行下面的命令):

$ docker run -d \
-p 80:80 \
-v $(pwd)/nginx/conf.d:/etc/nginx/conf.d:ro \
-v $(pwd)/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
-v $(pwd)/logs/nginx:/var/log/nginx \
-v $(pwd)/nginx/html:/usr/share/nginx/html \
--restart=always \
--name=gateway \
--network=webnet \
nginx:1.14

注意:这时没有映射 443 端口,也没有挂载存放证书的目录。只能以 http 协议访问访问我们的站点:

为站点生成 ssl/tls 证书

let'
s encrypt 是一个提供免费 ssl/tls 证书的网站,它为用户提供了 certbot 工具用来生成 ssl/tls 证书。方便起见,我们把 certbot 简单的封装到容器中。在用户的家目录下创建 certbot 目录,进入 certbot 目录并把下面的内容保存到 dockerfile 文件中:

from alpine:3.4
run apk add --update bash certbot
volume ["
/etc/letsencrypt"
]

然后执行下面的命令创建 certbot 镜像:

$ docker build -t certbot:1.0 .

然后在 certbot 目录下创建自动更新证书的脚本 renew_cert.sh,内容如下:

#!/bin/bash
webdir="
$1"

list=('
filterinto.com'
'
www.filterinto.com'
)
led_list=()
www_root=/usr/share/nginx/html
for domain in ${list[@]};
do
docker run \
--rm \
-v ${webdir}/nginx/conf.crt:/etc/letsencrypt \
-v ${webdir}/logs/letsencrypt:/var/log/letsencrypt \
-v ${webdir}/nginx/html:${www_root} \
certbot:1.0 \
certbot certonly --verbose --noninteractive --quiet --agree-tos \
--webroot -w ${www_root} \
--email="
nick.li@grapecity.com"
\
-d "
$domain"

code=$?
if [ $code -ne 0 ];
then
failed_list+=($domain)
fi
done

# output failed domains
if [ ${#failed_list[@]} -ne 0 ];
then
echo '
failed domain:'

for (( i=0;
i<
${#failed_list[@]};
i++ ));

do
echo ${failed_list[$i]}
done
fi

在用户的家目录中执行 ./renew_cert.sh /home/nick 命令就可以生成新的证书(/home/nick 为当前用户的家目录)。生成的证书被保存在 /home/nick/nginx/conf.crt/live 目录下,以域名命名的目录下保存着该域名的证书:

然后去检查下 nginx/html 目录,发现多了一个隐藏的 .well-known 目录,这个目录就是在生成证书时创建的:

有了 ssl/tls 证书,接下来我们就可以配置 https 站点了。

为站点配置 ssl/tls 证书

有了 ssl/tls 证书,接下来更新 nginx 的配置文件就可以了,更新 nginx/conf.d/default.conf 的内容如下:

upstream web{
server myweb:3000;

}

server {
listen 80;

listen [::]:80;

server_name filterinto.com www.filterinto.com;


location ^~ /.well-known/acme-challenge/ {
default_type "
text/plain"
;

root /usr/share/nginx/html;

}
location = /.well-known/acme-challenge/ {
return 404;

}
return 301 https://$server_name$request_uri;

}
server {
listen 443;

listen [::]:443;

server_name filterinto.com;


# enable ssl
ssl on;

ssl_protocols tlsv1 tlsv1.1 tlsv1.2;

ssl_prefer_server_ciphers on;

ssl_ciphers "
eecdh+ecdsa+aesgcm eecdh+arsa+aesgcm eecdh+ecdsa+sha384 eecdh+ecdsa+sha256 eecdh+arsa+sha384 eecdh+arsa+sha256 eecdh edh+arsa !anull !enull !low !3des !md5 !exp !psk !srp !dss !rc4"
;


# config ssl certificate
ssl_certificate conf.crt/live/filterinto.com/fullchain.pem;

ssl_certificate_key conf.crt/live/filterinto.com/privkey.pem;


location ^~ /.well-known/acme-challenge/ {
default_type "
text/plain"
;

root /usr/share/nginx/html;

}
location = /.well-known/acme-challenge/ {
return 404;

}
location / {
proxy_pass http://web;

}
}
server {
listen 443;

listen [::]:443;

server_name www.filterinto.com;


# enable ssl
ssl on;

ssl_protocols tlsv1 tlsv1.1 tlsv1.2;

ssl_prefer_server_ciphers on;

ssl_ciphers "
eecdh+ecdsa+aesgcm eecdh+arsa+aesgcm eecdh+ecdsa+sha384 eecdh+ecdsa+sha256 eecdh+arsa+sha384 eecdh+arsa+sha256 eecdh edh+arsa !anull !enull !low !3des !md5 !exp !psk !srp !dss !rc4"
;


# config ssl certificate
ssl_certificate conf.crt/live/www.filterinto.com/fullchain.pem;

ssl_certificate_key conf.crt/live/www.filterinto.com/privkey.pem;


location ^~ /.well-known/acme-challenge/ {
default_type "
text/plain"
;

root /usr/share/nginx/html;

}
location = /.well-known/acme-challenge/ {
return 404;

}
location / {
proxy_pass http://web;

}
}

然后删除容器 gateway 并用下面的脚本重新创建:

$ docker run -d \
-p 80:80 \
-p 443:443 \
-v $(pwd)/nginx/conf.d:/etc/nginx/conf.d:ro \
-v $(pwd)/nginx/conf.crt:/etc/nginx/conf.crt:ro \
-v $(pwd)/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
-v $(pwd)/logs/nginx:/var/log/nginx \
-v $(pwd)/nginx/html:/usr/share/nginx/html \
--restart=always \
--name=gateway \
--network=webnet \
nginx:1.14

现在就只能通过 https 来访问站点了:

自动更新证书

let'
s encrypt 提供的 ssl/tls 证书期限只有三个月,每过三个月要手动更新一次证书也够呛的,下面我们介绍自动更新证书的方法。

其实我们的配置已经为自动化更新证书提供了最大的便利(其实是使用 docker 带来的便利),在定时任务中添加下面两条记录就可以了:

0 0 1 * * /home/nick/certbot/renew_cert.sh /home/nick >
>
/home/nick/logs/cert.log 2>
>
/home/nick/logs/cert.error.log
0 1 1 * * docker exec gateway nginx -s reload

每月 1 号的 0 点更新证书,一个小时后 reload nginx 的配置。



在当今互联网世界中,安全性是至关重要的,而HTTPS是保障网站安全性的重要手段之一。在应用开发与部署中,Docker已经成为一种重要的技术。本文将详细介绍如何在Docker中配置Nginx的HTTPS,保证网站与数据的安全性。
一、生成SSL证书
在配置HTTPS前,需要先生成SSL证书。可以通过certbot工具来实现,该工具是Let's Encrypt官方工具之一,可以快速、免费地生成有效的SSL证书。
安装certbot工具: sudo apt install certbot -y
生成SSL证书:sudo certbot certonly --standalone -d example.com
二、配置Nginx的HTTPS
有了SSL证书之后,接下来就可以为Nginx配置HTTPS了。具体配置步骤如下:
1.修改Nginx配置文件,添加以下内容:
# HTTPS server
server {
listen 443 ssl;
server_name example.com; # 域名
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # 证书文件
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # 私钥文件
ssl_session_timeout 5m;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
}

2.然后,重新载入Nginx配置文件就可以愉快地上HTTPS了:
sudo nginx -s reload
三、测试HTTPS服务
现在,Nginx已经配置完毕,运行成功之后,可以用浏览器测试一下HTTPS服务是否正常。可以打开浏览器,输入网站域名或IP后,前面应该是https开头,而不是http。
总结
本文介绍了如何为Docker中的Nginx配置HTTPS,并使用Let's Encrypt免费证书,保证了网站与数据的安全性。只有保证了安全性,才能更好地为用户提供服务,保障用户的权益。希望本文能给大家带来帮助,欢迎大家多多指教。