Caddy is a modern, lightweight web server that is famous for its simplicity and automatic HTTPS support. When it is combined with Docker, it becomes a powerful tool for deploying secure and scalable web applications.
Instead of manually configuring SSL certificates or setting up complex reverse proxies, you can rely on a Caddyfile. Using a Caddyfile with Docker enables you to manage sites, handle traffic routing, and enable HTTPS with only a few code lines.
In this guide, we will study how to use Caddyfile Docker with all the technicalities.
What Is a Caddyfile?
A Caddyfile is basically a configuration file that is used by the Caddy web server. It offers a simple but human-readable syntax for defining sites, reverse proxies, TLS/SSL settings, and other server rules.
Unlike other complex configuration formats, such as Nginx or Apache, the Caddyfile is minimal.
Example of a simple Caddyfile:
Get exclusive access to all things tech-savvy, and be the first to receive
the latest updates directly in your inbox.
example.com {
reverse_proxy localhost:5000
}
This example shows that the Caddy will serve traffic for example.com site and forward requests to the app that is running locally on port 5000, while automatically handling HTTPS certificates.
Using Caddy with Docker
Caddy can run inside a Docker container to simplify deployment and scalability. Using Caddyfile with Docker, you can:
- Run Caddy as a reserve proxy for your apps.
- Mount a Caddyfile into the container for easy configuration.
- Automatically handle the HTTPS certificates using Let’s Encrypt.
- Use Docker Compose to manage multi-server/ service setups.
Example basic command to run Caddy with Docker:
docker run -d \
-p 80:80 -p 443:443 \
-v $PWD/Caddyfile:/etc/caddy/Caddyfile \
-v caddy_data:/data \

-v caddy_config:/config \
caddy:latest
This mounts your Caddyfile with Docker and sets up persistent volumes for certificates and configurations.
Caddyfile Configuration Basics
The Caddyfile in Docker is structured around site blocks, which define how the Caddy shall handle a request for a domain.
Key features include:
- reverse_proxy: Forwards requests to a backend service.
- root: Serves static files.
- tls: Configures TLS certificates (automatic with Let’s Encrypt by default).
- log: Enables request logging.
Example:
myapp.com {
root * /var/www/html
file_server
log {
output file /var/log/caddy/access.log
}
}
This configuration serves a static site from /var/www/html with logging enabled.
Caddyfile Docker Config Proxy Examples
A few common Caddyfile Docker config proxy examples include:
- Simple Reverse Proxy
example.com {
reverse_proxy app:5000
}
Forwards traffic from example.com to a container named app running on port 5000.
- Multiple Domain Configuration
example1.com {
reverse_proxy app1:4000
}
example2.com {
reverse_proxy app2:5000
}
Handles multiple services under different domains.
myservice.com {
reverse_proxy app1:4000 app2:4000 app3:4000
}
Distributes traffic across multiple backend containers for scalability.
Using Caddyfile with Docker Compose
Another way to run Caddy with apps is by using Docker Compose, which would manage multiple containers at once.
docker-compose.yml Example:
version: “3.9”
services:
caddy:
image: caddy:latest
ports:
– “80:80”
– “443:443”
volumes:
– ./Caddyfile:/etc/caddy/Caddyfile
– caddy_data:/data
– caddy_config:/config
depends_on:
– app
app:
build: ./app
expose:
– “5000”
volumes:
caddy_data:
caddy_config:
This setup runs a Go/Python/Node app alongside Caddy, which automatically proxies requests to the app container.
Best Practices for Caddyfile in Docker
A few best practices that would help you make the most out of Caddyfile in Docker.
- Always mount /data and /config as persistent volumes to avoid losing TLS certificates on container restart.
- Use separate site blockers for clarity instead of cramming multiple rules into one.
- Enable logging by configuring access and error logs for debugging.
- Use docker-compose or orchestration tools to keep services consistent and automated.
- Limit the number of open ports and restrict file permissions on mounted Caddyfiles to enhance security.
- Test locally first by validating all the Caddyfiles with caddy validate before deploying.
Common Issues and Fixes
Issue | Cause | Fix |
Caddy not starting | Syntax error in Caddyfile | Run caddy validate to check the config |
HTTPS not working | Port 443 blocked or DNS misconfigured | Open firewall ports, ensure DNS points to the server |
Certificates not persisting | Missing volumes for /data and /config | Mount persistent Docker volumes |
Proxy not forwarding | Wrong container name or port in Caddyfile | Ensure container names/ports match Compose setup |
Multiple domains failing | Overlapping/misconfigured site blocks | Use separate site blocks for each domain |
Conclusion – Using Caddyfile with Docker
Using Caddy with Docker makes it easy and simple to manage web servers and reverse proxy management by leveraging the power of the two. The Caddyfiles simplifies route defining, SSL, and proxy rules without complex setups, while Docker Compose provides a structured way to manage multiple services.
FAQs
How do I use a Caddyfile with Docker?
You can mount your Caddyfile into the Caddy container using the -v
flag or Docker Compose. For example:
docker run -d -p 80:80 -p 443:443 \ -v $(pwd)/Caddyfile:/etc/caddy/Caddyfile \ caddy
This maps your local configuration file to the container.
How do I use Caddyfile with Docker Compose?
With Docker Compose, you can define both your app and the Caddy container in a docker-compose.yml
file, mounting the Caddyfile for configuration. This simplifies management and networking between services.
Where is the Caddyfile located inside the Docker container?
By default, the Caddyfile is located at /etc/caddy/Caddyfile
inside the container. You can mount your own file to this location to override the default configuration.