Derafu Docker with Python and Caddy for Fabric
A modern Docker setup for hosting Python websites with Caddy web server and SSH access for Fabric deployments — the Python counterpart of Docker with PHP and Caddy.
Features
- Python 3.14: Supported Python version with common extensions.
- Caddy: Modern web server with automatic HTTPS.
- SSH Access: For automated deployments with Fabric.
- Automatic Site Discovery: Just add your site folder and it works.
- Development Domains: Test with
.localdomains that map to production folders. - Automatic WWW Redirection: For second-level domains (e.g.,
example.com→www.example.com). - Auto-HTTPS: Certificates are automatically generated on-demand.
- Environment Separation: Development and production environments managed through Docker Compose override.
- Optional PHP embed +
phpy: build PHP with--enable-embedand installphpyso Python code running in this container can host and call PHP libraries directly (e.g. Backbone Bridge Python). Disabled by default — see PHP Embed + phpy below.
Quick Start
Prerequisites
- Docker and Docker Compose installed on your system.
- SSH key for deployment access.
Setup
-
Clone this repository:
git clone https://github.com/derafu/docker-python3.14-caddy-server.git cd docker-python3.14-caddy-server -
Add your SSH public key to
config/ssh/authorized_keysfor admin, and default deployment, access:cat ~/.ssh/id_rsa.pub > config/ssh/authorized_keys -
Build and start the container:
docker-compose up -d
Testing Your First Site
-
Create the site directory structure and a Django project:
mkdir -p sites/www.example.com/ cd sites/www.example.com/ python3 -m venv venv source venv/bin/activate pip install django django-admin startproject example . -
Run it:
/scripts/start_sites.sh www.example.comIf no site is specified, the script starts every available site under
/var/www/sites. -
Access it at
https://www.example.com(production, requires DNS) orhttps://www.example.com.local:8443(development, requires a local/etc/hostsentry).
PHP Embed + phpy (Optional)
This image can optionally build PHP from source with --enable-embed and install phpy, so Python code can load and call a PHP library directly in the same process — the Python-hosts-PHP direction; the opposite direction, PHP-hosts-Python, is what Docker with PHP and Caddy provides.
This is disabled by default: no regular PHP package (apt, Homebrew, official Docker images) ships with --enable-embed, so getting it requires compiling PHP from source, which adds several minutes to the image build. Enable it explicitly when you actually need it:
# In your .env file:
PHPY_ENABLED=true
PHPY_PHP_VERSION=8.5.3 # Optional, defaults to 8.5.3.
docker compose build
docker compose up -d
When enabled, the embed-enabled PHP build lives at /opt/php (php, php-config, phpize on PATH), and phpy is installed into the container’s Python. Verify it works with:
docker compose exec webserver python3 -c "import phpy; print(phpy)"
Building with the default PHPY_ENABLED=false skips all of this and behaves exactly like a normal Python + Caddy image.
Since phpy is installed into the container’s own Python, not into any particular virtualenv, create yours with python3 -m venv --system-site-packages so it can still see it. See Backbone Bridge Python for the Python-side package that builds on top of this.
Development vs Production Environment
Docker Compose’s override mechanism separates the two:
- Production (
docker-compose.ymlalone): minimal configuration, required environment variables, essential ports (HTTP, HTTPS, SSH), no external volumes. - Development (
docker-compose.override.yml, merged automatically bydocker-compose up -d): additional development ports and local volume mounts for live editing.
To run production-only:
docker-compose -f docker-compose.yml up -d
Access and Management
# SSH access.
ssh admin@localhost -p 2222
# Direct container shell.
docker exec -it derafu-sites-server-python-caddy bash
# Restart Caddy.
docker exec -it derafu-sites-server-python-caddy supervisorctl restart caddy
# Stop the container.
docker-compose down