基于GitHub Actions部署的DigitalOcean Docker镜像SSL配置问题
为Docker部署的DigitalOcean应用配置Let's Encrypt SSL证书
已通过Docker容器注册表将应用部署至DigitalOcean Droplet,尝试相关教程后仍无法为主域名及子域名https://dev.example.com启用HTTPS,以下是适配现有架构的解决方案。
现有环境信息
应用目录结构
root +--.github/workflows -- main.yml +-- app -- .next -- node_modules -- public -- src -- Dockerfile +-- nginx-conf -- nginx.conf +-- server -- node_modules -- src -- Dockerfile
现有Nginx配置(nginx-conf/nginx.conf)
server { listen 8000 default_server; listen [::]:8000 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name example.com dev.example.com; location / { root /var/www/html; try_files $uri /index.tsx; } location /api/ { proxy_pass http://server/api/; } }
app/Dockerfile
FROM node:14 WORKDIR /usr/src/app COPY . . RUN npm install RUN npm run build EXPOSE 3000 ENV NODE_ENV=test CMD [ "npm", "start" ]
server/Dockerfile
# Create build FROM node:alpine as build WORKDIR /server COPY package*.json ./ COPY tsconfig.json ./ RUN npm i -g typescript ts-node RUN npm ci COPY . . RUN npm run build # Run Build FROM node:alpine as prod WORKDIR /server COPY --from=build /server/package*.json ./ COPY --from=build /server/build ./ RUN npm ci --only=production EXPOSE 8000 CMD [ "npm", "run", "prod" ]
GitHub Actions部署脚本(main.yml片段)
jobs: buildClient: runs-on: ubuntu-latest defaults: run: working-directory: app steps: - uses: actions/checkout@v2 - name: Build client docker image run: | docker login -u ${{ secrets }} -p ${{ secrets }} registry.digitalocean.com docker build -t registry.digitalocean.com/....... . docker push registry.digitalocean.com/.......... deployContainers: name: Deploy containers to DO Droplet runs-on: ubuntu-latest needs: [ buildClient, buildServer ] steps: - name: SSH into Droplet uses: appleboy/ssh-action@v0.1.4 with: host: ${{ secrets }} username: ${{ secrets }} key: ${{ secrets.SSH }} passphrase: ${{ secrets }} script: | docker login -u ${{ secrets }} -p ${{ secrets }} registry.digitalocean.com docker stop app docker rm app docker image rm registry.digitalocean.com/....... docker pull registry.digitalocean.com/.......... docker run --name app -p 80:3000 -d registry.digitalocean.com/.........
解决方案步骤
1. 用Docker Compose编排容器
单独启动容器难以管理网络和依赖,在项目根目录创建docker-compose.yml,整合应用、服务、Nginx和Certbot:
version: '3.8' services: app: image: registry.digitalocean.com/你的镜像名/app:latest restart: always networks: - app-network server: image: registry.digitalocean.com/你的镜像名/server:latest restart: always networks: - app-network nginx: image: nginx:alpine restart: always ports: - "80:80" - "443:443" volumes: - ./nginx-conf:/etc/nginx/conf.d - ./certbot/conf:/etc/letsencrypt - ./certbot/www:/var/www/certbot 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 volumes: - ./certbot/conf:/etc/letsencrypt - ./certbot/www:/var/www/certbot entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" networks: - app-network networks: app-network: driver: bridge
2. 修改Nginx配置支持SSL和域名验证
更新nginx-conf/nginx.conf,实现HTTP转HTTPS并适配Let's Encrypt验证:
# HTTP服务器:处理域名验证和跳转HTTPS server { listen 80 default_server; listen [::]:80 default_server; server_name example.com dev.example.com; # Let's Encrypt验证路径 location /.well-known/acme-challenge/ { root /var/www/certbot; } # 所有HTTP请求跳转至HTTPS location / { return 301 https://$host$request_uri; } } # HTTPS服务器:提供加密访问 server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name example.com dev.example.com; # Certbot自动生成的证书路径 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # 转发前端请求至app容器 location / { proxy_pass http://app:3000; proxy_set_header Host $host; 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; } # 转发API请求至server容器 location /api/ { proxy_pass http://server:8000/api/; proxy_set_header Host $host; 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; } }
3. 首次获取SSL证书
在Droplet上执行以下命令(替换邮箱和域名):
# 创建Certbot所需目录 mkdir -p certbot/conf certbot/www # 生成证书 docker-compose run --rm certbot certonly --webroot -w /var/www/certbot -d example.com -d dev.example.com --email your-email@example.com --agree-tos --no-eff-email
4. 更新GitHub Actions部署脚本
将原有的单容器启动命令替换为Docker Compose部署,修改main.yml的deployContainers步骤:
deployContainers: name: Deploy containers to DO Droplet runs-on: ubuntu-latest needs: [buildClient, buildServer] steps: - name: Checkout code uses: actions/checkout@v2 - name: SSH into Droplet and deploy uses: appleboy/ssh-action@v0.1.4 with: host: ${{ secrets.DO_HOST }} username: ${{ secrets.DO_USER }} key: ${{ secrets.SSH_PRIVATE_KEY }} passphrase: ${{ secrets.SSH_PASSPHRASE }} script: | # 安装docker-compose(如果未安装) if ! command -v docker-compose &> /dev/null; then sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose fi # 登录DO容器注册表 docker login -u ${{ secrets.DO_REGISTRY_USER }} -p ${{ secrets.DO_REGISTRY_TOKEN }} registry.digitalocean.com # 拉取最新镜像并重启容器 docker-compose pull app server docker-compose up -d --force-recreate app server nginx # 清理旧镜像 docker system prune -f
5. 验证自动续期
Certbot容器已配置每12小时自动检查续期,Nginx会自动重载配置。可手动测试:
docker-compose run --rm certbot renew --dry-run
额外注意事项
- 确保Droplet防火墙开放80、443端口
- 确认
example.com和dev.example.com的DNS解析指向Droplet公网IP - 将app容器的
NODE_ENV改为production优化性能
内容的提问来源于stack exchange,提问作者asela daskon
相关产品推荐
相关产品推荐

