Docker Compose部署DRF项目:JSON环境变量读取失败求助
问题分析与解决方法
核心问题
- Docker Compose的
env_file不支持JSON格式:env_file仅识别键值对格式的文本文件(如.env),你的secrets.json是JSON结构,无法被直接加载。 - 原entrypoint.sh无法解析JSON:脚本用
=分割行的方式读取文件,完全适配不了JSON的语法结构,导致环境变量未正确导出。 - backend服务未使用entrypoint.sh:docker-compose.yml里backend的entrypoint直接写了启动命令,等于没用到你准备的entrypoint脚本。
具体修改方案
1. 修复entrypoint.sh,使其正确解析JSON
替换原entrypoint.sh内容为以下代码(依赖jq工具解析JSON,需确保镜像中已安装):
#!/bin/bash # 解析顶级JSON键值对,导出为环境变量 for key in $(jq -r 'keys[]' /app/secrets.json); do value=$(jq -r --arg key "$key" '.[$key]' /app/secrets.json) # 跳过嵌套的DATABASES,单独处理 if [ "$key" != "DATABASES" ]; then export "$key"="$value" fi done # 解析DATABASES下的嵌套字段,统一添加POSTGRES_前缀 db_default=$(jq -r '.DATABASES.default' /app/secrets.json) for db_key in $(echo "$db_default" | jq -r 'keys[]'); do db_value=$(echo "$db_default" | jq -r --arg key "$db_key" '.[$key]') export "POSTGRES_$(echo "$db_key" | tr '[:lower:]' '[:upper:]')"="$db_value" done # 执行Django启动流程 python manage.py collectstatic --no-input python manage.py migrate gunicorn Realby_project.wsgi --workers=5 -b 0.0.0.0:8000
补充:需在Django镜像的Dockerfile中安装
jq,基于Debian/Ubuntu的镜像添加:RUN apt-get update && apt-get install -y jq;基于Alpine的镜像添加:RUN apk add --no-cache jq。
2. 修正docker-compose.yml配置
- 移除postgres服务无效的
env_file配置,改用环境变量传递数据库信息; - 修改backend服务的entrypoint,指向entrypoint.sh;
- 删除backend中冗余的environment变量(将由entrypoint.sh从JSON自动导出)。
修改后的docker-compose.yml:
version: '3.8' volumes: postgres: {} django_media: {} django_static: {} services: postgres: container_name: postgres image: postgres:15.3 volumes: - postgres:/var/lib/postgresql/data/ environment: - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_NAME=${POSTGRES_NAME} backend: container_name: backend build: ./backend/ entrypoint: /app/entrypoint.sh volumes: - ./backend/django/:/app/ - /etc/localtime:/etc/localtime:ro - django_media:/app/media/ - django_static:/app/static/ - ./backend/django/secrets.json:/app/secrets.json environment: - DEBUG=1 depends_on: - postgres restart: always nginx: container_name : nginx image: nginx:1.23.2 ports: - "80:80" - "443:443" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf - django_media:/media/ - django_static:/static/ depends_on: - backend restart: always
3. 配置Django读取环境变量
在settings.py中通过os.environ.get()获取环境变量,示例:
import os SECRET_KEY = os.environ.get('SECRET_KEY') DEBUG = os.environ.get('DEBUG', False) == '1' DATABASES = { 'default': { 'ENGINE': os.environ.get('POSTGRES_ENGINE'), 'NAME': os.environ.get('POSTGRES_NAME'), 'USER': os.environ.get('POSTGRES_USER'), 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), 'HOST': os.environ.get('POSTGRES_HOST'), 'PORT': os.environ.get('POSTGRES_PORT'), } } # 第三方服务配置同理 SOCIAL_AUTH_GOOGLE_CLIENT_ID = os.environ.get('SOCIAL_AUTH_GOOGLE_CLIENT_ID') SOCIAL_AUTH_GOOGLE_SECRET = os.environ.get('SOCIAL_AUTH_GOOGLE_SECRET')
额外注意事项
- 若不想依赖
jq,可改用Python脚本解析JSON并导出环境变量; - 确保
secrets.json中字段值无多余引号,jq会自动处理合法的JSON格式; - 生产环境建议使用Docker Secrets或专业密钥管理工具,避免直接挂载密钥文件。
内容的提问来源于stack exchange,提问作者VinylStage
相关产品推荐
相关产品推荐

