前阵子买了个配置不错的阿里云,先搭了个Minecraft上去,Minecraft也跑在Docker里,并加载了DynMap显示实时地图。为了日后好扩展,方便上一些比较好看的页面,先用一个nginx反代一下,顺便挂上HTTPS,证书当然要从Letsencrypt搞。
看了下现有的方案,感觉都不太好看,都需要独立维护一个Dockerfile,不能直接用Nginx mainline,刷新证书的时候需要先关闭服务器,而且acme.sh和nginx跑在同一个容器里。想了一下,打算让acme.sh和nginx分开跑,nginx把challenge内容转发给acme.sh,这样应该就妥了,惟一的不好的地方是需要写个crontab,每隔2个月重启一下nginx的容器。不过其他方案也有downtime,也算可以接受。
目录结构和配置文件:
/ acme.sh - SSL证书存放和acme帐号信息,配置信息 nginx - 自定义nginx配置存放的地方 conf.d - 一些nginx全局配置 sites-enabled - 各个domain设置 sites-conf - domain之间共用的设置
nignx/conf.d/acme.sh.conf
upstream acme-sh { server acme-sh:80; }
nignx/conf.d/enabled-sites.conf
include /etc/nginx/sites-enabled/*.conf;
nginx/sites-conf/acme.sh.conf
location ~ "^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$" { default_type text/plain; proxy_read_timeout 60; proxy_connect_timeout 60; proxy_redirect off; proxy_pass http://acme-sh; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; }
nginx/sites-enabled/example.com.conf
server { server_name example.com; listen 0.0.0.0:443 ssl; listen [::]:443 ssl; ssl on; ssl_certificate /etc/ssl/letsencrypt/example.com/fullchain.cer; ssl_certificate_key /etc/ssl/letsencrypt/example.com/example.com.key; include sites-conf/acme.sh.conf; ... } server { server_name example.com; listen 0.0.0.0:80; listen [::]:80; include sites-conf/acme.sh.conf; location / { return 301 https://example.com$request_uri; } }
第一次要先获取一个有效证书:
docker run --rm -it \ -v "$(pwd)/acme.sh":/acme.sh \ --net=host \ neilpang/acme.sh --issue -d example.com --standalone
使用docker-compose做容器管理,yml内容如下:
some-other-service: ... nginx-srv: image: nginx:mainline volumes: - ./nginx/conf.d:/etc/nginx/conf.d - ./nginx/sites-conf:/etc/nginx/sites-conf - ./nginx/sites-enabled:/etc/nginx/sites-enabled - ./acme.sh:/etc/ssl/letsencrypt links: - some-other-service:upstream - acme-sh:acme-sh ports: - "443:443/tcp" - "80:80/tcp" acme-sh: image: neilpang/acme.sh command: daemon volumes: - ./acme.sh:/acme.sh
调 docker-compose up就可以了。
最后加一个cronjob让nginx定期重新读取证书:
/var/spool/cron/root:
cd /path/to/docker-compose.yaml && /usr/bin/docker-compose exec nginx-srv nginx -s reload
既然是nginx -s reload,就不会有down time啦
确实阿,感谢指正。