Skip to content

Repository files navigation

Derafu Sites Server - Docker with Python and Caddy for Fabric

GitHub last commitGitHub code size in bytesGitHub Issues

A modern Docker setup for hosting Python websites with Caddy web server and SSH access for Fabric deployments.

Features

  • Python 3.14.7: 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 .local domains 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-embed and install phpy so Python code running in this container can host and call PHP libraries directly (e.g. derafu/backbone-bridge-python). Disabled by default; see PHP embed + phpy (optional) below.

Quick Start

Prerequisites

  • Docker and Docker Compose installed on your system.
  • SSH key for deployment access.

Setup

  1. Clone this repository:

    git clone https://github.com/derafu/docker-python3.14-caddy-server.git
    cd docker-python3.14-caddy-server
  2. Add your SSH public key to config/ssh/authorized_keys for admin, and default deployment, access:

    cat ~/.ssh/id_rsa.pub > config/ssh/authorized_keys
  3. Build and start the container:

    docker-compose up -d

    The -d parameter runs it in detached mode (background).

Verification

Check that the container is running:

docker-compose ps

View container logs:

docker-compose logs -f

The -f parameter allows you to follow logs in real-time.

Testing Your First Site

  1. Create the site directory structure:

    mkdir -p sites/www.example.com/
    cd sites/www.example.com/
  2. Create project Django

    python3 -m venv venv
    source venv/bin/activate
    pip install django
    django-admin startproject example .
  3. Run a single site manually

    /scripts/start_sites.sh www.example.com

    Note: If no site is specified, the script will start all available sites under /var/www/sites.

  4. Access the site at:

For local development, add to your /etc/hosts file:

127.0.0.1 www.example.com.local

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-php8.5-caddy-server 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, composer 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.

Directory Structure

docker-python3.14-caddy-server/
├── Dockerfile # Python + Caddy server base image definition (+ optional PHP/phpy)
├── docker-compose.yml # Production Docker services and volumes
├── .env # Environment variables for docker-compose
├── LICENSE # Project license
├── README.md # Main project documentation
Configuration
├── config/
│ ├── bash/
│ │ └── bashrc # Shell prompt / history tweaks for container user
│ ├── caddy/
│ │ └── Caddyfile # Caddy reverse proxy rules (HTTPS, domains, routing)
│ ├── cron/
│ │ └── logrotate # Cron job for rotating logs periodically
│ ├── logrotate/
│ │ ├── caddy # Logrotate rules for Caddy
│ │ └── gunicorn # Logrotate rules for Gunicorn
│ ├── ssh/
│ │ ├── authorized_keys # Public keys for SSH login (e.g., deploy access)
│ │ └── sshd_config # SSH server settings (OpenSSH)
│ └── supervisor/
│ └── supervisord.conf # Supervisor config to manage processes (Caddy, Gunicorn, etc.)
Development
├── sites/ # Django projects, one per domain
│ └── www.example.com/ # Project folder for www.example.com
Helper Scripts
├── scripts/
│ └── start_procfile_supervisord.sh # Auto-detect and launch Gunicorn/Celery for each site under /sites
Documentation
├── docs/
│ └── docker.md # Notes and recommendations for Docker usage

Development vs Production Environment

This project uses Docker Compose's override functionality to separate development and production configurations:

Production Environment

The base docker-compose.yml contains the minimal configuration needed for production deployment. It:

  • Sets up required environment variables.
  • Defines essential ports (HTTP, HTTPS, SSH).
  • Doesn't mount external volumes.

Development Environment

The docker-compose.override.yml file adds development-specific settings:

  • Adds additional development ports (e.g., management interface).
  • Mounts local volumes for easy site development.

Usage:

  • Development: Docker Compose automatically merges both files:

    docker-compose up -d
  • Production: Use only the base configuration:

    docker-compose -f docker-compose.yml up -d

Access and Management

SSH Access

Connect to the container via SSH:

ssh admin@localhost -p 2222

Direct Container Access

Access the container shell:

docker exec -it derafu-sites-server-python-caddy bash

Restarting Services

Restart Caddy web server:

docker exec -it derafu-sites-server-python-caddy supervisorctl restart caddy

Stopping the Container

docker-compose down

Rebuilding After Configuration Changes

Rebuild for development:

docker-compose build --no-cache
docker-compose up -d

Rebuild for production:

docker-compose -f docker-compose.yml build --no-cache
docker-compose -f docker-compose.yml up -d

Adding New Sites

  1. Create the site directory structure:

    mkdir -p sites/www.newsite.com/
    cd sites/www.newsite.com/
  2. Create project Django

    python3 -m venv venv
    source venv/bin/activate
    pip install django
    django-admin startproject newsite .

    NOTE: It's important that the requirements.txt file includes the gunicorn dependency (Example gunicorn==23.0.0)

  3. No server restart required! Caddy automatically detects new sites.

  4. For local development, add to your hosts file:

    127.0.0.1 www.newsite.com.local
    

Environment Variables

Customize behavior through environment variables:

VariableDescriptionDefault
SERVER_NAMEName for the docker containerderafu-sites-server
CADDY_DEBUGEnable debug mode with debug(empty)
CADDY_EMAILEmail for Let's Encryptadmin@example.com
CADDY_HTTPS_ISSUERTLS issuer (internal, acme)internal
CADDY_HTTPS_ALLOW_ANY_HOSTAllow any host for TLSfalse
CADDY_LOG_SIZELog file max size100mb
CADDY_LOG_KEEPNumber of log files to keep5
WWW_ROOT_PATHWeb root path/var/www/sites
WWW_USERWWW and SSH user in the containeradmin
WWW_GROUPWWW group in the containerwww-data
HTTP_PORTHTTP port in host8080
HTTPS_PORTHTTPS port in host8443
SSH_PORTSSH port in host2222
PHPY_ENABLEDBuild PHP (--enable-embed) + phpy + Composerfalse
PHPY_PHP_VERSIONPHP version to build when PHPY_ENABLED=true8.5.3

Domain Logic

The server handles domains in the following way:

  1. Development domains: Any domain ending with .local (e.g., www.example.com.local)

    • Maps to the same directory as its production counterpart.
    • Uses internal self-signed certificates.
  2. Production domains:

    • Redirects from non-www to www for second-level domains.
    • Automatically obtains and manages Let's Encrypt certificates (issuer acme).

Troubleshooting

SSL Certificate Issues

If you're having issues with SSL certificates in development:

  • Ensure your browser trusts self-signed certificates.
  • Try using HTTP instead of HTTPS for local development.

Permissions Issues

If you encounter permission issues:

docker exec -it derafu-sites-server-python-caddy chown -R admin:www-data /var/www/sites

Logs Location

Logs are available in the container and can be accessed with:

docker exec -it derafu-sites-server-python-caddy cat /var/log/caddy/access.log

Advanced Usage

Custom Caddy Configuration

For advanced configurations, modify the Caddyfile at config/caddy/Caddyfile.


Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

License

This package is open-sourced software licensed under the MIT license.

About

Docker with Python 3.14 and Caddy for Django

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

Contributors

Languages