How to set up a Django Project with Docker and Poetry

Ridwan Yusuf
AWS Tip
Published in
5 min readJun 18, 2023

--

Hi friends and welcome to another edition in this tutorial series.

In the previous post, we discussed how to efficiently manage Python project package requirements using Poetry. If you haven’t checked it out yet, feel free to do so as it covers some fundamental concepts.

This guide will provide an overview of using Poetry in a Dockerized Django application.

The starter project can be found in a separate branch called ‘starter’ within the GitHub repository. The completed project can be found here

Feel free to clone the starter project and follow along.

Here is the structure of starter project:

├── blog
├── core
├── docker
├── docker-compose.dev.yml
├── manage.py
├── pytest.ini
├── README.md
└── requirements.txt

The blog folder contains a sample API that implements CRUD functionality for managing blog posts.

blog
├── admin.py
├── apps.py
├── __init__.py
├── migrations
├── models.py
├── serializers.py
├── tests
├── urls.py
└── views.py

The core folder houses the settings and configuration files for the project.

core
├── asgi.py
├── db.sqlite3
├── __init__.py
├── settings
├── urls.py
└── wsgi.py

The docker directory contains the Dockerfile used in development mode:

docker
└── dev
├── Dockerfile
└── entrypoint.sh

To get started, navigate to the project directory and run the command poetry init to initialize the existing project.

poetry init creates pyproject.toml file. Make sure to provide the necessary information as requested.

This screenshot displays a sample interactive prompt.

poetry init

Since we are working on an existing project, there is no need to create a new project from scratch. However, if you do need to start a project from scratch, you can use the command poetry run django-admin startproject project-name to create a new project.

The poetry run command is used to execute the given command within the project's virtual environment.

Additionally, you can use the command poetry add <package_name> to install new packages into the project.

This command allows you to specify the name of the package you want to install, and Poetry will handle the installation process, including managing the package’s dependencies and updating the project’s pyproject.toml file to reflect the newly added package.

In our case, since we already have a requirements.txt file that contains all the necessary packages for the simple blog API application to run, we can use Poetry to install these packages.

poetry add `cat requirements.txt`

The content of pyproject.toml file is automatically updated to include the installed packages

[tool.poetry.dependencies]
python = "^3.10"
django = "4.0.6"
djangorestframework = "3.13.1"
django-cors-headers = "3.13.0"
drf-spectacular = "0.22.1"
python-decouple = "3.6"
pytest-django = "4.5.2"
pytest-factoryboy = "2.5.0"

The pyproject.toml file also includes a section called [tool.poetry] that contains metadata about the project.

[tool.poetry]
name = "django-docker-poetry"
version = "0.1.0"
description = ""
authors = ["ridwanray <alabarise@gmail.com>"]
readme = "README.md"
packages = [{include = "django_docker_poetry"}]

In our case, we need to exclude the packages section since the django_docker_poetry directory is not an actual package.

Updated content:

[tool.poetry]
name = "django-docker-poetry"
version = "0.1.0"
description = ""
authors = ["ridwanray <alabarise@gmail.com>"]
readme = "README.md"

Docker file

The Dockerfile used in the projects is put in a directory called docker.

Here is the folder structure:

├── blog
├── core
├── docker
├── docker-compose.dev.yml
├── .env
├── .env.example
├── .gitignore
├── manage.py
├── poetry.lock
├── pyproject.toml
├── pytest.ini
├── README.md
└── requirements.txt
docker
└── dev
├── Dockerfile
└── entrypoint.sh

Dockerfile

# Pull official base image 
FROM python:3.10-slim

# Set working directory
WORKDIR /app

# Set env variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt-get update \
&& apt-get install -y gcc python3-dev musl-dev libmagic1 libffi-dev netcat-traditional \
build-essential libpq-dev

COPY poetry.lock pyproject.toml /app

RUN pip3 install poetry
#RUN poetry config virtualenvs.create false
# Install dependencies
RUN poetry install

# Copy entrypoint.sh
COPY ./docker/dev/entrypoint.sh /entrypoint.sh

RUN chmod +x /entrypoint.sh

COPY . /app/

ENTRYPOINT [ "/entrypoint.sh" ]

The provided Dockerfile sets the working directory, installs system dependencies, copies the poetry.lock and pyproject.toml files into the /app directory, installs Poetry, installs the project dependencies using poetry install.

docker-compose.dev.yml

version: '3.9'

services:
api: &api
build:
context: .
dockerfile: docker/dev/Dockerfile
image: ray-blog-api
command: poetry run python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- '8000:8000'
env_file:
- ./.env
restart: unless-stopped

The docker compose file uses the command poetry run python manage.py runserver 0.0.0.0:8000 inside the container to start the development server.

Also, remember to include the contents of the .env file as follows:

DEBUG=1
SECRET_KEY=secret
ENVIRONMENT=dev

Next, you can build the image and start the container using the following command:

docker-compose -f docker-compose.dev.yml up --build

Access the documentation on http://0.0.0.0:8000/api/v1/doc/

Automated tests

To run automated tests, use the following command:

docker exec -it <container_name> poetry run pytest
Automated tests

The complete source code for this project can be found here.

Thanks for reading up to this point, and I hope you enjoyed it. Also, please enable the notification icon to receive updates when a new guide is published.

Ready to elevate 🚀 your Python 🐍 skills? Check out YouTube for exclusive content. Don’t forget to subscribe to the channel to stay updated with future releases.

Linkedin : link

--

--