Docker Nginx容器加载默认entrypoint启动后执行自定义脚本方法
实现方法
官方Nginx镜像默认的/docker-entrypoint.sh启动逻辑自带扩展点:启动Nginx主进程前,会自动按文件名排序执行/docker-entrypoint.d/目录下所有有可执行权限的.sh脚本,不需要修改、覆盖默认启动文件,也不需要在docker-compose里重写command配置,完全匹配需求。
具体操作步骤
1. 编写自定义初始化脚本
新建脚本文件40-certbot-init.sh(数字前缀保证它在官方自带的预处理脚本执行完之后再运行),内容如下:
#!/bin/sh set -e # 临时启动Nginx,用于响应Let's Encrypt的校验请求 nginx -g "daemon on;" # 等待Nginx启动完成 until nc -z localhost 80; do echo "等待Nginx启动完成,准备申请证书..." sleep 1 done # 执行证书申请,替换成自己的邮箱和域名 certbot certonly --webroot \ -w /var/lib/letsencrypt \ -d 你的域名 \ --non-interactive \ --agree-tos \ --email 你的联系邮箱 \ --no-eff-email # 写入SSL配置片段 cat > /etc/nginx/snippets/ssl.conf << EOF ssl_certificate /etc/letsencrypt/live/你的域名/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/你的域名/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; EOF # 关闭临时启动的Nginx,后续由默认entrypoint启动前台主进程 nginx -s stop
注意:脚本最后不要手动启动Nginx,交给默认启动流程拉起前台运行的Nginx主进程即可,避免主进程退出导致容器反复重启。
2. 修改现有Dockerfile
在原有Dockerfile的基础上,补充复制脚本、给执行权限的步骤,删掉原来RUN块最后未完成的certbot相关行:
FROM node:14-alpine as frontend-builder WORKDIR /app/frontend COPY ./frontend . ENV PATH ./node_modules/.bin/:$PATH RUN set -ex; \ yarn install --frozen-lockfile --production; \ yarn cache clean; \ yarn run build ############################################### FROM nginx:1.19.2-alpine RUN rm /etc/nginx/conf.d/default.conf COPY ./compose/production/build/nginx.conf /etc/nginx/conf.d COPY --from=frontend-builder /app/frontend/build /usr/share/nginx/html/build # 安装依赖 RUN apk update && \ apk add --no-cache nano certbot && \ mkdir -p /var/lib/letsencrypt /var/lib/letsencrypt/.well-known /etc/nginx/snippets && \ chgrp www-data /var/lib/letsencrypt && \ chmod g+s /var/lib/letsencrypt # 写入ACME校验配置片段 RUN cat > /etc/nginx/snippets/letsencrypt.conf << EOF location ^~/.well-known/acme-challenge/ { allow all; root /var/lib/letsencrypt/; default_type "text/plain"; try_files \$uri =404; } EOF # 复制自定义初始化脚本到Nginx官方扩展目录,给执行权限 COPY ./40-certbot-init.sh /docker-entrypoint.d/ RUN chmod +x /docker-entrypoint.d/40-certbot-init.sh
之前操作的问题说明
- 直接在Dockerfile里用RUN执行certbot:RUN指令是镜像构建阶段执行的,此时容器内Nginx服务根本没有启动,无法响应ACME校验请求,必然执行失败。
- 在docker-compose里配置command:直接自定义command会覆盖默认entrypoint的执行逻辑,如果自定义命令执行完后没有以前台模式拉起Nginx主进程,容器主进程退出就会触发重启策略反复重启。
可选优化
如果需要自动续期证书,可以在初始化脚本里加一条定时任务,续期完成后重载Nginx配置即可:
# 加在40-certbot-init.sh末尾,关闭临时Nginx之前 echo "0 3 * * * certbot renew --quiet --deploy-hook 'nginx -s reload'" | crontab - crond
内容的提问来源于stack exchange,提问作者user19271630
相关产品推荐
相关产品推荐

