Caddy plugin that gives native support for Python WSGI apps.
It embeds the Python interpreter inside Caddy and serves requests directly without going through a reverse proxy or creating a new process.
There's a docker image available, it ships Python 3.12 and can be used as follows:
FROM ghcr.io/mliezun/caddy-snake:main
WORKDIR /app
# Copy your project into app
COPY . /app
# Caddy snake is already installed and has support for Python 3.12
CMD ["caddy", "run", "--config", "/app/Caddyfile"]
Go 1.21 and Python 3.9 or later is required, with development files to embed the interpreter.
To install in Ubuntu do:
sudo apt-get update
sudo apt-get install -y python3-dev
To install in macOS do:
brew install python@3
Build this module using xcaddy:
CGO_ENABLED=1 xcaddy build --with github.com/mliezun/[email protected]
There's a template file in the project: builder.Dockerfile. It supports build arguments to configure which Python or Go version is desired for the build.
FROM ubuntu:latest
ARG GO_VERSION=1.22.1
ARG PY_VERSION=3.12
RUN export DEBIAN_FRONTEND=noninteractive &&\
apt-get update -yyqq &&\
apt-get install -yyqq wget tar software-properties-common gcc pkgconf &&\
add-apt-repository -y ppa:deadsnakes/ppa &&\
apt-get update -yyqq &&\
apt-get install -yyqq python${PY_VERSION}-dev &&\
mv /usr/lib/x86_64-linux-gnu/pkgconfig/python-${PY_VERSION}-embed.pc /usr/lib/x86_64-linux-gnu/pkgconfig/python3-embed.pc &&\
rm -rf /var/lib/apt/lists/* &&\
wget https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go*.linux-amd64.tar.gz && \
rm go*.linux-amd64.tar.gz
ENV PATH=$PATH:/usr/local/go/bin
RUN go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest &&\
cd /usr/local/bin &&\
CGO_ENABLED=1 /root/go/bin/xcaddy build --with github.com/mliezun/caddy-snake &&\
rm -rf /build
CMD ["cp", "/usr/local/bin/caddy", "/output/caddy"]
You can copy the contents of the builder Dockerfile and execute the following commands to get your Caddy binary:
docker build -f builder.Dockerfile --build-arg PY_VERSION=3.9 -t caddy-snake .
docker run --rm -v $(pwd):/output caddy-snake
{
http_port 9080
https_port 9443
log {
level error
}
}
localhost:9080 {
route {
python "simple_app:main"
}
}
The python
rule is an HTTP handler that expects a wsgi app as an argument.
- simple_app. WSGI App that returns the standard hello world message and a UUID.
- simple_exception. WSGI App that always raises an exception.
- example_flask. Flask application that also returns hello world message and a UUID.
- example_fastapi. FastAPI application that also returns hello world message and a UUID.
- Caddyfile. Caddy config that uses all of the example apps.
NOTE
It's also possible to provide virtual environments with the following syntax:
python {
module_wsgi "simple_app:main"
venv_path "./venv"
}
What it does behind the scenes is to append venv/lib/python3.x/site-packages
to python sys.path
.
Disclaimer: Currently, when you provide a venv it gets added to the global
sys.path
, which in consequence means all apps have access to those packages.