Static sites with Python, uv, Caddy, and Docker

https://news.ycombinator.com/rss Hits: 11
Summary

Wednesday, August 20, 2025 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/ The first line is our starting image: # use Debian image with uv, no need for system Python FROM ghcr.io/astral-sh/uv:debian AS build It uses an image built by Astral, the makers of uv, that’s based on Debian. It also names it build, since we’re only using the image in the first step, and are actually not relying on it by the end of the process. The second line defines our working directory inside the container: # explicit work d...

First seen: 2025-08-23 20:41

Last seen: 2025-08-24 06:58