Lukáš Vinclav 2021-08-13 20 minutes
Starting a new project is always exciting because something new and fresh is starting but to maintain this motivation in the long term future, proper tooling has to be set up. The right selection of tools will help developers successfully react to new challenges in software developer life and keep the codebase in proper shape.
When the new project is being configured there are two crucial technologies implemented right at the beginning - Docker, and Poetry. The main reason why Docker is used is to have the same development environment across several developers using the different operating systems. With Docker, project onboarding for new developers is simplified to the bare minimum. For Poetry it is to avoid future dependency hell and have a clear list of used packages.
To complete this tutorial, the following items are required:
The main plan is to create the basic service in Docker which will be based on the Python image. In the running container, the Django application is going to be configured. As more and more settings and tools are going to be added, project settings are going to be adjusted (Dockerfile config for Django application).
In the beginning, docker-compose.yml configuration would be needed. Just for quick reference, docker-compose.yml is using to manage multiple Docker containers. At this point, docker compose will be just used to manage the Django application (we can add Postgres later).
version: "3" services: app: image: python:3 tty: true working_dir: /usr/src/app volumes: - .:/usr/src/app
The configuration above is self-explanatory. It is saying which services are going to be run (app) and specifies service attributes. In this case, only the simple Python container is going to be used without any specific functionality. Once the container is started by using docker-compose up command, it is possible to connect inside the container by running docker-compose exec app bash.
When the container is running, the same basic project setup is needed. First of all, Poetry installation and configuration must be done. When initializing the Poetry project via poetry init command, some basic questions are asked. After the initialization virtual environment is going to be created. After that, it is possible to start installing dependencies, in this case, it is going to be Django.
# Install Poetry from Pypi repository pip3 install poetry # Set up Poetry project. Some additional questions are asked. poetry init # Install new dependecy into Poetry project poetry add django
After running the commands above, the Docker container has properly configured the Poetry project with the installed virtual environment. Now it is time to set up the Django project. As a best practice, it is considered to put project files into src directory where all codebase is going to be located. In this directory run django-admin startproject project to bootstrap the new project but before this is done, it is needed to load the virtual environment which was created by Poetry. To enable this virtual environment run poetry shell.
# Our working directory cd /usr/src/app # Directory where all codebase is going to be located mkdir src cd src # Load virtual environment created by Poetry poetry shell # Start new Django project django-admin startproject project # Run the project - available on 0.0.0.0:8000 python manage.py runserver
The steps which were done till this moment manually, need to be put into Dockerfile which is specifying the build process. Developers are not expected to make such a configuration manually each time they are setting up the project but it must be done automatically.
The Dockerfile specifies all steps needed to setup the project. To start with Dockerfile only the Dockerfile file must be created in the root directory of the project on the same level as docker-compose.yml. In the general, it describes the same steps as the manual process above but with slight differences. WORKDIR is configuring the "home" directory inside the Docker container in which all upcoming actions are going to be executed.
In the build process, the Docker container does not have the access to the directory structure on the local machine via the mount points so some basic configuration files must be copied from the local machine into the container by using COPY command. In this case, the Poetry configuration files are copied and in the following actions, they are used by Poetry to set up the virtual environment.
FROM python:3 ENV PYTHONUNBUFFERED 1 WORKDIR /usr/src/app COPY poetry.lock pyproject.toml /usr/src/app/ RUN pip3 install poetry RUN poetry install
Once the Dockerfile is created, it is needed to adjust docker-compose.yml to reflect Dockerfile existence in the project. From the previous docker-compose.yml, two lines of code must be changed. By removing image parameter and replacing it with build: ., it will be communicated to use the new Dockerfile to specify the build process, and command: "poetry run python src/manage.py runserver 0.0.0.0:8000" will tell the container which command to run.
version: "3" services: app: command: "poetry run python src/manage.py runserver 0.0.0.0:8000" build: . volumes: - .:/usr/src/app ports: - "8000:8000"
After saving the new docker-compose.yml, all required changes have been made. Now by running docker-compose up, the new container is going to be built with the Django project using Poetry as the dependency management tool. After the successful build, it is possible to access the server on this URL http://0.0.0.0:8000/.