You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 18:58:06