Using environment variables to configure Django and other Python applications is awesome, but using them with Apache and mod_wsgi in Docker is a tricky process to get right.
That's why I created a step-by-step tutorial and a sample application to review all the info you need in one place.
While this tutorial uses Docker and Django, the same steps apply whether you're using a virtual machine or a different Python framework.
Review the code directly from the repository >
When hosting a Python WSGI compatible framework like Django in Apache with mod_wsgi, the only environment variables populated in the os.environ dictionary are those that exist in the environment of the script that starts Apache. But instead of having to mess with Apache's service manager settings (e.g. systemd or systemctl), there's a better way.
Most Apache distributions provide a shell script specifically for the purpose of setting environment variables that are made available to modules such as mod_wsgi.
It's then a matter of knowing the location of this shell script since it can be different depending on the Linux distribution. For example:
We'll be using Debian-based python:3.9-slim-buster Docker image.
Our goal is for secrets to be fetched as key/value pairs and written to the envvars file in the typical shell environment variables format:
But from where and how do we fetch the app config and secrets to populate that file?
Since we're fans of Doppler :) let's start with a Doppler CLI example. But it's important to note that the mechanics of "fetch secrets, then append to file" can easily be adapted.
First, you need to set up your project in Doppler. To make the process easier, Import to Doppler to follow along.
Then use the Doppler CLI inside the Docker container to fetch the secrets:
Note: This requires a DOPPLER_TOKEN environment variable with a Service Token value
Did you notice that I used single quotes, not double quotes around the values?
That's because it gives you the flexibility of storing secrets with double quotes such as JSON in Doppler. As an example, you could use this to dynamically set Django's ALLOWED_HOSTS for any environment.
While you could also use a .env file, I wouldn't recommend it. Instead, consider using a secrets manager— why not Doppler?
Knowing the downsides to using .env files, If you must use them in your environment, the process is still straightforward:
Now that we know how to pass environment variables from Apache to mod_wsgi, let's move onto getting this working in Docker.
Let's review the task of configuring a Python Django Application using Apache and mod_wsgi in Docker into three parts:
If you only want to review the working code examples, review the examples on GitHub >
Since this isn't a Docker or Apache tutorial, we won't go into depth about the Dockerfile or Apache site config file. Do you have questions, need help, or want to share your thoughts? Check out our community forum >
Running your application in Docker is usually a case of setting the CMD, for example:
But it's trickier here because we need to append the environment variables to /etc/apache2/envvars before running Apache.
Since this requires multiple commands, let's create a custom script:
Here's an example Apache site config file for a Django application:
The Docker file is reasonably straightforward, installing the Doppler CLI and Apache dependencies before copying the Django source code, custom script, and Apache site config:
With all the pieces in place, we can now build the Docker image (clone the sample repository to follow along):
Now we're ready to run the container!
Let's start with a Doppler example, then with an .env file.
With Doppler, you'll first need to set a DOPPLER_TOKEN environment variable to the value of a Service Token. This is what provides read-only access to a specific Doppler config in production environments.
Usually, this would be securely set by your deployment environment (e.g. GitHub Actions Secret) but for this exercise, we'll set it manually:
Now run the container:
To run the .env file version, we'll use the sample.env file from the sample repository:
Then to run the container:
Now you know how to configure Python applications hosted with Apache and mod_wsgi running in Docker using environment variables for app configuration and secrets.
After using the Doppler CLI versus managing .env files through our exercise, the difference is clear.
Manage environment variables, rotate secrets, and ship securely with Doppler >
Trusted by the world’s best DevOps and security teams. Doppler is the secrets manager developers love.