Tech News
← Back to articles

Static sites with Python, uv, Caddy, and Docker

read original related products more articles

Static Sites with Python, uv, Caddy, and Docker

My preferred deployment stack for Python-built static sites.

I’ve largely switched to uv at this point and it’s been pretty great. I use it for everything I can, from little scripts with uv run , to libraries, to applications. It’s so fast it does actually matter, the workflow side of things works well enough for me, and—perhaps most valuably—it manages Python executables for me beautifully.

As we’re all familiar with by now, I’m a static site aficionado, and have a number out in the wild. Some are purely static—hand-crafted artisanal HTML and CSS—and others are built with Python. I like serving them all with Caddy inside a multi-stage build Docker container, which has been working quite well for me so far.

In this post I want to explain the fairly simple setup I use to build and serve a number of websites using the above stack.

Example

For our main example we can use my personal deployment of sus, a static site based URL shortener I wrote and have been using for years.

Dockerfile

Let’s start with the Dockerfile and then we’ll go through it line by line:

# use Debian image with uv, no need for system Python FROM ghcr.io/astral-sh/uv:debian AS build # explicit work dir is important WORKDIR /src # copy all files COPY . . # install Python with uv RUN uv python install 3 .13 # run build process RUN uv run --no-dev sus # serve with Caddy FROM caddy:alpine # copy Caddy config COPY Caddyfile /etc/caddy/Caddyfile # copy generated static site COPY --from = build /src/output /srv/

... continue reading