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: |location_mega_tutorial|
.. |location_mega_tutorial| raw:: html
The Flask Mega-Tutorial, Part XIX: Deployment on Docker Containers ↗
Create a Flask Slice
--------------------
* In the Syminet Cloud Panel, click :guilabel:`Create` -> :guilabel:`Slice`
* Click the :guilabel:`Marketplace` tab.
* Click :guilabel:`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:
.. code-block::
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, :doc:`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 :ref:`install_directly` below.
The quickest way is to install from debian packages with a single command:
.. code-block::
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.
.. _install_directly:
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:
.. code-block::
#!/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 `` and run it.
Once complete, make sure docker is running:
.. code-block::
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:
.. code-block::
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:
.. code-block::
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:
.. code-block::
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:
.. code-block::
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:
.. code-block::
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
~~~~~~~~~~~~~~~~~~~~~
.. code-block::
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.
.. code-block::
docker tag flaskr:latest registry.gitlab.com/my_group/my_project/flaskr:latest
You can then push your image to the registry:
.. code-block::
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 :guilabel:`Create` -> :guilabel:`Slice`
* Use the default image, :guilabel:`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.
.. code-block::
apt install docker.io
Once complete, make sure docker is running:
.. code-block::
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:
.. code-block::
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block::
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:
.. code-block::
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.