- How To Use Docker Python Images and Docker Compose With Python
- Is Docker Important for Python Development
- More Useful Docker Commands
- Closing Thoughts
- Ways to set environment variables in Compose
- Compose file
- Substitute with an .env file
- Use the environment attribute
- Use the env_file attribute
- Substitute from the shell
- CLI
- Substitute with —env-file
- Set environment variables with docker compose run —env
How To Use Docker Python Images and Docker Compose With Python
Docker and Python are two great tools that work great together to simplify the development and deployment of an application. Most of my readers are naturally already quite familiar with Python, and I’m sure most are familiar with Docker, but if you’re not, don’t worry.
The answer to can you use Docker with Python is that you most certainly can, and it’s not complicated. Docker allows you to bundle an image — similar to a virtual machine but more lightweight — along with whatever code you wish to ship. Hence, it’s an excellent platform for running Python processes.
This tutorial teaches you how to use Docker with Python. We’ll start with the basics and work through several examples, using docker, the command-line client for the Docker daemon (server), and docker-compose, a tool for building, combining, and networking containers together in various ways.
- Is Docker Important for Python Development
- First Steps: Installing and Configuring Docker
- Basic Docker Concepts
- Running Python Flask in a Docker Container
- Selecting a Base Docker Image for Python
- A Simple Flask Dockerfile
- Building and Running the Flask Image and Python Docker Container
- Running Django and Postgres Using Docker Compose
- A Django And Docker-Compose Starter Application
- A docker-compose.yaml file for Postgres and Django
- The Django Dockerfile and Source
- Some Django Utility Scripts for Docker
- A Simple Django Dockerfile
- Putting It All Together
Is Docker Important for Python Development
Getting started with docker-compose python is not hard. However, before getting into the how of using Docker and Docker-Compose with Python perhaps it makes sense to take a step back and think about the why.
Docker is important for Python development because it is a tool that makes development environments easy to automate on local and remote machines. It also allows the creation of containers that can run in almost any environment including all major cloud vendors and on-premise environments as well.
Moreover, the popularity of Kubernetes and the fact that it is so widely supported by different vendors means the definition of Cloud Native Computing frequently gets associated with Docker and Kubernetes, a fact that the Wikipedia entry acknowledges as well:
Not only do we have Django up and running, but we’ve run migrations and created our superuser. Let’s confirm that now by navigating to http://localhost/admin. There we can log in using our settings from secrets.txt. Here are the relevant lines from above:
Plugging the values from my own secrets file, it looks like this:
Clicking login brings me to the Django administration screen:
When you’re done working in Django or want to restart due to some changes, simply use the following command to stop the containers you have running:
More Useful Docker Commands
The commands we’ve discussed so far in this article are just a few of those that are available to you using the “ docker ” client There are several others. For a complete list, you can run the command docker on the command line. Then, given any command, you can also learn more by running “ docker —help» There is also excellent documentation online.
Again, for those commands that are deleting images/containers, please exercise caution before using them. I tend to treat all images and containers as something I can rebuild and re-obtain as needed, so when troubleshooting, I reach for a bigger hammer, but this may not be appropriate to your situation.
Closing Thoughts
As we mentioned at the start, Docker and Docker Compose add substantial capabilities to the Python developer’s toolkit. Especially when it comes to Docker Compose, the many options for networking, etc. that are available can sometimes make it a bit daunting to configure correctly, but even having not touched it for a while, I was able to stand up the stack in about a day. Because of their declarative syntax, both Docker and Compose are not hard to master. They are effective and accessible tools not only for independent projects but also for team collaboration and releasing software builds that run consistently, regardless of the platform on which they’re deployed.
Ways to set environment variables in Compose
Environment variables are dealt with by either the Compose file or the CLI. Both have multiple ways you can substitute in or set your environment variables. This is outlined below.
Tip
Don’t use environment variables to pass sensitive information, such as passwords, in to your containers. Use secrets instead.
Compose file
Substitute with an .env file
The .env file is useful if you have multiple environment variables you need to store.
Below is a simple example:
$ cat .env TAG=v1.5 $ cat docker-compose.yml services: web: image: "webapp:$TAG>"
When you run docker compose up , the web service defined in the Compose file substitutes in the image webapp:v1.5 which was set in the .env file. You can verify this with the config command, which prints your resolved application config to the terminal:
$ docker compose config services: web: image: 'webapp:v1.5'
The .env file should be placed at the root of the project directory next to your docker-compose.yml file. You can use an alternative path with one of the following methods:
For more information on formatting an environment file, see Use an environment file.
Important
Substitution from .env files is a Docker Compose CLI feature.
It is not supported by Swarm when running docker stack deploy .
Use the environment attribute
You can set environment variables in a service’s containers with the environment attribute in your Compose file. It works in the same way as docker run -e VARIABLE=VALUE .
You can choose not to set a value and pass the environment variables from your shell straight through to a service’s containers. It works in the same way as docker run -e VARIABLE . :
The value of the DEBUG variable in the container is taken from the value for the same variable in the shell in which Compose is run.
See environment attribute for more information.
Use the env_file attribute
You can pass multiple environment variables from an external file through to a service’s containers with the env_file option. This works in the same way as docker run —env-file=FILE . :
web: env_file: - web-variables.env
If multiple files are specified, they are evaluated in order and can override values set in previous files.
Note
With this option, environment variables declared in the file cannot then be referenced again separately in the Compose file or used to configure Compose.
See env_file attribute for more information.
Substitute from the shell
It’s possible to use environment variables in your shell to populate values inside a Compose file. Compose uses the variable values from the shell environment in which docker compose is run.
For example, suppose the shell contains POSTGRES_VERSION=9.3 and you supply the following configuration:
When you run docker compose up with this configuration, Compose looks for the POSTGRES_VERSION environment variable in the shell and substitutes its value in. For this example, Compose resolves the image to postgres:9.3 before running the configuration.
If an environment variable is not set, Compose substitutes with an empty string. In the example above, if POSTGRES_VERSION is not set, the value for the image option is postgres: .
Note
postgres: is not a valid image reference. Docker expects either a reference without a tag, like postgres which defaults to the latest image, or with a tag such as postgres:15 .
Important
Values set in the shell environment override those set in the .env file, the environment attribute, and the env_file attribute. For more information, see Environment variable precedence.
CLI
Substitute with —env-file
You can set default values for multiple environment variables, in an environment file and then pass the file as an argument in the CLI.
The advantage of this method is that you can store the file anywhere and name it appropriately, for example, .env.ci , .env.dev , .env.prod . This file path is relative to the current working directory where the Docker Compose command is executed. Passing the file path is done using the —env-file option:
$ docker compose --env-file ./config/.env.dev up
In the example below, there are two environment files, .env and .env.dev . Both have different values set for TAG .
$ cat .env TAG=v1.5 $ cat ./config/.env.dev TAG=v1.6 $ cat docker-compose.yml services: web: image: "webapp:$TAG>"
If the —env-file is not used in the command line, the .env file is loaded by default:
$ docker compose config services: web: image: 'webapp:v1.5'
Passing the —env-file argument overrides the default file path:
$ docker compose --env-file ./config/.env.dev config services: web: image: 'webapp:v1.6'
When an invalid file path is being passed as an —env-file argument, Compose returns an error:
$ docker compose --env-file ./doesnotexist/.env.dev config ERROR: Couldn't find env file: /home/user/./doesnotexist/.env.dev
Important
Values set in the shell environment override those set when using the —env-file argument in the CLI. For more information, see Environment variable precedence
Set environment variables with docker compose run —env
Similar to docker run —env , you can set environment variables in a one-off container with docker compose run —env or its short form docker compose run -e :
$ docker compose run -e DEBUG=1 web python console.py
You can also pass a variable from the shell by not giving it a value:
$ docker compose run -e DEBUG web python console.py
The value of the DEBUG variable in the container is taken from the value for the same variable in the shell in which Compose is run.