In the fast-paced world of software development and deployment, Docker containers have become indispensable tools for packaging, distributing, and running applications seamlessly across various environments. But have you ever wanted to create your own custom Docker container tailored to your specific needs? In this step-by-step guide, we’ll take you through the process of crafting your Docker container from scratch. Whether you’re a seasoned DevOps engineer or just starting your containerization journey, this article will empower you to build and deploy containers with confidence. Let’s dive into the world of Docker container creation and unleash the full potential of containerized applications by building your own docker container step by step.
From the command line
mkdir -p DockerExamples/Example-01 && touch DockerExamples/Example-01/Dockerfile && cd DockerExamples/Example-01Web
ok, so what do we want the image to be? Database? WebServer? In our previous articles we went through a supoerfast introduction to FastAPI, so what we can do is to create the Dockerfile file within these lines
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y python3-pip
RUN pip install --no-cache-dir fastapi uvicorn
and execute this command
docker image build . -t example-02
as you can see on the screen, quite a lot of things are happening that will not end up in having a container run. However what we can do is run the list image command
$ ~/DockerExamples/Example-01$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
example-02 latest 497a90a3c9e4 32 seconds ago 509MB
ubuntu 20.04 9873176a8ff5 3 weeks ago 72.7MB
Pretty cool but not yet what we want, since if we try to run this image what will happen is, it will start and stop immediately
$:docker run -d 497a90a3c9e4
d5230b0e6e3bed419254b472cd3852862adb4b9f1438771febac2dc952d95b17
$:~/DockerExamples/Example-01$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
We need to anchor the docker execution to a process, but also we need to execute all those steps we did in the above mentioned article but in an automated and repetitive way so that we can spin up/destroy as many times as we want without the hassle of going through all those manual steps. In reality what we will need are 3 simple things
- have the docker container running a minimal FastAPI application
- since is a container we will need to expose a port so that we can connect to
- no third thing required
How to have the docker container running a minimal FastAPI application
In the Example-01 folder just create another folder called app (mkdir app) and create a main.py file in it with this content
# app/main.py
from fastapi import FastAPI
app = FastAPI(
title="Example-02",
description="keep-4-yourself-example-02-docker",
)
@app.get("/")
def say_hello():
return {"hello": "world", "from": "docker-cotnainer"}
Change the docker file to be like this
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y python3-pip
RUN pip install --no-cache-dir fastapi uvicorn
COPY ./app /app
WORKDIR /app
CMD uvicorn main:app --host 0.0.0.0 --port 8080
Nothing extra ad exception that we are using the COPY command for binding ./app that is ~DockerExamples/Example-01/app in our filesystem to /app in the container. We then change the working directory and execute the exact same command we had in the FastAPI introduction article.
To make this image ready we have to run this command
docker build . -t example-02
We can then list the images
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
example-02 latest 6fc908545f97 4 minutes ago 509MB
ubuntu 20.04 9873176a8ff5 3 weeks ago 72.7MB
alpine 3.14 d4ff818577bc 3 weeks ago 5.6MB
the image built in the previous step is 6fc908545f97 that we can make it run using this command
docker run -d -p 8080:8080 6fc908545f97
And we can double check by browser or using curl
$ curl "http://localhost:8080"
{"hello":"world","from":"docker-cotnainer"}
Job done everything is working as expected! The only small issue I see in this is that each time we are changing the source of main.py we have to rebuild the image. In the next article I will show you how to avoid this by using the volumes that offer a nicer experience while developing big applications.
This is a really small introduction on this topic but I hope will give you a general idea of what can be achieved by using a custom Dockerfile. Of course on the docker hub there are a lot of already made recipes that can do the same job, but is good to get this knowledge since it can happen that in heavily regulated environment, the download of third party libraries, tools etc. can be a painful process if not negated from the start.
Share this content: