如何在DigitalOcean Droplet中搭建并分离部署生产与开发环境?
部署Django/数据库容器到DigitalOcean Droplet:生产与开发环境分离方案
我目前通过Github Action将Docker化的Django/数据库容器部署到单个DigitalOcean Droplet,现在需要分离生产与开发环境逻辑并实现单独部署,有两个疑问:
- 是否需要为开发环境新增Droplet?
- 是否需要为生产、开发环境分别创建独立的Github Action和docker-compose.yml文件?
问题解答
1. 是否需要为开发环境新增Droplet?
这取决于你的隔离需求和服务器资源情况:
- 无需新增的场景:如果Droplet资源充裕(CPU、内存足够支撑双环境运行),且对环境隔离要求不高(比如开发环境仅用于内部测试,不会频繁占用大量资源影响生产),可以在同一个Droplet内通过Docker Compose的
profiles特性实现环境分离,节省成本。 - 需要新增的场景:如果生产环境需要严格的性能保障(开发环境的调试、构建操作可能抢占资源),或者有安全隔离要求(比如生产数据不能与开发环境共享同一服务器),建议单独创建开发环境Droplet,避免相互干扰。
2. 是否需要独立的Github Action和docker-compose.yml文件?
不需要强制拆分,利用现有工具特性即可实现环境区分,降低维护成本:
- 对于Docker Compose:你当前的配置已经用到
profiles,可以继续基于单文件,通过指定--profile参数启动对应环境的服务,无需拆分文件。 - 对于Github Action:可以通过分支触发规则区分生产/开发部署,比如
main分支推送触发生产环境部署,dev分支推送触发开发环境部署,在Action脚本中根据分支选择对应的Docker Compose命令。
优化后的配置示例
1. 调整后的Github Action配置
name: 环境部署 on: push: branches: - main # 生产环境分支 - dev # 开发环境分支 jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: 上传代码到Droplet uses: burnett01/rsync-deployments@5.2 with: switches: --exclude="\.git" --exclude="\.github" --exclude="\.env*" --exclude="logs" -avzr --delete path: ./ remote_path: /root/Name # 单Droplet用同一个IP;双Droplet则根据分支切换IP remote_host: ${{ github.ref == 'refs/heads/dev' && secrets.ssh_ip_dev || secrets.ssh_ip_prod }} remote_user: ${{ secrets.ssh_user }} remote_key: ${{ secrets.key }} - name: 构建并启动对应环境服务 uses: appleboy/ssh-action@master with: host: ${{ github.ref == 'refs/heads/dev' && secrets.ssh_ip_dev || secrets.ssh_ip_prod }} username: ${{ secrets.ssh_user }} key: ${{ secrets.key }} env: POSTGRES_USER: ${{ secrets.postgres_user }} POSTGRES_DB: ${{ secrets.postgres_db }} POSTGRES_PASSWORD: ${{ secrets.postgres_password }} POSTGRES_PROD_PORT: ${{ secrets.postgres_prod_port }} POSTGRES_DEV_PORT: ${{ secrets.postgres_dev_port }} script: | # 根据分支选择启动的profile和容器名 if [ "${{ github.ref }}" == "refs/heads/main" ]; then PROFILE="prod" else PROFILE="dev" fi docker-compose -f /root/Name/docker-compose.yml build --profile $PROFILE docker-compose -f /root/Name/docker-compose.yml down --profile $PROFILE docker-compose -f /root/Name/docker-compose.yml up -d --profile $PROFILE - name: 执行数据库迁移 uses: appleboy/ssh-action@master with: host: ${{ github.ref == 'refs/heads/dev' && secrets.ssh_ip_dev || secrets.ssh_ip_prod }} username: ${{ secrets.ssh_user }} key: ${{ secrets.key }} script: | CONTAINER_NAME=$(if [ "${{ github.ref }}" == "refs/heads/main" ]; then echo "prod"; else echo "dev"; fi) docker exec -i $CONTAINER_NAME python manage.py migrate
2. 优化后的Docker Compose配置(保留profiles,增强环境区分)
version: "3.7" services: webserver: image: nginx:1.22.0 container_name: webserver restart: always ports: - 80:80 - 443:443 volumes: - ./logs/nginx/:/var/log/nginx/ - ./nginx/ssl/:/etc/nginx/ssl/:ro - ./nginx/configs/:/etc/nginx/sites-enabled/:ro - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro profiles: - prod - dev # 让Nginx属于双环境,统一反向代理 db_prod: image: postgres:15 container_name: db_prod restart: always ports: - ${POSTGRES_PROD_PORT}:5432 volumes: - db_prod:/var/lib/postgresql/data environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_DB: ${POSTGRES_DB} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} profiles: - prod db_dev: image: postgres:15 container_name: db_dev restart: always ports: - ${POSTGRES_DEV_PORT}:5432 volumes: - db_dev:/var/lib/postgresql/data environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_DB: ${POSTGRES_DB}_dev # 开发环境使用独立数据库名 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} profiles: - dev prod: build: ./src command: ["./start.sh"] container_name: prod restart: always volumes: - env_prod:/env:delegated - .env.prod:/app/.env:ro # 生产环境用独立配置文件 - ./logs/prod/gunicorn/:/var/log/gunicorn/ depends_on: - db_prod environment: LOG_PATH: /var/log POSTGRES_HOST: db_prod profiles: - prod dev: build: ./src command: ["./start.sh"] container_name: dev restart: always volumes: - env_dev:/env:delegated - .env.dev:/app/.env:ro # 开发环境用独立配置文件 - ./src:/app # 挂载代码目录,支持热重载 - ./logs/dev/gunicorn/:/var/log/gunicorn/ depends_on: - db_dev environment: LOG_PATH: /var/log POSTGRES_HOST: db_dev profiles: - dev adminer: image: dockette/adminer:pgsql container_name: adminer restart: always environment: UPLOAD: ${ADM_UPLOAD} profiles: - dev # 仅开发环境启用数据库管理工具 volumes: db_prod: db_dev: env_dev: env_prod:
内容的提问来源于stack exchange,提问作者B. Mohammad
相关产品推荐
相关产品推荐

