docker,nginx,ssl最佳实践
基于我对docker,nginx还有ssl证书的部署,提出了我对这些服务最高效的部署方法。仅供参考,一定会有更好的方法,只是我还有待学习
使用docker部署nginx
docker部署nginx有什么好处呢?大概就是可以把所有相关的配置文件汇集在一块,也方便在不同的服务器中迁移。
这里提供部署所使用的docker代码:
1 | 先创建一个nginx网络 |
在上述命令中,最关键的内容有4点:
本地目录映射
我一共映射了4个目录和一个配置文件(这些目录和配置文件需要你提前创建好,方便docker对其映射)
logs
该目录下主要保存着每次访问网站时保存的日志记录,可以用来查询相关的访问记录和debug
html
这里就是你所使用的静态文件了。同样映射到了docker下的/etc/nginx/html
这个部分的内容即默认的root根目录。可以很方便的对不同的项目进行反向代理,而且只用填相对路径ssl
此处放你需要配置的ssl证书,后续我会说如何配置freessl
实现永久的证书自动配置功能conf.d
这个目录存放你对不同项目的不同配置文件,做到每个项目都分开存放,结构清晰。nginx.conf
这里是使用默认的配置文件,我会提供模板: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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
# 这里将会引用你在conf.d下的所有配置文件。所以这个nginx.conf文件你都不用编辑
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
include /etc/nginx/conf.d/**/*.conf;
#test_3d
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
配置专门的nginx网络
可以看到我在上面的docker命令中,有一个--network=nginx_container
的选项。
使用docker network inspect nginx_container
命令查看
如何将其他容器添加到某个网络中?
1 | 一,在启动容器时就使用--network的选项就添加到某个网络中去 |
使用图示来展示关于这一操作的妙用:
这样子,其他的服务不占用主机的外部端口,而只依靠nginx代理出去。保证了服务的安全,也减少了端口被扫,被攻击的风险。
同时,在配置文件中,也会有很方便的地方。这里展示alist.conf
我们不在需要写完整的服务器ip地址,而是通过http://alist
的方式自动去访问,即便服务器被重启,他分配在不同的ip。也可以实现对应的访问功能。
还有更多关于nginx网络的部分可以查看这一文章docker网络模式
设置一直重启
这里就是简单的参数配置--restart=always
即使服务器因为断电等原因重启,也可以在通电后重新恢复服务。
为nginx配置ssl证书
配置ssl证书其实是比较简单的事。
你可以从阿里云,腾讯云免费领取到时长1年的单域名证书,然后在conf配置中开启ssl校验并配置ssl证书和密钥的地址即可。
我这里主要是为了实现泛域名的永久性配置。
freessl这是我最常用的ssl证书配置服务。他提供3个月时长的免费泛域名。然后通过一些配置实现到期自动更新部署新的证书,做到永久有效。
他有新版和旧版之区分,我这里演示旧版的功能。新版就是替你实现dns服务器的配置过程。都是很好的服务。(只是我懒得搞了。就用旧版演示看看就好啦)
添加域名
添加域名可以使用泛域名和单域名。添加域名后,需要你证明这个域名是在你的名下,而且你对他有控制权。即在对应的dns服务商添加上他要求你添加的配置项
新版就是这里不需要你进行验证,而是把验证过程交给系统去实现,你只需要提供几个token。
通过添加CNAME验证,过一小段时间后,他就会校验成功。
将证书部署到服务器
接下里使用acme.sh
将证书部署到服务器。
安装
acme.sh
客户端
官方下载地址:1
curl https://get.acme.sh | sh -s email=my@example.com
备用下载地址
1
curl https://gitcode.net/cert/cn-acme.sh/-/raw/master/install.sh?inline=false | sh -s email=my@example.com
获取申请命令
在ACME客户端
->申请证书
中,获取安装命令
然后将你获取到的命令直接在服务器中运行即可,等待片刻后,证书和密钥就会保存在你用户目录下的.acme.sh/{域名}
下
其中你需要使用的到的是fullchain.cer
和selflove.ren.key
将证书安装到具体的目录下
命令如下:(以我的目录结构为示例)1
2
3acme.sh --install-cert -d selflove.ren \
--key-file /home/zfxt/docker_data/nginx/ssl/selflove.key \
--fullchain-file /home/zfxt/docker_data/nginx/ssl/selflove.cer完成安装后,他会每天检测定时检测,若是域名还只剩下一个月时,他就会重新进行一次证书获取和安装
可以使用crontab -l
查看系统的定时任务。会有一个和acme.sh相关的任务的
为nginx使用配置文件
直接使用模板文件到时候再修改即可:
1 | server { |
在docker中的etc/nginx/ssl
目录就映射我们在对应位置的ssl目录。因此只需要做到上述配置。就差不多配置好了ssl证书了。
以上,本次文章的目的基本就达成了。下面在补充一些关于nginx的使用说明。
nginx使用说明
Nginx的location语法
1 | location [=|~|~*|^~] /uri/ { … } |
- = 严格匹配。如果请求匹配这个location,那么将停止搜索并立即处理此请求
- ~ 区分大小写匹配(可用正则表达式)
- ~* 不区分大小写匹配(可用正则表达式)
- !~ 区分大小写不匹配
- !~* 不区分大小写不匹配
- ^~ 如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式
alias与root的区别
- root 实际访问文件路径会拼接URL中的路径
- alias 实际访问文件路径不会拼接URL中的路径
示例如下:
1 | location ^~ /sta/ { |
请求:http://test.com/sta/sta1.html
实际访问:/etc/nginx/html/static/sta1.html
文件
1 | location ^~ /tea/ { |
请求:http://test.com/tea/tea1.html
实际访问:/etc/nginx/html/tea/tea1.html
文件
proxy_pass的使用
1 | location /api { |
配置反向代理时,移除前缀。比如我们的服务http://test.com/api/random
, 我们想要代理到http://yiyan.com/random
,即切换域名的同时,去掉api前缀。区别是proxy_pass
结尾的/
.
无/
则保留前缀,有/
则删除前缀。
permanent 和 redirect关键字的区别
rewrite … permanent
永久性重定向,请求日志中的状态码为301rewrite … redirect
临时重定向,请求日志中的状态码为302