enhance(): Publishing new post titled "Time to deploy our static blog"
This commit is contained in:
parent
d0675d9a7c
commit
da48aac295
2 changed files with 416 additions and 0 deletions
|
@ -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:
|
||||
|
|
217
content/posts/time-to-deploy-our-static-blog.md
Normal file
217
content/posts/time-to-deploy-our-static-blog.md
Normal 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.
|
Loading…
Reference in a new issue