Setting Up a Great Python Dev Environment with Docker
Tags: python, docker, fastapi
Published: 2023-03-11 06:15:00

Are you tired of having to set up your Python development environment every time you start a new project? Docker can help you out! In this post, I will guide you through the process of setting up a Python development environment using Docker, starting with cloning a git repo.

## Prerequisites

To be able to follow along, make sure you are using VS Code and you have Git installed.

## Cloning the git repo

To get started, clone the git repo for your project. In this case, I am working on [q-lipa’s API](https://github.com/Njoguu/qlipa-API). You can do this by running the following command in your terminal:
`git clone https://github.com/Njoguu/qlipa-API.git`

![Cloning a repo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8oiqrlhrlrakmndxagbe.png)

## Setting Up the Environment

First, make sure that you have installed Docker on your machine. Installation instructions can be found on the Docker [website](https://www.docker.com/). I already have it installed.

![Checking if docker is installed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wdzyp1x3wwg9fenxky8o.png)

Next, navigate to the directory and create a new file called "requirements.txt" to house all the dependencies required for your app. Additionally, create a directory called "src" where the Python files will be stored.

<video 
 src="https://drive.google.com/uc?id=1WScrANefOs85_6BiehbOM4rrgwmePAhL" controls>
</video>

Create a sample main.py file that will act as a ‘placeholder’ for the app. You can get the code from [FastAPI's Tutorial-Guide](https://fastapi.tiangolo.com/tutorial/first-steps/).  

<video 
 src="https://drive.google.com/uc?id=155cuUPlGGhd5ROSNeiMG8ISQKvUFMzir" controls>
</video>

To use Docker with your project, first create a file named “Dockerfile” in the root directory of the project. Dockerfile typically contains instructions for installing dependencies, copying files into the image, and configuring the environment. Once the Dockerfile is created, it can be used to build a Docker image, which can then be used to run containers with the application inside.

Next, add the necessary packages for your Dockerfile, at the time this includes Uvicorn and FastAPI, to the requirements.txt file. Once this is done, you can build your Docker image by adding the following code to the Dockerfile.

```
# Use the latest Python Version as the base image
FROM python:3.12.0a6-slim-buster

# Setup the working directory for the container
WORKDIR /code

# Copy the requirements file to the container
COPY ./requirements.txt ./

# Install the Python dependencies using Python 
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application code to the container
COPY ./ ./

# Setup the command to run when the container starts
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
```

<video 
 src="https://drive.google.com/uc?id=1knJ19A1oG6uIhyxhQxnYG57VQVKQIMWI" controls>
</video>

### Building the Docker image

Navigate to the repo directory and build the Docker image by running the following command in your terminal:

`docker build -t <your-image-name> .
`

This will build the Docker image for your Python development environment.

<video 
 src="https://drive.google.com/uc?id=1OdZDxw_g6KXcJzxzrhlWItI8KwL8qmeb" controls>
</video>

### Running the Docker container

Now that the Docker image has been built, you can run the Docker container and start working on your Python project. 

Run the following command in your terminal:
`docker run -d -p 8000:8000 <your-image-name>
`

This command starts the Docker container, maps port 8000 on your local machine to port 8000 in the container, and runs the app.

<video 
 src="https://drive.google.com/uc?id=1Q_pMyoBXNbFz4W-qZ4vNXZ3YmrOI79oh" controls>
</video>

### Registering File changes - Using Docker Volumes

This all looks great, but there is a problem. When you change something in the code and refresh the app in the browser, you don’t get the new code/the new changes. This is because the code is in your local machine but the app itself is running inside the container.

<video 
 src="https://drive.google.com/uc?id=12xL6zs1wBLVENvgIgrMqdUzzxkhJBRLJ" controls>
</video>

To make the changes and make the app register those changes automatically, we use volumes. 
SEE 👉 [What is a volume?](https://docs.docker.com/storage/volumes/)

You can do this by making a few changes to what you use to run the docker image. instead use the following code:

`docker run -d -p 8000:8000 -v $(pwd):/code <your-image-name>`

This code launches a container and maps port 8000 on your local machine to port 8000 in the container. It also mounts the current working directory on  the host machine to the `code` directory in the container.

**Important Note**: You may run into an error that typically occurs when you are trying to run a Docker command with a repository name that includes uppercase letters. (I’ve right now just learnt Docker repository names must all be lowercase). I found a [fix on StackOverflow](https://stackoverflow.com/questions/48522615/docker-error-invalid-reference-format-repository-name-must-be-lowercase).

If you run into the error, use this code:
 
`docker run -d -p 8000:8000 -v "$(pwd):/code" <your-image-name>`

<video 
 src="https://drive.google.com/uc?id=1ZRkQ2dJ7DaIu9xbg8qZxirffEDlIm7EK" controls>
</video>

When you run the app successfully, and make changes to the code, the app will automatically register the changes, and they will be displayed.

### Using an IDE in a Docker Container

There is still a problem though. We can’t really code inside the IDE as the IDE does not recognize the dependencies of the app. If you remember, we did not install the dependencies on the local machine, but inside the container. What we actually want is to have this IDE inside the Docker Container.

To achieve this, you need two VS Code extensions, **Docker** extension and the **Dev Containers** extension. Install these two, and then on the bottom left, you should see a little button that when you hover, it says “Open a Remote Window”. Click on it.

As you will see from the options, there are different ways in which you can connect to a remote container. But in our case, since we have an existing container that is already running in the background, click on “Attach to Running Container” and select the container for the project you are working on.

This will open up a new instance of VS Code and this lives inside the Docker Container which we created.

Since this is a whole new environment, you will have to install all necessary extensions again for you to use in your project. In this case, I install the Python extension.

<video 
 src="https://drive.google.com/uc?id=1ypV0twbn3hQWM9YcgJ8aqh448S4Ta2Az" controls>
</video>

We can now code!


## Conclusion

In this post, I have shown you how to set up a great Python development environment using Docker. By cloning a git repo, building a Docker image, and running the Docker container, using Docker Volumes, using an IDE inside a Docker Container.

You can easily set up a consistent Python development environment that can be used across projects. Happy coding!

**_This project will later require multiple containers though, this is where Docker Compose comes in. It is a tool for defining and running multi-container applications. Stay tuned to learn how to set it up!_**