HOME / BLOG / Docker Django
Docker Django
over 1 year
2023 04
How to Dockerize your Django Project with PostgreSQL
In this tutorial I will provide some examples on how to dockerize your Django application.
We will also setup a PortgreSQL database, running on it's container.
First you need to create your project folder and change directory to the project root.
I recommend you create the following files:
We will also setup a PortgreSQL database, running on it's container.
First you need to create your project folder and change directory to the project root.
I recommend you create the following files:
touch .gitignore README.md .env .env.example
Now let's create the requirements.txt for our python backend & add the following content to the file:
Django>=4.0 psycopg2>=2.8
This will make the installation easier. And it's standard for python projects to list your dependencies on the requirements.txt.
Now let's create the Dockerfile which will hold our image recipe to create our Django container.
# syntax=docker/dockerfile:1 FROM python:3 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 WORKDIR /code COPY requirements.txt /code/ RUN pip install -r requirements.txt COPY . /code/
This Dockerfile example was taken from 'https://github.com/docker/awesome-compose/tree/master/official-documentation-samples/django/'
Now we can create the docker-compose.yml
services: db: image: postgres container_name: postgresql-docker restart: on-failure networks: - database-network volumes: - ./postgres_data:/var/lib/postgresql/data ports: - ${POSTGRES_HOST_PORT}:${POSTGRES_HOST_PORT} environment: - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} backend: build: . container_name: django-docker restart: on-failure networks: - database-network command: python manage.py runserver 0.0.0.0:${BACKEND_PORT} volumes: - .:/code ports: - ${BACKEND_PORT}:${BACKEND_PORT} environment: - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_HOST_PORT=${POSTGRES_HOST_PORT} depends_on: - db networks: database-network: driver: bridge
We have defined two containers db & backend, this names should be allusive to what the container means to the developer and those names seam to fit.
The db will use the standard postgres image, but you can specify any version you want like this:
The db will use the standard postgres image, but you can specify any version you want like this:
image: postgres:15.1
The container-name is just for meta-data so it's not a random name, we also want to restart on failure, and we will need containers to talk to the DataBase, so we create an internal network database-network.
We also want the DataBase to be persistent so we will set up a volume for it.
Since the volume will setup the postgres_data in the same folder I will add this to the .gitignore so it's not pushed to my repo.
Also you should include .env in the .gitignore
The .env should contain all the variables that you used for the docker-compose.yml
And .env.example is a template to show people how they should set up the .env
Now we are ready to start the Django project.
And .env.example is a template to show people how they should set up the .env
Now we are ready to start the Django project.
sudo docker compose run backend django-admin startproject portfolio42 .
If you are on linux, you might need to change the ownership of manage.py in order to start using the script.
sudo chown -R $USER:$USER composeexample manage.py
Now you have to set-up the PostgreSQL database for the Django project.
Go to <django_project>/settings.py and change the following:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('POSTGRES_DB'),
'USER': os.environ.get('POSTGRES_USER'),
'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
'HOST': 'postgresql-docker',
'PORT': os.environ.get('POSTGRES_HOST_PORT'),
}
}
Now you can run:
docker compose up
And go to the localhost:<BACKEND_PORT>
At this point you are good to go, just start developing your application.
I decided to add a local workflow CI testing integrated with Github.
This will help developers run the test suite every time they do a Pull Request, and this way they can see if their code is passing or not.
Just create a the folder:
I decided to add a local workflow CI testing integrated with Github.
This will help developers run the test suite every time they do a Pull Request, and this way they can see if their code is passing or not.
Just create a the folder:
mkdir -p .github/workflows
Now create a file:
touch .github/workflows/django.yml
In that file put the following code:
name: Django CI on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: # runs-on: ubuntu-latest runs-on: self-hosted strategy: max-parallel: 4 matrix: python-version: [3.8] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install Dependencies run: | python3 -m pip install --upgrade pip pip install -r requirements.txt - name: Run Tests run: | python3 manage.py test --settings=portfolio42.unittest_settings
In this case I placed:
runs-on: self-hosted
Because I host my own server to test, but you can also out an ubuntu machine which github provides. But that will be slower.
What If I want to use React?
I will set up a React app for the front end, so my django application will actually only serve as an API.
In this case we want to divide the project in two: backend & frontend.
In this case we want to divide the project in two: backend & frontend.
npx create-react-app frontend mkdir backend mv requirements.txt manage.py Dockerfile <your_django_project> backend/
That way the root looks something like this:
Now we should change the docker-compose a little, because our container image change location:
services: db: image: postgres container_name: postgresql-docker restart: on-failure networks: - database-network volumes: - ./postgres_data:/var/lib/postgresql/data ports: - ${POSTGRES_HOST_PORT}:${POSTGRES_HOST_PORT} environment: - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} backend: build: backend/. container_name: django-docker restart: on-failure networks: - database-network command: python backend/manage.py runserver 0.0.0.0:${BACKEND_PORT} volumes: - .:/code ports: - ${BACKEND_PORT}:${BACKEND_PORT} environment: - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_HOST_PORT=${POSTGRES_HOST_PORT} depends_on: - db networks: database-network: driver: bridge
Your django.yml for CI should also change:
name: Django CI on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: # runs-on: ubuntu-latest runs-on: self-hosted strategy: max-parallel: 4 matrix: python-version: [3.8] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install Dependencies run: | cd backend python3 -m pip install --upgrade pip pip install -r requirements.txt - name: Run Tests run: | cd backend python3 manage.py test --settings=portfolio42.unittest_settings
Now you should be able to run the project with their respective docker containers, also in the future you might want to add another container for the REACT, this could be for the production hosting of the files, or just to run a node server for the react development.
I hope you enjoyed this tutorial, good luck Dockerizing your applications!