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:

http://SYMSLICE_IPV4_ADDRESS

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:

http://SYMSLICE_IPV4_ADDRESS

If it comes up, congratulations! You now have at least a general understanding of how to deploy applications using docker.