Deploy Any SSL Secured Website With Docker And Traefik
What is Docker?
Docker is a platform that is used for developing, shipping, and running all kinds of applications. It enables the separation of applications from the infrastructure so that software can be delivered without concerns about the operating system of the host or the end-user.
To install Docker on your machine download the installation package from the official docker page here: https://docs.docker.com/get-docker/
To work with Docker you should get familiar with the following keywords/concepts: Container, Dockerfiles, Docker-Images, Docker-Compose
Container
A container describes a unit of software that merges code and every dependency to run an application. They provide a quick and safe way to run an application on several different devices. Also, it secures the application because of different isolation capabilities.
Docker Images
A Docker image is a read-only template that is used for creating the container to run the application within the Docker platform. It packages up applications and preconfigured server environments to create the container which will be deployed. On the officially DockerHub several already configured images are available to use. You can use the search function to find any image and deploy it on your system with:
$ docker run -it "NAME_OF_IMAGE_FROM_DOCKERHUB"
Dockerfiles
A Dockerfile is a plain text document that contains every command to set up an image. It contains the base image to use (operating system) and the additional software that should be installed on the resulting image.
Every time custom content is used for a Docker container a Dockerfile has to be created and filled with the missing information.
As an example, the following two snippets will demonstrate the usage of a Dockerfile. The first one will extend an NGINX image to serve a simple HTML file that is shown in the second snippet.
FROM nginx
COPY index.html /usr/share/nginx/html
<html>
<h1>How To Deploy Docker</h1>
<p>Learning IT. Level Up.</p>
<p>This is a simple static website, built and deliver from a docker container</p>
<p><a href="https://blog.paulknulst.de/">Check out my blog here</a></p>
</html>
If you place both files within the same folder you can run it with:
$ docker build -t nginx-sample .
$ docker run --name test-nginx -d -p 8080:80 nginx-sample
Now open your favorite web browser and hit http://localhost:8080
(or http://your-ip:8080
if you working on a server)
Docker Compose
Docker Compose is a tool that was developed to create multi-container applications in an easy way by using a YAML file that could contain several Docker containers.
One big advantage over simple Dockerfiles is that it enables the use of a simple “stack” file for your whole application stack. You can keep one Compose file in your repository and deploy everything with one simple command: docker-compose up -d
To install Docker Compose follow the official tutorial: https://docs.docker.com/compose/install/
Afterward, read the official Docker Compose guide to fully understand how a Docker Compose file is created because this will not be part of this article.
What is Traefik?
Traefik Makes Networking Boring
Cloud-Native Networking Stack That Just Works.
Traefik is used to forward incoming requests to a service deployed in a Docker environment. Also, it has the ability to create Let’s Encrypt SSL certificates automatically for every domain which is managed by traefik.
To set up a local Traefik service within your Docker environment you can download this Docker Compose file and execute the following commands:
1. Create an external network that is used for Traefik
$ docker network create traefik-public
2. Export all needed variables
export PRIMARY_DOMAIN=yourdomain.de
export TRAEFIK_SSLEMAIL=youremail@yourdomain.de
3. Deploy
$ docker-compose up -d
To access the traefik dashboard you can hit https://dashboard.yourdomain.de
and log in with:
username: devadmin
password: devto
To get a deeper understanding of Traefik you can read about How To Deploy it within this article.
Set Up And Deploy Your Website
Create A Simple Website
After you learned the basics and set up a Traefik instance you can start creating a Dockerfile and a Compose file to create a Docker Container (service) for your website.
To simplify this procedure I will deploy a simple dashboard project that I forked from an awesome list on GitHub. To get a copy of that dashboard either download the latest zip file here or clone the repository:
$ git clone git@github.com:paulknulst/personal-dashboard.git
In contrast to the original repository, I have adjusted the index.html and the CSS file to be kind of SEO optimized and have 5 items per row instead of 6.
Create a new folder (personal-dashboard) and extract (or move) the project files into a subfolder named html
. Now, you should open it in your favorite IDE, copy the config.sample.json to config.json and open it.
Change it to fulfill your needs and provide your own personal links. I will use the following settings:
{
"title" : "Pauls Simple Dashboard",
"items" : [
{
"alt" : "Github",
"icon" : "fab fa-github",
"link" : "https://github.com/paulknulst"
},
{
"alt" : "Twitter",
"icon" : "fab fa-twitter",
"link" : "https://twitter.com/paulknulst"
},
{
"alt" : "Portfolio",
"icon" : "fab fa-at",
"link" : "https://www.paulknulst.de"
},
{
"alt" : "Medium",
"icon" : "fab fa-medium",
"link" : "https://blog.paulknulst.de"
}
]
}
Create Dockerfile
The Dockerfile will be created in the simple-dashboard folder and only contains the base image and one copy command to add the HTML folder into the container.
FROM nginx
COPY html /usr/share/nginx/html
Create Compose File
The Compose file will be created in the simple-dashboard folder too. It contains every setting to set up your personal dashboard within your Docker environment. Furthermore, it will use Traefik to enable Let’s Encrypt certificate generation.
The complete Docker Compose file which will be explained afterward:
version: '3.4'
services:
web:
image: personal-dashboard
build:
context: ./
dockerfile: Dockerfile
networks:
- traefik-public
healthcheck:
test: curl --fail http://localhost || exit 1
interval: 60s
retries: 5
start_period: 20s
timeout: 10s
labels:
- traefik.enable=true
- traefik.docker.network=traefik-public
- traefik.constraint-label=traefik-public
- traefik.http.routers.personal-dashboard-http.rule=Host(`personal-dashboard.${PRIMARY_DOMAIN}`)
- traefik.http.routers.personal-dashboard-http.entrypoints=http
- traefik.http.routers.personal-dashboard-http.middlewares=https-redirect
- traefik.http.routers.personal-dashboard-https.rule=Host(`personal-dashboard.${PRIMARY_DOMAIN}`)
- traefik.http.routers.personal-dashboard-https.entrypoints=https
- traefik.http.routers.personal-dashboard-https.tls=true
- traefik.http.routers.personal-dashboard-https.tls.certresolver=le
- traefik.http.services.personal-dashboard.loadbalancer.server.port=80
# - traefik.http.routers.personal-dashboard-https.middlewares=security-headers
restart: unless-stopped
networks:
traefik-public:
external: true
Within this Compose file, you can see that we define an image in Line 5 (personal-dashboard:v1). Also, we add a build section because the image does not officially exist. Within the build section, we define that the Dockerfile which is located in the same directory should be used for creating the image.
The networks part (Line 9–10) contains the external network that was created during Traefik installation. Also, within Line 33–35 we especially define the network as an external network for this Compose service.
Another very important section is healthcheck (Line 11–16). For me, this part should be contained in every Docker Compose file because it helps to know if a Docker Container is running correctly without any runtime errors. For further reading have a look at this article that explains how to implement different types of health checks.
The most important part of this Compose file is the labels section. This section contains several labels that are important for Traefik. First, we enable Traefik (Line 18) for this service because in our Traefik service there was an option to not be working for every Docker service. Within Line 19 we define which external network is used for traefik.
In Line 20 we set the constraint-label of this service. Normally this is an optional setting and only used if we have more than one Traefik instance deployed to our Docker environment.
From Line 21–25 we define the URL of the service for HTTP and for HTTPS. For the HTTP part, we also activate a middleware from the Traefik configuration that will always redirect HTTP requests to HTTPS (Line 23).
The labels in Line 26 and 27 are necessary to create automatic SSL certificates for this Docker service.
Line 28 is needed to “expose” the internal Docker service port to the Traefik instance. All incoming requests to the URL defined in Line 21/24 will be forwarded to the Docker service on the Port mentioned within this label.
Line 29 is commented out because it is an extra middleware that I personally use in my Docker environment. I did not include this middleware within the Traefik installation but if you want to read about it have a look at my article about hardening any Traefik service.
Keep in mind that this file only works correctly if you followed the above steps to set up Traefik. If not you have to adjust PRIMARY_DOMAIN
, your Docker external network, and the entry points used for Traefik (http
, https
).
Deploy The Website
Now, that you finished creating the needed files you can open your CLI, switch to your project folder and start the deployment process by executing:
$ docker-compose up -d --build
After the deployment is complete you can open your dashboard in your browser and if you followed this tutorial it should look like this:
Closing Notes
I hope you enjoyed reading my tutorial and are now able to deploy your own website within a Docker container and enhance it with Traefik and SSL certificates.
Keep in mind that you can replace the HTML folder with every other static website. Also, you can extend the Compose file with other services like a database for your website. Furthermore, you can exchange the image with another public one from Docker Hub.
To help you, I have written another tutorial on how to deploy a Kimai2 Timetracking website that also includes a Docker Hub image, Traefik settings, a database, and an NGINX.
I would love to hear your feedback about this tutorial. Furthermore, if you already run a traefik installation and use a different approach please comment here and explain what you have done differently. Also, if you have any questions, please jot them down below. I try to answer them if possible.
Feel free to connect with me on Medium, LinkedIn, Twitter, and GitHub.