将环境变量中的Django SECRET_KEY传递给Dockerized gunicorn

时间:2018-11-30 20:17:49

标签: django docker environment-variables gunicorn secret-key

某些背景

最近我遇到了一个问题,尽管DJANGO_SETTINGS_MODULE被设置为另一个,我的Django应用程序仍在使用基本设置文件。原来的问题是,gunicorn没有继承环境变量,解决方案是将-e DJANGO_SETTINGS_MODULE=sasite.settings.production添加到我称为gunicorn的Dockerfile CMD条目中。

问题

我在如何处理应用程序中的SECRET_KEY时遇到了麻烦。尽管我以前将其存储在JSON文件中,但我将其设置为环境变量,但这似乎不太安全(如果我输入错了,请纠正我)。

问题的另一部分是,当使用gunicorn时,它不会继承通常在容器上设置的环境变量。如上所述,我遇到了DJANGO_SETTINGS_MODULE这个问题。我认为Gunicorn也会与SECRET_KEY出现问题。怎么办呢?

我当前的方法

我在环境变量中设置SECRET_KEY并将其加载到Django设置文件中。我在包含export SECRET_KEY=<secretkey>的文件“ app-env”中设置值,Dockerfile包含RUN source app-env,以便在容器中设置环境变量。

关注问题

用Dockerfile命令ENV设置环境变量SECRET_KEY而不是采购文件会更好吗?这样在Dockerfile中对秘密密钥进行硬编码是否可以接受(似乎对我而言不是)?

在Dockerized应用程序中是否有处理秘密密钥的“最佳实践”?

如果事实证明它和环境变量一样安全,那么我总是可以回到JSON。但是弄清楚人们如何使用环境变量来处理SECRET_KEY和gunicorn的问题仍然是一件好事。

代码

这是Dockerfile:

FROM python:3.6
LABEL maintainer x@x.com

ARG requirements=requirements/production.txt
ENV DJANGO_SETTINGS_MODULE=sasite.settings.production_test

WORKDIR /app

COPY manage.py /app/
COPY requirements/ /app/requirements/ 

RUN pip install -r $requirements

COPY config config
COPY sasite sasite
COPY templates templates
COPY logs logs
COPY scripts scripts

RUN source app-env

EXPOSE 8001

CMD ["/usr/local/bin/gunicorn", "--config", "config/gunicorn.conf", "--log-config", "config/logging.conf", "-e", "DJANGO_SETTINGS_MODULE=sasite.settings.production_test", "-w", "4", "-b", "0.0.0.0:8001", "sasite.wsgi:application"]

1 个答案:

答案 0 :(得分:2)

我将首先说明为什么它不能按原样工作,然后讨论您必须前进的选项:

在容器的构建过程中,单个RUN指令作为其自己的独立容器运行。对于后续层,仅捕获对该容器的写层的文件系统所做的更改。这意味着您的source app-env命令将运行并退出,并且可能不会在磁盘上进行任何更改,从而使RUN行变为无操作。

Docker允许您在构建时使用ENV指令指定环境变量,该指令已使用DJANGO_SETTINGS_MODULE变量完成。我不一定同意在此处指定SECRET_KEY,尽管可以在Dockerfile中放置开发所需的值。


由于SECRET_KEY变量对于不同的环境(登台和生产)可能有所不同,因此在运行时设置该变量可能很有意义。例如:

docker run -d -e SECRET_KEY=supersecretkey mydjangoproject

-e选项是--env的缩写。此外,还有--env-file,您可以传入变量和值的文件。如果您不直接使用docker cli,那么您的docker客户端也应该可以在其中指定这些名称(例如,docker-compose可以让您在yaml中指定这两个名称)


在这种特定情况下,由于您在容器内有 知道哪些变量是必需的,因此可以在运行时调用它。有两种方法可以完成此操作。首先是将CMD更改为此:

CMD source app-env && /usr/local/bin/gunicorn --config config/gunicorn.conf --log-config config/logging.conf -e DJANGO_SETTINGS_MODULE=sasite.settings.production_test -w 4 -b 0.0.0.0:8001 sasite.wsgi:application

这使用CMD的外壳封装语法而不是exec语法。这意味着CMD的整个参数将在/ bin / sh -c“”

中运行

shell将处理正在运行的source app-env,然后处理您的gunicorn命令。

如果您需要在运行时更改命令,则需要记住在需要的地方指定source app-env &&,这使我想到了另一种方法,即使用ENTRYPOINT脚本


Docker的ENTRYPOINT功能使您可以在容器首次启动时处理容器内部的所有必要启动步骤。考虑以下入口点脚本:

#!/bin/bash
cd /app && source app-env && cd - && exec "$@"

这将明确cd到app-env所在的位置,获取它,将cd返回到oldpwd所在的位置,然后执行命令。现在,您可以在运行时为此映像覆盖命令目录和工作目录,并使app-env文件中指定的任何变量处于活动状态。要使用此脚本,您需要将其添加到映像中的某个位置,并确保其可执行,然后使用ENTRYPOINT指令在Dockerfile中将其指定:

ADD entrypoint.sh /entrypoint.sh
RUN chmod a+x /entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

使用入口点策略,您可以保持CMD不变而无需更改。