Instead of using a blogging engine like Wordpress, my website is created with a static site generator called Hugo. I don’t need to setup a database and my website is fast and secure, because I just need to serve static files.
In this setup, Traefik is configured as a reverse proxy, responsible for managing SSL certificates. Nginx is serving the static content from a directory. Everything is dockerized, of course.
We’ll start with a basic setup and further fine-tune the Nginx configuration.
Create the project structure #
mkdir -p $HOME/docker-projects/blog/www
cd docker-projects/blog
You should have the following structure:
├── blog
├── docker-compose.yml
└── www
In the www
directory you can place your static files (e.g. HTML files, images).
For testing purposes, create a index.html
file in www/
:
echo "<h1>HelloWorld</h1>" >> www/index.html
Very basic setup #
Now, we create a docker-compose.yml
in docker-projects/blog
:
services:
blog:
container_name: "blog"
image: nginx:1.26.1
volumes:
- ./www:/usr/share/nginx/html:ro
networks:
- docknet
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.blog.rule=Host(`example.com`)'
- 'traefik.http.routers.blog.entrypoints=https'
- 'traefik.http.routers.blog.tls=true'
- 'traefik.http.routers.blog.tls.certresolver=letsencrypt'
expose:
- 80
networks:
docknet:
external: true
Start the container using docker compose up -d
:
docker compose up -d
Open your domain in a web browser to verify that you can see the index.html
page displaying Hello World.
Add nginx.conf configuration file #
Update docker-compose.yml
to add a nginx.conf configuration file:
services:
blog:
container_name: "blog"
image: nginx:1.26.1
volumes:
- ./www:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- docknet
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.blog.rule=Host(`ggn92.dev`)'
- 'traefik.http.routers.blog.entrypoints=https'
- 'traefik.http.routers.blog.tls=true'
- 'traefik.http.routers.blog.tls.certresolver=letsencrypt'
expose:
- 80
networks:
docknet:
external: true
Add the Nginx configuration file nginx.conf
:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
Restart your Docker container using docker compose restart
and check the logs with docker logs blog
to make sure that everything is healthy:
docker compose restart
docker logs blog
Enable compression in Nginx #
Compressing responses often significantly reduces the size of transmitted data. It may be possible to gain performance benefits by enabling it in Nginx.
This is a response of my server without enabling compression:
curl -H "Accept-Encoding: gzip" -I https://ggn92.dev/
HTTP/2 200
accept-ranges: bytes
content-type: text/html
date: Fri, 09 Aug 2024 14:53:39 GMT
etag: "66b62859-63f5"
last-modified: Fri, 09 Aug 2024 14:31:53 GMT
server: nginx/1.26.1
content-length: 25589
We’ll set gzip
to on
and provide some additional configuration parameters:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_proxied any;
gzip_min_length 1000;
gzip_comp_level 5;
gzip_vary on;
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
Again, restart your Docker container and check the logs to make sure that everything is healthy:
docker compose restart
docker logs blog
And here is the result with enabled compression:
curl -H "Accept-Encoding: gzip" -I https://ggn92.dev/
HTTP/2 200
content-encoding: gzip
content-type: text/html
date: Fri, 09 Aug 2024 14:59:04 GMT
etag: W/"66b62859-63f5"
last-modified: Fri, 09 Aug 2024 14:31:53 GMT
server: nginx/1.26.1
vary: Accept-Encoding
Hide Nginx version #
Did you notice that we’re using nginx/1.26.1? We can omit that:
Add this line inside the http
section of nginx.conf
:
server_tokens off;
Restart the container and check the result:
docker compose restart
curl -I https://ggn92.dev/
HTTP/2 200
accept-ranges: bytes
content-type: text/html
date: Fri, 09 Aug 2024 15:57:27 GMT
etag: "66b62859-63f5"
last-modified: Fri, 09 Aug 2024 14:31:53 GMT
server: nginx
vary: Accept-Encoding
content-length: 25589
Thank you #
I appreciate your feedback on this tutorial. If you have suggestions, improvements, or encounter any bugs, please don’t hesitate to reach out. I’ll strive to keep this guide updated with the latest best practices and features.
Thank you for following along, and I hope this tutorial has been helpful in setting up your Nginx Docker container. Happy deploying!