Docker之Nginx搭建HTTPS环境

什么是HTTPS

超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为HTTP over TLS,HTTP over SSL或HTTP Secure)是一种透过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。这个协议由网景公司(Netscape)在1994年首次提出,随后扩展到互联网上。 上面这段介绍来自维基百科,想要一两句话解释清楚什么是HTTPS,以及HTTPS的到底是什么也不是一件易事,本文这里不做探讨,感兴趣的朋友可以去搜索了解。

怎么获得证书

国内有很多服务商出售证书,价格从几千到上万不等,但是我们也可以通过阿里云、腾讯云、又拍云等获取免费证书,本文会以阿里云、腾讯云分别为例申请证书搭建HTTPS环境

准备工作

准备两个域名

我这里准备了2个二级域名用于申请上述两家提供的证书: aliyun.0558web.com、tencent.0558web.com 并把域名解析到对应的服务器

使用Docker创建Nginx环境

首先确保本机已经安装Docker,使用以下命令拉取nginx image

1
docker pull nginx

创建文件夹

在你的服务器上创建三个文件夹,nginx用于存放证书和nginx配置文件,www用于存放项目代码,ssl用于存放证书,这里演示在当前目录下创建文件夹

1
mkdir -p nginx/{aliyun,tencent} www/{aliyun,tencent} ssl/{aliyun,tencent}

下面来演示一下在阿里云和腾讯云申请的SSL证书来搭建HTTPS环境

阿里云

申请SSL证书
登录阿里云平台,进入控制台>选择产品与服务>搜索SSL证书,在SSL证书页面点击右上角的购买证书,购买页面提供的证书种类有很多种,每次我都是找半天才找到免费证书,民间土豪或企业可以直接购买收费的证书,如果是和我一样选择免费证书请记住以下几步:选择品牌(Symantec)>保护类型(1个域名)>证书类型(免费型DV SSL)>购买 购买成功以后,在SSL证书页面会看到刚才购买的证书,补全资料等待审核通过以后就可以下载我们的证书了,因为本文是在nginx下搭建HTTPS环境,所以这里下载证书 for Nginx

申请成功以后下载证书上传到/ssl/aliyun/目录下

编写配置nginx配置文件
在/nginx/aliyun/文件夹下编写配置文件,用于映射到docker容器中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
events{
worker_connections 1024;
}
http{

server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
}

