如何使用docker compose拆分开发环境文件和生产环境文件?

How to split development env file and production env file with docker compose?

提问人:mightycode Newton 提问时间:11/16/2023 最后编辑:mightycode Newton 更新时间:11/17/2023 访问量:78

问:

我已经用nginxdockerized了django应用程序。我有两个环境文件:一个用于开发,一个用于生产。env 文件的内容是数据库的凭据。

但显然,不会执行生产环境文件中的凭据。

我的文件夹结构如下所示:

root 
 - welzijn
 -admin

因此,当我将名为 .env 和 prod.env 的 env 文件放在根文件夹中时,它不起作用。

但是当我将带有生产凭据的 .env 文件放在 welzijn 文件夹中时,它就可以工作了。即使我将文件 prod.env 放在文件夹 welzijn 中,它也不起作用

我真的为此挠头。

所以这是 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"),
    }
}


所以我现在在根文件夹中有 prod.env 文件。但这行不通。

奇怪的是,当我从根文件夹中删除 prod.env 文件并尝试构建 docker 容器时,我收到一个错误,指出该文件不存在。

问:为了执行 prod.env 文件,我必须更改什么?

django nginx docker-compose 环境变量

评论

1赞 David Maze 11/16/2023
应用程序如何读取其设置?如果应用程序本身正在寻找一个名为 的文件,则会使用您进入映像的文件。Compose 将设置实际的环境变量,在 Python 中,您将通过这些变量和类似的机制进行读取。.envCOPYenv_file:os.environ
0赞 mightycode Newton 11/16/2023
@DavidMaze。我已经用 settings.py 文件更新了帖子。
0赞 mightycode Newton 11/16/2023
但是我必须改变什么?

答:

0赞 Moziii 11/16/2023 #1

根据您的描述,问题似乎出在 Docker 设置中如何读取和使用文件中的环境变量。以下是帮助解决此问题的一些步骤和注意事项:prod.env

  • 确保文件中指令中指定的路径正确指向文件。如果文件位于根目录中,则路径应正确为 。env_filedocker-compose-deploy.ymlprod.env- prod.env
  • 该文件需要位于 Docker 映像的生成上下文中。如果要从根目录构建映像(如 中所示),则放置在根目录中应该可以工作。prod.envcontext: ./docker-compose-deploy.ymlprod.env
  • 在 中,您正在使用 .默认情况下,此函数查找文件。如果您使用的是其他文件名(如 prod.env),则需要显式指定路径:settings.pydotenv.read_dotenv()an .env
dotenv.read_dotenv(os.path.join(BASE_DIR, 'prod.env')) 

确保在访问任何环境变量之前执行此代码。

  • 在 Dockerfile 中,将整个项目目录复制到映像中。如果 prod.env 文件位于根目录中,则应包括该文件。但是,请注意,Dockerfile 中的 ENV 指令在构建时设置环境变量,而不是在运行时设置环境变量。你的 Django 应用在运行时读取它们。
  • 确保文件中的卷挂载不会无意中覆盖 prod.env 所在的目录。docker-compose-deploy.yml
  • 生成映像后,运行容器并在其中执行,以检查 prod.env 文件是否存在于预期位置。
  • 复制文件后,暂时将 Dockerfile 中的命令添加到文件中,以确保正确复制该文件。catprod.env
  • 用于验证撰写文件是否已正确配置并包含 prod.env 文件。docker compose config
  • 检查 prod.env 文件的权限,确保在容器内运行 Django 应用程序的用户可读取该文件。
  • 每次对文件或 Docker 配置进行更改时,请确保使用 .prod.envdocker compose up --build

评论

0赞 Elvin Jafarov 11/17/2023
docker-compose 被认为是旧技术,最好使用 docker compose。
1赞 Moziii 11/17/2023
在大多数使用 Docker Compose v2 的现代设置中,这两个命令都可能指向相同的 Docker Compose v2 功能,但这并不是普遍正确的,尤其是在仍安装了 Docker Compose v1 的环境中。你是对的; 应该最好使用,我编辑了我的答案。@ElvinJafarovdocker compose
0赞 mightycode Newton 11/17/2023
好的,但我使用的是 docker compose 而不是 docker-compose: docker compose -f docker-compose-deploy.yml build。好的,我将尝试将docker-compose-deploy文件放在一个单独的文件夹中。