Skip to content

Blog built by mkdocs-material, served by nginx inside a Docker container

Here's the Dockerfile generated by Claude Sonnet 3.6 (updated by DeepSeek-R1).

A bit of update just below this code block and a note about mkdocs and nginx below that

# Build stage
FROM python:3.12-slim AS builder
WORKDIR /mkdocs
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN mkdocs build

# Serve stage
FROM nginx:alpine-slim
COPY --from=builder /mkdocs/site/ /usr/share/nginx/html/
# Add custom nginx conf with trailing slash and port 3000
RUN echo 'server { \
    listen 3000; \
    location / { \
        root   /usr/share/nginx/html; \
        index  index.html index.htm; \
        try_files $uri $uri/ /index.html; \
    } \
    # Force trailing slash \
    rewrite ^([^.]*[^/])$ $1/ permanent; \
}' > /etc/nginx/conf.d/default.conf

EXPOSE 3000

# Thanks, Claude Sonnet 3.6

Updated

# Build stage
FROM python:3.12-slim AS builder
WORKDIR /mkdocs
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN mkdocs build

# Serve stage
FROM nginx:alpine-slim
COPY --from=builder /mkdocs/site/ /usr/share/nginx/html/

# Custom Nginx configuration with trailing slash and port 3000
RUN echo 'server { \
    listen 3000; \
    root /usr/share/nginx/html; \
    \
    # Force trailing slash for all non-file paths \
    if ($request_uri ~* "^[^.]*[^/]$") { \
        rewrite ^(.*)$ $scheme://$host$1/ permanent; \
    } \
    \
    location / { \
        index index.html index.htm; \
        try_files $uri $uri/ /index.html; \
    } \
}' > /etc/nginx/conf.d/default.conf

EXPOSE 3000

# Started by Sonnet, corrected by DeepSeek-R1

See the update context here

Extra note

It seems that most of people come here trying to find out how to set up nginx for mkdocs? You can take this with a grain of salt since I haven't tried it but the resulting docker's nginx configuration in the container is:

server {
    listen 3000;
    root /usr/share/nginx/html;
    if ($request_uri ~* "^[^.]*[^/]$") {
        rewrite ^(.*)$ $scheme://$host$1/ permanent;
    }
    location / {
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}

Please note, that is not tested in a standard nginx server.

So, build the mkdocs, then copy the whole site to the html folder or public_html. Then, maybe find a proper guide on serving a static HTML website with nginx. For HTTPS/SSL, set it up using certbot.

Dockerfile discussion

So in the first container (or "image"? I have to check the right term), we installed mkdocs-material (which is the only library in requirements.txt). It has the mkdocs command. Then we run mkdocs build on our mkdocs project folder.

Read the guide here: Getting started with MkDocs.

In the second container, we simply copy the built static site from /site/ (which is in our first container, builder) to the default HTML site of nginx in /usr/share/nginx/html/.

The RUN echo part is just nginx configuration, where I add the trailing slash rule.

We expose the second container's port 3000. It's Coolify's default port setting: 3000:3000. The SSL part is handled by Coolify, simply by stating that the domain is (for my blog) https://ariesta.id.

With this, every time I add a new post file in my git repo and push it, Coolify should build the site and update it.