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。两种处理方式:- 指定
prod.env路径:# 替换原dotenv.read_dotenv() dotenv.read_dotenv(os.path.join(BASE_DIR.parent, 'prod.env')) - 直接删除所有
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
相关产品推荐
相关产品推荐

