Environment variables play a critical role in web services, enabling secure management of sensitive data, configuration settings, and API keys. While developers in the Node.js ecosystem have long adopted best practices for handling environment variables, these same techniques can be easily applied to Python web services. By properly managing environment variables, you ensure that your application stays secure, flexible, and easily configurable across different environments. In this post, I will guide you through managing environment variables in Python, utilizing .env files and the python-dotenv package. I’ll show you how to integrate these practices into your local development with Docker, as well as in production environments via CI/CD pipelines. This method ensures sensitive information never makes it to your codebase, and configuration is streamlined for all stages of development. Let’s explore how to manage environment variables effectively in Python web services!
Using .env Files for Environment Variables
A common approach for managing environment variables is to use a .env file, which stores key-value pairs for variables you want to manage. This file can include things like database credentials, API keys, and other sensitive information. However, it is essential to make sure that the .env file is excluded from version control to avoid accidentally committing sensitive data.
First, create a .env file in your project root to store environment variables. For example:
DATABASE_URL=postgres://username:password@localhost:5432/mydatabase SECRET_KEY=mysecretkey LOG_LEVEL=DEBUG
To ensure the .env file is not tracked by Git, add it to your .gitignore file:
.env
While the .env file should be kept private, it’s a good practice to include a .env.example file in your repository. This file should contain all the necessary variable names without sensitive data, so others know what variables to define in their own .env file. Here’s what a .env.example file might look like:
DATABASE_URL= SECRET_KEY= LOG_LEVEL=DEBUG
This file can be pushed to GitHub so that anyone cloning the repository will know which variables need to be set in their own .env file.
Using the python-dotenv Package
The python-dotenv package makes it easy to load environment variables from a .env file into your application. To install it, run the following:
pip install python-dotenv
Next, you need to load the environment variables at the start of your application. This is typically done in the main initialization file or the entry point of your web service.
from dotenv import load_dotenv load_dotenv()
This will load all the variables defined in your .env file into the environment, where you can access them using Python’s os.environ.
Accessing Environment Variables
Once loaded, you can access environment variables like this:
import os database_url = os.getenv('DATABASE_URL') secret_key = os.getenv('SECRET_KEY') log_level = os.getenv('LOG_LEVEL', 'INFO') print(f"Connecting to database at {database_url}") print(f"Log level is {log_level}")
Using Docker with .env Files
When running your Python service in Docker locally, it’s important to ensure that your .env file is available inside the Docker container. You can achieve this by mounting the .env file into the container. Here’s an example of how to run your Docker container and mount the .env file:
echo "BUILDING DOCKER IMAGE" docker build -t my-service . if [ $? -eq 0 ]; then echo "RUNNING DOCKER IMAGE" docker run -p 5000:5000 -v $(pwd)/.env:/app/.env my-service:latest else echo "Docker build failed. Exiting." exit 1 fi
This command binds the .env file from your local project directory to the /app/.env path inside the Docker container, ensuring that your environment variables are accessible.
Environment Variables in Production
In a production environment, especially when using services like GitHub Actions or GitLab CI/CD, environment variables can be injected directly into the Docker container without the need for an .env file. Those variables can be retrieved from environment variables of your repository in GitHub or GitLab or Vault.
When building the Docker image, you can inject environment variables directly using the -e flag:
docker build -e DATABASE_URL=your-database-url -e SECRET_KEY=your-secret-key -t my-service:latest .
This approach ensures that your production configuration is securely injected into the container, without needing to include sensitive data in the .env file.
Conclusion
Effective variable management is a cornerstone of building secure, maintainable, and flexible Python web services. By adopting best practices from environments like Node.js, Python developers can ensure their applications handle sensitive data securely and configurations are easily managed across different environments.
In this post, we explored how to use .env files, the python-dotenv package, and Docker to manage variables in a Python web service. Whether you’re working locally or deploying to development or production, these practices ensure that your application’s configuration stays clean and secure. Remember, the goal is to never hard-code sensitive information or configuration directly into your codebase, and instead, rely on environment variables for easy configuration management.
By following these techniques, you’ll improve both the security and maintainability of your Python web services, ultimately enabling a smoother development experience. With a solid foundation in variable management, your application will be ready to scale efficiently across different stages of deployment.
Happy coding!
Support this blog if you do like!