Summary
As a developer, it’s common to download tool packages that help us create projects, such as a language, a library, a framework, or a mix of all of those.
If we add Docker to this combination, we can see the importance of downloading these packages since by default a Docker container has nothing inside it, and it is through an image that we communicate to Docker the packages that we need to download and install to work. Downloading and installation can take a long time, and the problem increases if this has to be repeated a number of times.
Is there an efficient way to go through this installation time only once?
Well, a possible answer to this question is: Yes, using “Utility Containers”.
Let's start by clarifying that “Utility Container” is not an official term, so you may not find this in the Docker documentation, however, it is an interesting and effective idea when we are trying to reduce installation time. Those “Utility Containers” are also very useful if we just want to try some new technology and don't want to modify our current development environment.
A Utility Container contains all the installation files of the tools we need, and nothing else. The idea is to use this container by connecting it to our local environment to access the required resources. We can delete the utility container later or save it for the future without putting the code of our project at risk. We can even have several containers each with different tools and choose the one that best suits our current project, thus avoiding downloading the tools every time we need them.
Another possible use case is to use the image with installed tools. We may want to test how our existing project works with the update of a framework to see if something breaks, check if everything works as we expect, or simply try a new technology without the need to install anything and modify our current tools.
Now that we know what a utility container is, we're going to build one.
Requirements
To follow this post, you need to understand the basic concepts of Docker, the command line, and the FastApi framework. If you want to just follow the tutorial it’s ok, but for a better understanding of the code it would be useful if you have some experience in:
Docker:
- Images
- Volumes & Bindmount
- Dockerfile
Command line:
- Basic commands to create folders, and files and move in or out into a particular path
FastApi:
- Basic functionality
Visual Studio Code:
- Basic functionality, it’s recommended that you be able to launch VS code from the command line (you can learn how to do it here)
The first thing we're going to do is define the project, in this case, it’s going to be a simple API route with FastApi Python framework, the goal is entered to a network address that we’re going to define and see a “{"Hello":"World"}” message. We are going to follow the FastApi official documentation for containers. At the end of this tutorial, you would be able to create a Docker Utility Container with any technology tool that you want, not limited to FastApi.
The next step is to create FastApi code, so we create an app directory (“mkdir app” and then “cd app”).
Then we create an empty file __init__.py (“touch __init__.py”).
And finally, we create a main.py file (“touch main.py”) and type “code .” to fill this file with:
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
Next, we need to create a Docker file. This can be done by going to our terminal, entering our project folder with “cd ..” and typing “touch Dockerfile” to create a Docker file. With the “code .” command we can open our project folder in Visual Studio Code IDE. In the Docker file, we’re going to write the following code based on the official documentation of FastApi for Containers:
FROM python:3.9WORKDIR /code
COPY ./requirements.txt /code/rquirements.txt
RUN pip install –no-cache-dir –upgrade –r /code/requirements.txt
COPY ./app /code/app
ENTRYPOINT ["uvicorn", "app.main:app", "--host", "0.0.0.0"]
The next thing we need to do is build the image. In the terminal, inside the project folder we´re going to type the next command:
“docker build -t fastapi-util .”
We will wait until everything is downloaded and built. Now we’re going to use the “docker run” command with our new image:
“docker run –it –v DOCKERFILE_PATH:/code -p 80:80 fastapi-util --reload "
Suggestion
You can get the “DOCKERFILE_PATH” by clicking the right button on the Dockerfile on VS code and selecting the “Copy Path” option. Now paste it into the terminal. Remember to erase the “/Dockerfile” final part, since we want to bind mount a folder, not a file.
Notice that we’re using:
“–it” flag, to enable interactivity so that we can enter commands inside from the container.
“-v” flag, this is a bind mount, and we won't be focusing on this concept. However, we need to know that this flag allows us to mirror everything that happens inside the container to our local folder.
“-p 80:80”, this flag declares the ports that we will use. The 80 on the left is the port number on the local host machine, and the 80 on the right is the port number of the Docker container that we want to publish.
“fastapi-util”, tells Docker that we want to use the fastapi-util image that we previously built on this container.
“--reload”, finally, this flag tells FastApi to enable hot reload in this container, so that means we can modify the code inside “main.py” and it would immediately reflect on the network address that FastApi specifies on the terminal output (http://0.0.0.0:80).
That’s it, we have successfully built a docker util container that has all the FastApi tools packages inside, we can use FastApi commands like “-reload” using the container and avoid the installation of all the FastApi stuff in our local environment.
You might think that this utility container stuff is a lot of effort for only the FastApi package tool, but for a more complex project, you can see the advantage of utility containers because they save us a lot of space and time.
Sources
- Docker & Kubernetes: The Practical Guide [2023 Edition] by Maximilian Schwarzmüller
- https://youtu.be/Nb9YrksS_Dk by Lloyd
- https://fastapi.tiangolo.com/deployment/docker/ by Fast Api
About Encora
Fast-growing tech companies partner with Encora to outsource product development and drive growth. Contact us to learn more about our software engineering capabilities.