parent
d0675d9a7c
commit
da48aac295
@ -0,0 +1,217 @@ |
||||
+++ |
||||
title = "Time to deploy our static blog" |
||||
author = ["Elia el Lazkani"] |
||||
date = 2021-07-10 |
||||
lastmod = 2021-07-10 |
||||
tags = ["docker", "dockerfile", "linux", "traefik", "nginx", "ssl", "letsencrypt"] |
||||
categories = ["container"] |
||||
draft = false |
||||
+++ |
||||
|
||||
In the previous post, entitled "[Let's play with Traefik]({{< relref "let-s-play-with-traefik" >}})", we deployed |
||||
_Traefik_ and configured it. We left it in a running state but we haven't |
||||
_really_ used it properly yet. |
||||
|
||||
Let's put it to some good use this time around. |
||||
|
||||
<!--more--> |
||||
|
||||
|
||||
## Pre-requisites {#pre-requisites} |
||||
|
||||
This blog post assumes that you already have a generated static _website_ or |
||||
_blog_. There are multiple tools in the sphere which allows you to statically |
||||
generate your blog. |
||||
|
||||
You can find a list of them on the |
||||
[Awesome Static Web Site |
||||
Generators](https://github.com/myles/awesome-static-generators). |
||||
|
||||
Once we have the directory on disk, we can move forward. |
||||
|
||||
|
||||
## Components {#components} |
||||
|
||||
Let's talk components a tiny bit and see what we have and what we need. We |
||||
already a _static site_. We can expose our _site_ using _Traefik_. We can also |
||||
generate an _SSL certificate_ for the exposed _site_. |
||||
|
||||
What we don't have, is a way to _serve_ our _static site_. _Traefik_ is only a |
||||
_reverse proxy_ server. A _reverse proxy_, sort of, routes into and out of |
||||
sockets. These sockets could be open local ports, or they could, also, be other |
||||
containers. |
||||
|
||||
|
||||
## Nginx {#nginx} |
||||
|
||||
That's where [_nginx_](https://nginx.org/) comes into the picture. |
||||
|
||||
> nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a |
||||
> generic TCP/UDP proxy server, originally written by Igor Sysoev. |
||||
|
||||
We can find an _nginx_ docker image on |
||||
[dockerhub](https://hub.docker.com/%5F/nginx). But, if we look around carefully |
||||
we can see a section that mentions "_running nginx as a non-root user_". This |
||||
led me to a small discovery which made me look for an alternative of that image. |
||||
|
||||
Luckily for us, _nginxinc_ also releases an _unprivileged_ version of that image |
||||
under the name of [nginx-unprivileged](https://hub.docker.com/r/nginxinc/nginx-unprivileged). |
||||
|
||||
|
||||
### Configuration {#configuration} |
||||
|
||||
The _nginx_ docker image can be configured using a _template_ configuration file |
||||
which can be mounted into the container. |
||||
|
||||
The configuration can include _variables_ which will be replaced by _environment |
||||
variables_ we inject into the container. |
||||
|
||||
Let's look at an example configuration `default.conf.template`. |
||||
|
||||
```conf |
||||
server { |
||||
|
||||
listen ${NGINX_BLOG_PORT}; |
||||
server_name localhost; |
||||
|
||||
root /usr/share/nginx/html/${NGINX_BLOG_HOST}; |
||||
|
||||
location / { |
||||
index index.html; |
||||
|
||||
try_files $uri $uri/ =404; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
In the example above, we use `NGINX_BLOG_HOST` and `NGINX_BLOG_PORT` as |
||||
_environment variables_ to be replaced in the _nginx_ configuration. |
||||
|
||||
|
||||
## Container {#container} |
||||
|
||||
After creating our _nginx_ configuration, we need to run an _nginx_ container |
||||
and serve our blog to the users. |
||||
|
||||
In the [previous post]({{< relref "let-s-play-with-traefik" >}}), we used _docker-compose_ to |
||||
deploy _Traefik_. We will continue with that and deploy our _nginx_ container |
||||
alongside. |
||||
|
||||
|
||||
### docker-compose {#docker-compose} |
||||
|
||||
Before we go ahead and create another service in the _docker-compose_ file, |
||||
let's talk a bit about what we need. |
||||
|
||||
We need to deploy an _unprivileged nginx_ container, first and foremost. We need |
||||
to inject a few _environment variables_ into the container to be included in the |
||||
_nginx_ templated configuration. We, also, need not forget to include the |
||||
_labels_ required for _Traefik_ to route our container properly, and generate an |
||||
_SSL certificate_. Finally, we need to mount both the _nginx configuration |
||||
template_ and, of course, our _static blog_. |
||||
|
||||
Now let's head to work. |
||||
|
||||
```yaml |
||||
nginx: |
||||
container_name: nginx |
||||
image: nginxinc/nginx-unprivileged:alpine |
||||
restart: unless-stopped |
||||
mem_limit: 8m |
||||
command: ["nginx", "daemon off;"] |
||||
volumes: |
||||
- "./blog/static/:/usr/share/nginx/html/blog:ro" |
||||
- "./blog/nginx/default.conf.template:/etc/nginx/templates/default.conf.template:ro" |
||||
environment: |
||||
- NGINX_BLOG_PORT=80 |
||||
- NGINX_BLOG_HOST=blog.example.com |
||||
labels: |
||||
- "traefik.http.routers.blog-http.rule=Host(`blog.example.com`)" |
||||
- "traefik.http.routers.blog-http.service=blog-http" |
||||
- "traefik.http.services.blog-http.loadbalancer.server.port=80" |
||||
- "traefik.http.routers.blog-http.middlewares=blog-main" |
||||
- "traefik.http.middlewares.blog-main.chain.middlewares=frame-deny,browser-xss-filter,ssl-redirect" |
||||
- "traefik.http.middlewares.frame-deny.headers.framedeny=true" |
||||
- "traefik.http.middlewares.browser-xss-filter.headers.browserxssfilter=true" |
||||
- "traefik.http.middlewares.ssl-redirect.headers.sslredirect=true" |
||||
- "traefik.http.routers.blog-http.tls.certresolver=cloudflareresolver" |
||||
``` |
||||
|
||||
If we look at the _Traefik_ configuration we can see the following important configurations. |
||||
|
||||
`traefik.http.routers.blog-http.rule` |
||||
: This configures the `hostname` |
||||
_Traefik_ should be listening on for our _nginx_ container. |
||||
|
||||
`traefik.http.routers.blog-http.service` |
||||
: This configures the _router_ to |
||||
use our _service_. |
||||
|
||||
`traefik.http.services.blog-http.loadbalancer.server.port` |
||||
: We configure the |
||||
_service_ `port`. |
||||
|
||||
`traefik.http.routers.blog-http.middlewares` |
||||
: We configure the _router_ to |
||||
use our `middleware`. |
||||
|
||||
`traefik.http.middlewares.blog-main.chain.middlewares` |
||||
: We configure all the |
||||
`middleware` chain. |
||||
|
||||
`traefik.http.middlewares.ssl-redirect.headers.sslredirect` |
||||
: We always |
||||
redirect `http` to `https`. |
||||
|
||||
`traefik.http.routers.blog-http.tls.certresolver` |
||||
: We configure the |
||||
_resolver_ to use to generate our _SSL certificate_. |
||||
|
||||
We can also see our _static blog_ and the _nginx template_ being mounted as |
||||
_read-only_ inside the container to their right paths. Finally, we verify that |
||||
our `NGINX_BLOG_HOST` and `NGINX_BLOG_PORT` are configured correctly. |
||||
|
||||
|
||||
## Final steps {#final-steps} |
||||
|
||||
After putting everything in place, we do a quick last check that everything is |
||||
correctly in place. Once we are satisfied with the results, we run ! |
||||
|
||||
```shell |
||||
docker-compose up -d |
||||
``` |
||||
|
||||
And we're good to go. |
||||
|
||||
If we point our `/etc/hosts` to our site, we can test that everything works. |
||||
|
||||
```conf |
||||
192.168.0.1 blog.example.com |
||||
``` |
||||
|
||||
<div class="admonition note"> |
||||
<p class="admonition-title">Note</p> |
||||
|
||||
Replace `192.168.0.1` with your public server's IP address. This is an example |
||||
of an IP unroutable on the internet. |
||||
|
||||
</div> |
||||
|
||||
If everything is configured properly, we should see our _site_ pop up |
||||
momentarily. The _SSL certificate_ will fail for a few minutes until _Traefik_ |
||||
is able to generate a new one and serve it. Give it some time. |
||||
|
||||
Once everything up and running, you can enjoy your _blog_ being served by |
||||
_Traefik_ through an _nginx_ container. |
||||
|
||||
|
||||
## Conclusion {#conclusion} |
||||
|
||||
You can serve your _static blog_ with _Traefik_ and _nginx_ easily. Make sure to |
||||
take the necessary measures to run container _safely_ and it should be easy as pie. |
||||
|
||||
_Traefik_ makes it possible to route to multiple containers this way, allowing |
||||
us to add more services to the _docker-compose_ file. At the same time, _nginx_, |
||||
with the _templating feature_, offers us another flexible way to serve a big |
||||
variety of _static sites_. Using them in combination open a wide range of |
||||
possibilities. |
Loading…
Reference in new issue