enhance(): Publishing new post titled "Time to deploy our static blog"

This commit is contained in:
Elia el Lazkani 2021-07-10 16:18:04 +02:00
parent d0675d9a7c
commit da48aac295
2 changed files with 416 additions and 0 deletions

View file

@ -2360,6 +2360,205 @@ docker-compose up -d
If everything is configured correctly, your blog should pop-up momentarily.
*Enjoy !*
*** DONE Time to deploy our static blog :docker:dockerfile:linux:traefik:nginx:ssl:letsencrypt:
:PROPERTIES:
:EXPORT_HUGO_LASTMOD: 2021-07-10
:EXPORT_DATE: 2021-07-10
:EXPORT_FILE_NAME: time-to-deploy-our-static-blog
:CUSTOM_ID: time-to-deploy-our-static-blog
:END:
In the previous post, entitled "[[#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.
#+hugo: more
**** 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
[[https://github.com/myles/awesome-static-generators][Awesome Static Web Site
Generators]].
Once we have the directory on disk, we can move forward.
**** 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
That's where [[https://nginx.org/][/nginx/]] comes into the picture.
#+begin_quote
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.
#+end_quote
We can find an /nginx/ docker image on
[[https://hub.docker.com/_/nginx][dockerhub]]. 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 [[https://hub.docker.com/r/nginxinc/nginx-unprivileged][nginx-unprivileged]].
***** 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=.
#+begin_src 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;
}
}
#+end_src
In the example above, we use ~NGINX_BLOG_HOST~ and ~NGINX_BLOG_PORT~ as
/environment variables/ to be replaced in the /nginx/ configuration.
**** Container
After creating our /nginx/ configuration, we need to run an /nginx/ container
and serve our blog to the users.
In the [[#let-s-play-with-traefik][previous post]], we used /docker-compose/ to
deploy /Traefik/. We will continue with that and deploy our /nginx/ container
alongside.
***** 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.
#+begin_src 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"
#+end_src
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
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 !
#+begin_src shell
docker-compose up -d
#+end_src
And we're good to go.
If we point our ~/etc/hosts~ to our site, we can test that everything works.
#+begin_src conf
192.168.0.1 blog.example.com
#+end_src
#+BEGIN_EXPORT html
<div class="admonition note">
<p class="admonition-title">Note</p>
#+END_EXPORT
Replace ~192.168.0.1~ with your public server's IP address. This is an example
of an IP unroutable on the internet.
#+BEGIN_EXPORT html
</div>
#+END_EXPORT
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
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.
** K3s :@k3s:
*** DONE Building k3s on a Pi :arm:kubernetes:
:PROPERTIES:

View file

@ -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.