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

Docker Compose部署Django时prod.env文件不生效的解决求助

问题描述

我有一个Docker化的Django+Nginx应用,配置了开发和生产两个环境变量文件(存储数据库凭证),但生产环境的prod.env文件未生效。文件夹结构如下:

root 
 - welzijn
 - admin

将.env和prod.env放在root目录时均不生效;但将存储生产凭证的.env文件放在welzijn目录时可以正常工作,而prod.env文件无论放在root还是welzijn目录都无法生效。删除prod.env后构建容器会提示文件不存在,说明Docker Compose能找到该文件,但变量未被应用到Django中。

Dockerfile代码

# pull official base image
FROM python:3.9-alpine3.13

# ENV PATH="/scripts:${PATH}"

# set work directory
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt /tmp/requirements.txt
COPY ./scripts /scripts

WORKDIR /usr/src/app
EXPOSE 8000


# install psycopg2 dependencies
ARG DEV=false
RUN python -m venv /py && \
    /py/bin/pip install --upgrade pip && \
    apk add --update --no-cache postgresql-client jpeg-dev && \
    apk add --update --no-cache --virtual .tmp-build-deps \
    build-base postgresql-dev musl-dev zlib zlib-dev linux-headers && \
    /py/bin/pip install -r /tmp/requirements.txt && \
    apk del .tmp-build-deps && \
    adduser \
    --disabled-password \
    --no-create-home \
    django-user 


ENV PATH="/scripts:/py/bin:$PATH"
USER django-user
COPY . .
# run entrypoint.sh

CMD ["run.sh"]

docker-compose-deploy.yml代码

version: "3.9"

services:
  web:
    image: crdierenwelzijn.azurecr.io/web1
    build:
      context: ./
      dockerfile: Dockerfile.prod
    restart: always

    command: gunicorn DierenWelzijn.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - static_volume:/usr/src/app/staticfiles
      - media_volume:/usr/src/app/media
    expose:
      - 8000
    env_file:
      - prod.env

  proxy:
    image: crdierenwelzijn.azurecr.io/proxy1
    build:
      context: ./proxy
    restart: always
    depends_on:
      - web
    ports:
      - 80:80
    volumes:
      - static_volume:/home/app/staticfiles
      - media_volume:/home/app/media

volumes:
  static_volume:
  media_volume:

nginx.conf代码

upstream DierenWelzijn {
    server web:8000;
}

server {

    listen 80;
    server_name https://dierenwelzijndocker.azurewebsites.net; 

    location / {
        proxy_pass http://DierenWelzijn;
        proxy_set_header Host $http_host;       
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;                
        client_max_body_size    10M;       
        proxy_redirect off;
    }

    location /static/ {
        alias /home/app/staticfiles/;
    }

    location /media/ {
        alias /home/app/media/;
    }
}

settings.py部分代码

from os import environ
from pathlib import Path
import os
import dotenv

dotenv.read_dotenv()

BASE_DIR = Path(__file__).resolve().parent.parent

# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

SECRET_KEY = os.environ.get('SECRET_KEY')
DEBUG = bool(int(os.environ.get('DEBUG', 0)))

ALLOWED_HOSTS = ['localhost', '192.168.1.135',
                 'dockerdierenwelzijn.azurewebsites.net', 'www.dockerdierenwelzijn.azurewebsites.net']
ALLOWED_HOSTS.extend(
    filter(
        None,
        os.environ.get('ALLOWED_HOSTS', '').split(" "),
    )
)
# SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
CSRF_TRUSTED_ORIGINS = [
    "https://dockerdierenwelzijn.azurewebsites.net", "http://192.168.1.135:8000"]
# CSRF_TRUSTED_ORIGINS = os.listdir('CSRF_TRUSTED_ORIGINS')


# Application definition
CORS_ALLOW_CREDENTIALS = True

SECURE_CROSS_ORIGIN_OPENER_POLICY = None

DATABASES = {
    'default': {
        "ENGINE": 'django.db.backends.postgresql',
        "HOST": os.environ.get("DB_HOST"),
        "NAME": os.environ.get("DB_NAME"),
        "USER": os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASS'),
        "PORT": os.environ.get("DB_PORT", "5432"),
    }
}
解决方案

问题核心在于dotenv的加载逻辑和环境变量传递优先级,按以下步骤修改即可:

  • 修正dotenv加载逻辑或直接移除
    当前settings.py中dotenv.read_dotenv()默认只在welzijn目录找.env文件,完全没读取prod.env。两种处理方式:

    1. 指定prod.env路径:
      # 替换原dotenv.read_dotenv()
      dotenv.read_dotenv(os.path.join(BASE_DIR.parent, 'prod.env'))
      
    2. 直接删除所有dotenv相关代码:Docker Compose已经通过env_file把变量注入容器环境,Django用os.environ.get()就能直接读取,不需要额外读文件。
  • 确认prod.env格式正确
    文件每一行必须是KEY=VALUE格式,不要加多余空格,字符串值无需加引号(含空格的情况除外)。

  • 验证容器环境变量
    运行命令进入web容器检查变量是否存在:

    docker-compose -f docker-compose-deploy.yml exec web env
    

    若能看到prod.env中的变量,说明Docker传递成功,问题在Django读取逻辑;若看不到,检查prod.env路径和格式。

  • 修正Nginx配置(非环境变量问题,但需修复)
    nginx.conf中server_name不能写完整URL,改为纯域名:

    server_name dierenwelzijndocker.azurewebsites.net;
    

内容的提问来源于stack exchange,提问作者mightycode Newton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 01:10:25