How to Create a Dockerfile and Docker Compose for Flask Application with PostgreSQL Database
By khoanc, at: Nov. 20, 2024, 9:25 a.m.
How to Create a Dockerfile and Docker Compose for Flask Application with PostgreSQL Database
In our previous post, "Create a Dockerfile for Flask Application", we explored containerizing a Flask application with Docker.
In this post, we will integrate a PostgreSQL database with SQLAlchemy and show how to containerize both the Flask application and the database using Docker and Docker Compose. For this tutorial, we’ll use python:3.10-slim
as the base image as this is lightweight.
Step 1: The Dockerfile for Flask
Here’s the updated Dockerfile
:
# Use an official Python runtime as the base image
FROM python:3.10-slim
# Set the working directory in the container
WORKDIR /app
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the application code into the container
COPY . .
# Expose the application port
EXPOSE 5000
# Command to start the Flask app
CMD ["python", "app.py"]
Step 2: Docker Compose Configuration
The updated docker-compose.yml
file for managing both Flask and PostgreSQL:
version: '3.8'
services:
web:
build:
context: .
container_name: flask_app
ports:
- "5000:5000"
volumes:
- .:/app
environment:
- SQLALCHEMY_DATABASE_URI=postgresql://glinteco:glinteco@db:5432/glinteco
depends_on:
- db
db:
image: postgres:13
container_name: postgres_db
environment:
POSTGRES_USER: glinteco
POSTGRES_PASSWORD: glinteco
POSTGRES_DB: glinteco
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Step 3: Update Flask Application for SQLAlchemy
Here’s an example Flask application (app.py
) configured to use the PostgreSQL database:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# Database configuration
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://glinteco:glinteco@db:5432/glinteco'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# Define a simple model
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
@app.route('/')
def index():
return "Hello, Flask with PostgreSQL!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Step 4: Build and Run the Containers
Build the Docker Image:
docker-compose build
Start the Containers:
docker-compose up
docker-compose up -d # Run as a daemon
Verify the Setup:
Access the Flask application at http://localhost:5000
.
PostgreSQL will be running on localhost:5432
with the username, password, and database name as glinteco
.
Key Benefits of This Setup
- Unified Development Environment: Flask and PostgreSQL run seamlessly in containers, ensuring consistency.
- Customizable Database Settings: Username, password, and database name can be easily updated in the configuration.
- Simplified Integration: SQLAlchemy provides a clean and efficient way to interact with the database.
Common Docker errors and how to fix
Error: "Cannot connect to the Docker daemon"
This occurs when the Docker daemon is not running or the user lacks permission to access it. To resolve this, ensure the Docker daemon is running with the command sudo systemctl start docker
. You can also add your user to the Docker group using sudo usermod -aG docker $USER
to avoid using sudo
for every command. Afterward, restart your system or log out and back in to apply the group changes.
Error: "Image not found"
This happens when the specified Docker image doesn’t exist locally or in the Docker Hub repository. To fix this, double-check the image name and version, then pull it with docker pull < image_name >:< tag >
. If you're unsure of the image name, use docker search < image_name >
to find the correct one.
Error: "Port already in use"
If a container or another application is already using the specified port, use the command sudo lsof -i :< port >
to identify the conflicting process. You can either stop that process or specify a different port in your Docker run command or docker-compose.yml
.
Error: "Permission denied" when accessing files
This error arises when the container lacks permission to access files or directories on the host. Ensure the correct permissions with chmod 777 < file_or_directory >
. On systems with SELinux, use the :z
or :Z
options when mounting volumes to allow proper access, such as volumes: - /host/path:/container/path:Z
.
Error: "Container exited with code 1"
This error indicates that the application inside the container encountered an issue and exited. Check the container logs for details using docker logs <container_name></container_name>
. Review the application configuration, dependencies, or the entry point to resolve the issue.
Error: "Out of memory" or "Cannot allocate memory"
Docker or the host system may lack sufficient memory. Limit container memory usage in docker-compose.yml
using mem_limit: 512m
. Alternatively, free up system memory or add swap space to the host system.
Error: "Mounts denied: path outside of the allowed directories" on Mac or Windows
Docker Desktop restricts access to certain directories. To fix this, add the directory to the shared folders list in Docker Desktop settings or use directories within the allowed paths, such as those inside your user directory.
Error: "No space left on device"
This occurs when Docker consumes all available disk space. Remove unused images, containers, and volumes with docker system prune -a
. You can also check for large Docker files using docker system df
and clean them up accordingly.
Error: "Network not found"
This happens when the specified Docker network does not exist. List existing networks using docker network ls
, and if needed, create the network with docker network create < network_name >
.
Error: "Conflict: Unable to remove volume"
A volume may still be in use by a container. To fix this, stop and remove the container using the volume with docker stop <container_name></container_name>
and docker rm < container_name >
. Then remove the volume with docker volume rm <volume_name></volume_name>
.
Error: "Build failed: Invalid reference format"
This error occurs if the image name or tag in the Dockerfile or command is invalid. Ensure the format follows <repository>/:<tag></tag></repository>
and avoid special characters or spaces.
Error: "Docker Compose version mismatch"
This happens when the Docker Compose file version is incompatible with the installed Compose version. Check your Docker Compose version using docker-compose --version
, and either use a compatible version in your docker-compose.yml
file or update Docker Compose to a newer version.
Conclusion
By following this guide, you can containerize a Flask application with a PostgreSQL database using Docker and Docker Compose. This setup ensures a scalable and consistent environment for development and deployment. If you haven’t already, revisit our original post for a deeper understanding of Dockerizing Flask applications.