server {
listen 443;
server_name localhost;
# ssl on;
root html;
index index.html index.htm;
ssl_certificate /etc/ssl/cert/*****.pem;
ssl_certificate_key /etc/ssl/cert/*****.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
}

添加项目代码

在/www/aliyun/文件下新建index.html

1
2
<!---简单的输出一个Hello aliyun-->
Hello aliyun

创建nginx容器

运行一个nginx容器, 命名aliyun

1
2
3
4
5
6
7
docker run 
-p 8080:80
-p 8081:443
-v $PWD/nginx/aliyun/nginx.conf:/etc/nginx/nginx.conf
-v $PWD/www/aliyun:/usr/share/nginx/html
-v $PWD/ssl/aliyun:/ect/nginx/cert/aliyun
--name aliyun -d nginx

启动以后,使用下面的命令查看是否会输Hello aliyun,如果输出则表示启动成功,否则可以使用docker logs 容器ID查看错误日志

1
curl 127.0.0.1:8080

绑定域名、转发端口

在你的服务器上安装nginx,用于转发端口和绑定域名
安装成功以后,在/etc/nginx/sites-available/下新建aliyun.conf,然后来编写我们的配置文件

1
2
3
4
5
6
server {
listen 80;
server_name aliyun.0558web.com;

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

编写以后在/etc/nginx/sites-enabled/下添加软连接

1
2
3
4
5
6
7
8
9
cd ../sites-enabled
# 添加软连接
ln -s ../sites-available/aliyun.conf aliyun.conf

# 查看配置文件是否配置成功
nginx -t

# 重启你的本机nginx
service nginx restart

测试HTTPS环境是否成功

在浏览器中输入http://aliyun.0558web.com或https://aliyun.0558web.com:8081就能看会看到绿锁 这个时候使用阿里云提供的免费SSL证书,我们成功搭建了HTTPS环境 但是你会发现,HTTPS是可以使用了,但是后面还带着端口,这显然不是你想要的,下面分享一下我的两种解决办法

如果在一台服务器上只创建一个HTTPS环境完全可以把端口修改一下

1
2
3
4
5
6
7
8
9
docker run 
# 本机的80端口->docker容器的80端口
-p 80:80
# 本机的443端口->docker容器的443端口
-p 443:443
-v $PWD/nginx/aliyun/nginx.conf:/etc/nginx/nginx.conf
-v $PWD/www/aliyun:/usr/share/nginx/html
-v $PWD/ssl/aliyun:/ect/nginx/cert/aliyun
--name aliyun -d nginx

如果一台服务器上创建多个docker容器,并且要为每个容器配置HTTPS环境怎么办呢?下面我们申请腾讯云提供的免费SSL证书来演示一下

腾讯云

申请证书

登录腾讯云,进入控制台>云产品>搜索SSL证书管理,进入证书管理页面点击购买,选择域名型免费版(DV)免费申请,剩下的步骤和阿里云差不多,补全资料等待证书下发 这里通过腾讯云提供的SSL做一下演示

编写nginx配置文件
在nginx/tencent/文件夹下新增配置文件,用于映射到docker容器中

1
2
3
4
5
6
7
8
9
10
events {
woker_connections 1024;
}
http {
server{
listen 80;
server_name location;
root /usr/share/nginx/html;
}
}

编写项目代码

在www/tencent/文件夹下新建index.html

1
2
<!---简单的输出一个Hello Tencent-->
Hello Tencent

启动nginx
运行nginx容器,命名:tencent

1
2
3
4
docker run -p 8082:80
-v $PWD/nginx/tencent/nginx.conf:/etc/nginx/nginx.conf
-v $PWD/www/tencent:/usr/share/nginx/html
--name tencent -d nginx

判断是否运行成功

1
2
3
curl 127.0.0.1:8082
# 输出 Hello Tencent 表示运行成功
# 否则 通过 docker logs 容器ID查看错误日志

转发端口绑定域名

在/etc/nginx/sites-available/下新建配置文件tencent.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server{
listen 80;
server_name tencent.0558web.com;
return 301 https://$server_name$request_uri
}
server {
listen 443 default_server ssl;
server_name tencent.0558web.com;
ssl_certificate /root/project/ssl/tencent/1_tencent.0558web.com_bundle.crt;
ssl_certificate_key /root/project/ssl/tencent/2_tencent.0558web.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location /{
index index.html index.htm;
proxy_pass http://tencent.0558web.com:8082;
}
}

添加软链接 重启nginx

在/etc/nginx/sites-enabled/下添加链接

1
2
3
4
5
6
ln -s /etc/nginx/sites-available/tencent.conf /etc/nginx/sites-enabled/tencent.conf
# 查看nginx是否配置成功
nginx -t

# 重启nginx
service nginx restart

这个时候我们在浏览器中打开 tencent.0558web.com 或者https://tencent.0558web.com都会看到绿锁

遇到的坑

  • no “ssl_certificate” is defined in server listening on SSL port while SSL handshaking, client: ,,,, server: 0.0.0.0:443

大致意思是说在监听的端口上没有设置证书,但是我们命名已经设置,而且nginx -t 也没有报错,可能是我们设置的443 服务器端口没有监听到

解决办法:

1
2
3
4
5
6
server{
listen 443 default_server ssl;
.
.
.
}
  • the “ssl” directive is deprecated, use the “listen … ssl” directive instead in /etc/nginx/nginx.conf:14 nginx已经弃用的ssl指令
    解决办法
1
2
3
4
5
server{
# 注释ssl on
listen 443 ssl;
# ssl on;
}

总结:本文分享了通过阿里云和腾讯云提供的免费SSL证书,给docker中的nginx搭建HTTPS环境,主要用了nginx的端口转发,本人对Nginx只是属于入门阶段,文中难免有错误和不足,还请大佬们指正

坚持技术分享,您的支持将鼓励我继续创作!