如何在 Docker 中使用 Apache 和 mod_wsgi 为 Python Django 应用程序设置环境变量
使用环境变量来配置 Django 和其他 Python 应用程序非常棒,但是在 Docker 中将它们与 Apache 和 mod_wsgi 一起使用是一件棘手的事情。
这就是为什么我创建了这个分步教程和示例应用程序将您需要的所有信息放在一个地方。
尽管本教程适用于 Docker 和 Django,但无论您使用的是虚拟机还是不同的 Python 框架,都适用相同的步骤。
更喜欢阅读代码?前往的随附存储库 https://github.com/DopplerUniversity/django-apache-mod-wsgi
环境变量,Apache 和 mod_wsgi
当使用 mod_wsgi 在 Apache 中托管 Python WSGI 兼容框架(如 Django)时,os.environ 字典中填充的唯一环境变量是启动 Apache 的脚本环境中存在的环境变量。但是不必弄乱 Apache 的服务管理器设置(例如 systemd 或 systemctl),有更好的方法。
大多数 Apache 发行版都提供了一个专门用于设置环境变量的 shell 脚本,这些环境变量将可用于诸如 mod_wsgi 之类的模块。
然后知道这个 shell 脚本的位置是一个问题,因为它可能会因 Linux 发行版的不同而不同。例如:
-
Debian/Ubuntu:/etc/apache2/envvars
-
CentOS:/etc/sysconfig/httpd
我们将使用python:3.9-slim-buster Docker 镜像基于 Debian。
将应用程序配置和机密附加到环境变量文件
本质上,它归结为以键/值对的形式获取秘密,并以典型的 shell 环境变量格式将它们写入 envvars 文件:
export FIRST_NAME="The"
export LAST_NAME="Mandalorion"
但是我们从哪里以及如何获取应用程序配置和秘密来填充该文件?
由于我是 Doppler 的开发者倡导者,我将从Doppler CLI示例开始,但是“获取秘密,然后附加到文件”的机制可以很容易地适应。
首先,您需要在 Doppler 中设置您的项目,如果您想继续,可以使用以下按钮开始。
然后使用 Docker 容器内的 Doppler CLI 获取机密(需要具有服务令牌值的 DOPPLER_TOKEN 环境变量):
# Transform JSON key:value pairs into export statements using jq
if [ -n "$DOPPLER_TOKEN" ]; then
echo '[info]: Appending environment variables to /etc/apache/envvars using Doppler CLI'
doppler secrets download --no-file | jq -r $'. | to_entries[] | "export \(.key)=\'\(.value)\'"' >> /etc/apache2/envvars
fi
请注意,我使用了单引号,而不是值周围的双引号?
这是因为它为您提供了在多普勒中使用双引号(例如 JSON)存储机密的灵活性,例如,您可以使用为任何环境动态设置 Django 的 ALLOWED_HOSTS设置。
ALLOWED_HOSTS = json.loads(os.environ['ALLOWED_HOSTS'])
您也可以使用 .env 文件,但我不推荐它,相反,我会考虑使用秘密管理器。
但除此之外,您可以使用 .env 文件执行此操作:
if [ -f "$PWD/.env" ]; then
echo '[info]: Appending environment variables to /etc/apache/envvars from .env file'
cat "$PWD/.env" >> /etc/apache2/envvars
fi
现在我们知道如何将环境变量从 Apache 传递到 mod_wsgi,让我们继续在 Docker 中使用它。
Apache 和 mod_wsgi 的 Docker 配置
让我们将使用 Apache 和 Docker 中的 mod_wsgi 配置 Python Django 应用程序的任务分解为三个步骤:
1.自定义启动脚本
-
Apache 站点配置
-
Dockerfile
如果您只想查看工作代码示例,请前往的随附存储库 https://github.com/DopplerUniversity/django-apache-mod-wsgi
由于这不是 Docker 或 Apache 教程,我不会深入研究 Dockerfile 或 Apache 站点配置文件,但如果您有任何问题,请前往多普勒社区论坛我会能够在那里帮助你。
1.自定义启动脚本
在 Docker 中运行应用程序通常需要设置 CMD, 例如:
CMD ["python", "src/app.py"]
但这里比较棘手,因为我们首先需要在运行 Apache 之前将环境变量附加到/etc/apache2/envvars。
由于这需要多个命令,我们将创建一个自定义脚本:
#!/bin/bash
# apache-doppler-start
set -e
echo 'ServerName localhost' >> /etc/apache2/apache2.conf # Silence FQDN warning
# Doppler CLI
if [ -n "$DOPPLER_TOKEN" ]; then
echo '[info]: Appending environment variables to /etc/apache/envvars from Doppler CLI'
doppler secrets download --no-file | jq -r $'. | to_entries[] | "export \(.key)=\'\(.value)\'"' >> /etc/apache2/envvars
fi
# Mounted .env file
if [ -f "$PWD/.env" ]; then
echo '[info]: Appending environment variables to /etc/apache/envvars from .env file'
cat "$PWD/.env" >> /etc/apache2/envvars
fi
# Run Apache
apache2ctl -D FOREGROUND
2.阿帕奇站点配置
这是 Django 应用程序的示例 Apache 站点配置文件:
# wsgi.conf
<VirtualHost *:80>
ServerName django-apache-mod-wsgi
ServerAlias django-apache-mod-wsgi
ServerAdmin webmaster@doppler
# Defining `WSGIDaemonProcess` and `WSGIProcessGroup` triggers daemon mode
WSGIDaemonProcess django-apache-mod-wsgi processes=2 threads=15 display-name=%{GROUP} python-path=/usr/local/lib/python3.9/site-packages:/usr/src/app
WSGIProcessGroup django-apache-mod-wsgi
WSGIScriptAlias / /usr/src/app/doppler/wsgi.py
<Directory /usr/src/app/doppler/>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
# Redirect all logging to stdout for Docker
LogLevel INFO
ErrorLog /dev/stdout
TransferLog /dev/stdout
</VirtualHost>
3. Dockerfile
Dockerfile 相当简单,在复制 Django 源代码、自定义脚本和 Apache 站点配置之前安装 Doppler CLI 和 Apache 依赖项:
FROM python:3.9-slim-buster
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
# Install Doppler CLI and related dependencies
RUN apt-get -qq update && apt-get install -y apt-transport-https ca-certificates curl gnupg jq && \
curl -sLf --retry 3 --tlsv1.2 --proto "=https" 'https://packages.doppler.com/public/cli/gpg.DE2A7741A397C129.key' | apt-key add - && \
echo "deb https://packages.doppler.com/public/cli/deb/debian any-version main" | tee /etc/apt/sources.list.d/doppler-cli.list && \
apt-get -qq update && apt-get install doppler
# Install Apache and related dependencies
RUN apt-get install --yes apache2 apache2-dev libapache2-mod-wsgi-py3 && \
apt-get clean && \
apt-get remove --purge --auto-remove -y && \
rm -rf /var/lib/apt/lists/*
WORKDIR /usr/src/app
COPY requirements*.txt .
RUN pip install --quiet --no-cache-dir --upgrade pip && \
pip install --quiet --no-cache-dir -r requirements.txt
# Application source
COPY src/ ./
# Custom CMD script
COPY apache-doppler-start /usr/local/bin/
# Apache site config
COPY wsgi.conf /etc/apache2/sites-enabled/000-default.conf
EXPOSE 80 443
# https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop
STOPSIGNAL SIGWINCH
CMD ["apache-doppler-start"]
准备好所有部分后,我们现在可以构建 Docker 映像(克隆示例存储库以继续进行操作):
docker image build -t django-apache-mod-wsgi:latest .
现在我们已经准备好运行容器了!
在 Docker 中使用 Apache 和 mod_wsgi 运行 Django 应用程序
我们将从一个多普勒示例开始,然后是一个 .env 文件。
使用 Doppler,您首先需要将 DOPPLER_TOKEN 环境变量设置为服务令牌的值。这就是在生产环境中提供对特定多普勒配置的只读访问权限的原因。
通常,这将由您的部署环境(例如 GitHub Action Secret)安全地设置,但为了完整性和简单性,我们将在下面手动设置:
export DOPPLER_TOKEN="dp.st.xxxx" # Service token value created from Doppler dashboard
现在运行容器:
docker container run \
-it \
--init \
--name doppler-apache-mod-wsgi \
--rm \
-p 8080:80 \
-e DOPPLER_TOKEN="$DOPPLER_TOKEN" \
django-apache-mod-wsgi
.env 文件
要运行 .env 文件版本,我们将使用来自示例存储库的 sample.env 文件:
# sample.env
export DJANGO_SETTINGS_MODULE='doppler.settings'
export DEBUG='yes'
export ALLOWED_HOSTS='["*"]'
export SECRET_KEY='bf5e1b31-6ba7-48e2-9175-f2293671e6df'
然后运行容器:
docker container run \
-it \
--init \
--name dotenv-apache-mod-wsgi \
--rm \
-v $(pwd)/sample.env:/usr/src/app/.env \
-p 8080:80 \
django-apache-mod-wsgi
总结
做得很好,直到最后!
现在您知道了如何使用环境变量配置应用程序配置和机密来配置由 Apache 和在 Docker 中运行的 mod_wsgi 托管的 Python 应用程序。
欢迎反馈,您可以通过Twitter、我们的社区论坛联系我们,或发送电子邮件至ryan.blunden@doppler.com。
更多推荐



所有评论(0)