Dockerfile
Goal
This project is about the Dockerfile and the creation of your own images. You will:
- create your own Dockerfile for a service
- add a second service to the Dockerfile and connect the services
Tools
- Try to complete the tasks below with the help of the slides and the cheatsheets.
- If you have any problems with this, you will find a fold-out block for each task in which the solution is described.
Task 1 - Create a first Dockerfile
- Create a new subfolder
my-first-image
of the workspace folder/home/coder/workspace
. - Create a
Dockerfile
in the folder with the following properties:- Baseimage:
ubuntu:20.04
- Entrypoint:
["/bin/echo", "Hello"]
- Command:
["world"]
- Baseimage:
Solution (click on the arrow if you get stuck)
- Open the explorer of VSCode with
Ctrl + B
or alternatively by clicking on the file icon (above the magnifying glass) in the left bar. - Create a new folder with the name
my-first-image
via the Explorer. - Create a file in the folder with the name
Dockerfile
. - Add the following content to the file:
FROM ubuntu:20.04 ENTRYPOINT ["/bin/echo", "Hello"] CMD ["world"]
Task 2 - Building a first image
2.1: Building an image
In the terminal, build an image with the name demo01
from the Dockerfile
.
Solution (click on the arrow if you get stuck)
- Open a terminal (Menu > Terminal > New Terminal).
- Change to the created folder with
cd my-first-image
.cd
stands for stands forChange Directory
. - Execute
pwd
.pwd
returns the current directory. You should get the output/home/coder/workspace/my-first-image
. - If you do not receive the output, change to the directory with
cd /home/coder/workspace/my-first-image
. - Now build the image with:
docker build -t demo01 .
- You should see an output after the finished build that looks similar to the following:
Step 3/3 : CMD ["world"] ---> Running in fdef47b21535 Removing intermediate container fdef47b21535 ---> 6296257370ba Successfully built 6296257370ba Successfully tagged demo01:latest
2.2: Starting the image
Start the image in the foreground (without -d
). It should display "Hello world".
Solution (click on the arrow if you get stuck)
- Start the image with the following command:
docker run demo01
2.3: Starting the image with arguments
Start the image so that it outputs "Hello <name>", where <name>
should be your name.
Solution (click on the arrow if you get stuck)
- Start the image with the following command:
docker run demo01 <name>
Task 3 - Preparation of a small web app
3.1: Create app.py
Create a file app.py
with the following content in the folder /home/coder/workspace/my-first-image
:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Web App with Python Flask!'
app.run(host='0.0.0.0', port=80)
This Python file defines and starts a small Flask web application. The application is accessible via port 80.
3.2: Create requirements.txt
Create a requirements.txt
file with the following content in the /home/coder/workspace/my-first-image
folder:
Flask>2<3
Your folder should now look like this:
├── app.py
├── Dockerfile
└── requirements.txt
0 directories, 3 files
Task 4 - Extend Dockerfile for the web app
4.1: Install Python
Install the packages python3
and python3-pip
with the help of apt-get
.
Solution (click on the arrow if you get stuck)
- Your Dockerfile should now look like this:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ && rm -rf /var/lib/apt/lists/*
First, the package manager is updated to the latest version. The packages should then be installed. This part of the command is essential. The update and rm commands are best practice and are discussed in more detail in the following chapter. The -y option specifies that yes
is automatically answered to the installation question. Finally, we should delete the package cache to keep the image small.
4.2: Install dependencies
- Expand your Dockerfile so that the
requirements.txt
file is copied to the image in the/app
folder. Use theWORKDIR
command to switch to the /app context. - Install the dependencies with the following command:
python3 -m pip install -r requirements.txt
Solution (click on the arrow if you get stuck)
- Ihr Dockerfile sollte nun wie folgt oder ähnlich aussehen:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN python3 -m pip install -r requirements.txt
4.3: Integrate and start webapp
- Copy the file
app.py
into the image. - Document port 80 as access to the application.
- Execute
python3 app.py
when starting the image.
Solution (click on the arrow if you get stuck)
- Your Dockerfile should now look like this:
FROM ubuntu:20.04 RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN python3 -m pip install -r requirements.txt COPY app.py . EXPOSE 80 CMD ["python3", "app.py"]
4.4: Building and testing the image
- Build the image with the new Dockerfile.
- Start the image with port forwarding so that you can access the web app via reach the web app via the browser.
Solution (click on the arrow if you get stuck)
- Execute the following command to build:
docker build -t demo01 .
- Start the image as follows:
docker run -p 8080:80 demo01
- Try to open the webapp in a new tab under
http://code-0.labs.corewire.de:8080/
. - Important:
http
nothttps
- Replace
code-0
with your instance.
- If successful, you can switch back to the VSCode instance and close the container with
Ctrl+c
.
Task 5 - Change user in container
5.1: Create non-root user
For security reasons, we now want to run the web app in the container with a user with a user who does not have root rights. To do this, we need to create a user. This can be done with the following command:
groupadd --system --gid 10100 app-runner-group \
&& useradd --system --gid 10100 --uid 10100 app-runner-user
Solution (click on the arrow if you get stuck)
- Your Dockerfile should now look like this:
[...] RUN python3 -m pip install -r requirements.txt RUN groupadd --system --gid 10100 app-runner-group \ && useradd --system --gid 10100 --uid 10100 app-runner-user COPY app.py . [...]
5.2: Using non-root users
Now make sure that the webapp is executed with the created user app-runner-user
.
is executed.
Solution (click on the arrow if you get stuck)
- Your Dockerfile should now look like this:
[...] RUN groupadd --system --gid 10100 app-runner-group \ && useradd --system --gid 10100 --uid 10100 app-runner-user USER app-runner-user COPY app.py . [...]
5.3: Building and testing the image
- Build the image with the new Dockerfile.
- Start the image with port forwarding so that you can access the web app via the browser.
Solution (click on the arrow if you get stuck)
- Execute the following command to build:
docker build -t demo01 .
- Start the image as follows:
docker run -p 8080:80 demo01
- Try to open the webapp in a new tab under
http://code-0.labs.corewire.de:8080/
. - Important:
http
nothttps
- Replace
code-0
with your instance.
- If successful, you can switch back to the VSCode instance and close the container with
Ctrl+C
to close the container.
Privileged ports (ports < 1024) without root rights
Since Docker 20.10.0 (Release: 08.12.2020, Release notes) containers can also use ports < 1024 without requiring root rights.
An alternative solution for older versions to run the container without root rights
would be to replace port 80 in the app.py
with, for example, port 8080
in app.py
and adjust the port forwarding for docker run
accordingly.
You have now successfully containerized an existing application. You have defined everything necessary in the Dockerfile for the application to fulfill its purpose without errors.