ITPub博客

首页 > 应用开发 > Java > 用Docker来解决LetsEncrypt证书失效

用Docker来解决LetsEncrypt证书失效

原创 Java 作者:写BUG的程序袁 时间:2021-07-09 11:38:47 0 删除 编辑

 前言

起因是因为 Let's Encrypt 的管理证书协议 ACMEv1 要在今年废弃掉,导致一台老服务器上的 https 失效。 Let's Encrypt 官方推荐的方法是更新到支持 ACMEv2 的 certbot 版本。服务器是Ubuntu 14.04,支持 ACMEv2的客户端需要更新到Ubuntu 16.04 ,因为更新系统的不确定性,所以想到了使用 Docker 去解决这个问题。

项目结构大概是这样

3B751CEB-020F-4EF2-ABC6-27D54F7BB405.png

Nginx 做 Node Server 的反向代理,Certbot 用来获取并更新 Nginx 的 ssl 证书。

我们的目的是用容器将三个服务整合在一起。

构建 Node Server 的镜像

首先是要将 Node Server 进行Docker 化,直接在项目中加入 Dockerfile。

FROM node:6.17.1
ENV NODE_ENV=production
WORKDIR  /server
COPY ["package.json", "package-lock.json*", "yarn.lock", "npm-shrinkwrap.json*", "./"]
RUN yarn --silent --production
COPY . .
EXPOSE 3000
RUN yarn global add gulp
CMD ["yarn", "deploy"]

环境是直接用 node 官方的 v6.17.1,WORKDIR 是之后命令的工作目录,安装依赖,暴露 3000 端口,执行部署命令。

中途遇到了个小问题,因为deploy 命令后面是用 gulp 执行的,容器中局部依赖安装 gulp 找不到该命令,这里找到一篇文章来讨论这个问题  Why do we need to install gulp globally and locally? 这里我只是按最无脑的方法解决了,也可以使用 npm link 或者 alias node_modules/.bin/gulp 的方式去处理。

Dockerfile 完成之后,用 docker build . -t nodeapp 来构建 docker image。

Nginx + Certbot

在思考如何才能解决证书问题的时候,看到 certbot 的官网上有 Docker 的安装方式,但是因为容器间的通讯问题,certbot 虽然能自动获取证书,但需要手动去安装到 nginx 上。

大体的思路如下:

2BAF68A4-C638-40F8-B5E4-17B47C38C27E.png

按照这个思路做的时候,发现已经有人造过轮子了。Boilerplate for nginx with Let’s Encrypt on docker-compose 他的处理方式是通过 docker-compose 来将 Nginx 和 certbot 两个容器通过上图的方式建立联系。

这里有个鸡生蛋蛋生鸡的问题,LetsEncrypt 的验证方式是访问域名中的一个 /.well-known/acme-challenge/xxx 地址来进行验证,返回的数据是由 certbot 来提供。但如果一开始不提供证书的话,nginx 就不能启动。作者的方法是先生成一个假正书来启动 nginx,然后用获取到的真证书替换掉假正书。

因为在上面 Boilerplate 中已经有一个脚本来处理,就不重复造轮子了。

nginx 的配置文件如下

server {
    listen 80;
    server_name example.org;
    server_tokens off;
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    listen 443 ssl;
    server_name example.org;
    server_tokens off;
    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    location / {
        proxy_pass  http://example.org;
        proxy_set_header    Host                $http_host;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    }
}

拼装 Node Server + Nginx

我们现在已经获得了一个有了合法证书的 Nginx 服务器了,将 node server 接在 Nginx 的后面就大功告成了。 我们直接在前面的boilerplate中提供的 docker-compose.yml 进行一些修改。

version: "3"
services:
  nodeapp:
    image: nodeserver:1.0.0
    container_name: nodeapp
    restart: unless-stopped
    volumes:
      - /data/usersFolder:/server/config
    ports:
      - "3000:3000"
    networks:
      - app-network
  nginx:
    image: nginx:1.15-alpine
    container_name: nginx_server
    restart: unless-stopped
    volumes:
      - ./data/nginx:/etc/nginx/conf.d
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    ports:
      - "80:80"
      - "443:443"
    networks:
      - app-network
    command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
  certbot:
    image: certbot/certbot
    restart: unless-stopped
    container_name: certbot_one
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
networks:
  app-network:
    driver: bridge

通过创建一个 network 来让 nginx 直接和 node server 通信,nginx 的conf 也可以写的比较顺滑。以前我记得可以使用 —link 来进行容器间通信,但官方更推荐的做法还是创建一个 network。

docker-compose up !

执行 boilerplate 中的脚本启动 nginx 并获取到证书,再通过 docker-compose up 启动 node server。 这样,我们得到了一个带 https 并通过 nginx 作为反向代理的 node server。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70000438/viewspace-2780498/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2021-05-27

  • 博文量
    50
  • 访问量
    39396