Docker Tutorial Part 1: Application Deployment with Docker
This document will cover how to deploy an application using docker. We will then discuss how to push and pull docker images from docker registries to quickly deploy your application to servers.
For the sake of simplicity we will be using a default Flask slice automatically built from the Syminet Cloud Marketplace as our application.
The majority of this tutorial was distilled from the instructions from here: The Flask Mega-Tutorial, Part XIX: Deployment on Docker Containers ↗
Create a Flask Slice
In the Syminet Cloud Panel, click Create -> Slice
Click the Marketplace tab.
Click Flask
Proceed to create as normal.
Note
Marketplace installs can take a few minutes longer than regular builda. You will know the install is complete when the login message from SSH gives you details about the flask install and how to access it.
Disable nginx
When your application is run via docker, it will bind to port 80 and conflict with the nginx process running natively. Run the following commands to disable it:
systemctl stop nginx; systemctl disable nginx
Install docker
There are two methods for installing docker engine:
Method 1: Debian Official Packages
Note
The next tutorial after this, Docker Tutorial Part 2: Orchestration with Kamal wil not work with this method. If you plan to proceed through to that tutorial, you will need to install directly from docker using Method 2: Directly From Docker below.
The quickest way is to install from debian packages with a single command:
apt install docker.io
The above will work fine with this tutorial. However, if you want to use orchestration tools like kamal, this will not work. You will need to install directly from Docker.
Method 2: Directly From Docker
If you plan to use newer tools and/or orchestration such as Kamal, you will want to install from docker directly. The following is from the Docker engine install pages.
You can run the commands below in turn, or paste this into a file to make a script:
#!/bin/bash
#
# Install docker
#
# Add Docker's official GPG key:
apt-get update
apt-get install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
If pasted into a file, chmod +x <filename> and run it.
Once complete, make sure docker is running:
docker version
The above command should output the version information and additional details. If you get an error message, try above installation command again.
Build a Docker Image of your Application
Navigate to the directory containing your flask application:
cd /home/flask_app
Create a Dockerfile in your application directory.
Note
The filename is case sensitive: be sure to use a capital ‘D’: Dockerfile
Dockerfile should contain the following:
FROM debian:bookworm
RUN apt update
RUN apt -y install apt-utils
RUN apt -y install gunicorn
RUN apt -y install python3-gunicorn python3-flask python3-markupsafe python3-flaskext.wtf;
COPY deploy deploy
COPY flaskr flaskr
COPY starticorn ./
RUN chmod a+x starticorn
EXPOSE 80
ENTRYPOINT ["./starticorn"]
Build the image:
docker build -t flaskr:latest .
Note
The dot at the end of the command is important, meaning “this directory”. You can run this command any time to rebuild your image.
Run your new image in a container
You should be able to run your image right now locally:
docker run --name flaskr -d -p 80:80 flaskr:latest --rm flaskr:latest
The above command runs your application and assigns it the –name “flaskr”. The -d switch means daemonize (run in the background), and -p 80:80 opens port 80 on your docker container, proxying all traffic to port 80 on the public IP of your slice. (Docker automatically sets up iptables forwarding rules for this).
The –rm switch means automatically remove the container when it is stopped, which is often what you want.
You should be able to see the application with a URL like this (note that this is unencrypted http not https, for testing).
Replace SYMSLICE_IPV4_ADDRESS with the public IP of your slice:
Stop your container
If all is working, stop your container:
docker container stop flaskr
Push your docker image to a Registry
The default docker registry is at https://hub.docker.com but we will be using gitlab’s registry for this test. The commands are the same except we pass it gitlab’s URL when logging in.
Login to the Registry
docker login registry.gitlab.com
You will be prompted for your username and password. If correct, it should respond:
Login Succeeded
Push your Image to the Registry
To push your application to the registry, you need to tag it first. You can think of a tag roughly as a folder / filename separated by a colon. The typical form is to use the convention APP_NAME:VERSION_NUMBER. For this test we will call our version “latest”, which is a common convention:
Important
Be sure to replace your username and project name in the URL below. Gitlab and others should have the correct URL in their web interface.
docker tag flaskr:latest registry.gitlab.com/my_group/my_project/flaskr:latest
You can then push your image to the registry:
docker push registry.gitlab.com/my_group/my_project/flaskr:latest
Deploy your docker image to a New Slice
Now that your docker image is in a registry, you can pull your image to other servers to quickly deploy your application. To test, go ahead and set up a new “vanilla” slice:
Create a test Slice to “pull” into
In the Syminet Cloud Panel, click Create -> Slice
Use the default image, Debian 12.
Proceed to create as normal.
Once the build is complete, login to your new slice and install docker:
Install docker
Note
The single command below should work for the purposes of this tutorial, although the above installation Method 2: Directly from Docker will also work.
apt install docker.io
Once complete, make sure docker is running:
docker version
The above command should output the version information and additional details. If you get an error message, try above installation command again.
Login to the Registry
You need to login to the registry to pull your image from it:
docker login registry.gitlab.com
You will be prompted for your username and password. If correct, it should respond:
Login Succeeded
Pull your Image from the Registry
docker pull registry.gitlab.com/my_group/my_project/flaskr:latest
Once complete, run your image. This is the same, except you reference the registry URL with the image name:
docker container run -d --name flaskr --rm --publish 80:80 registry.gitlab.com/my_group/my_project/flaskr:latest
Note
Don’t forget the URL above must match your username / password at the registry (they should have correct URLs on their web panel).
You should be able to see the application with a URL like this (note that this is unencrypted http not https, for testing).
Replace SYMSLICE_IPV4_ADDRESS with the public IP of your new slice:
If it comes up, congratulations! You now have at least a general understanding of how to deploy applications using docker.