Caddy 2 Reverse Proxy Server with Docker and Docker Compose Example
Posted March 23, 2024
Caddy web server functions as a reverse proxy for your Docker containers and apps. Caddy is simple and this makes Docker Compose containers love it to add reverse proxy and Free valid HTTPS SSL certificates.
Now, Caddy configures TLS, load balancing, URL rewriting, etc. In this guide, you will learn how to set up a Caddy Reverse Proxy Server with Docker and Docker Compose. You will:
- Expose Caddy reverse proxy server with Docker.
- Add Caddy Proxy to running Docker containers.
- How to handle Caddy reverse proxy with SSL/TLS certificates.
- Managing different Docker compose apps with Caddy reverse proxy.
Ready? Dive in and setup Caddy Reverse Proxy Server with Docker and Docker Compose Example like a Pro.
Setting up Docker and Docker Compose for Caddy
You are using Caddy with Docker and Docker Compose. In your machine (I’m using Ubuntu), ensure Docker is installed and Docker compose is ready:
Docker should be running:
Ensure You have Docker Compose installed:
docker compose version
If you don’t have Docker and Compose ready, check this guide and set up Docker.
Related: How to Setup Nginx Proxy Manager with Docker Compose
Configuring Caddy with Docker
You will use Docker Compose to set up Caddy. To configure Caddy with Docker, you can create a Docker Compose file to build an image with your Caddy configuration as follows:
version: '3.9'
services:
caddy_reverse_proxy:
# Use the caddy:latest image from Docker Hub
image: caddy:latest
# Restart policy: restart the container unless explicitly stopped
restart: unless-stopped
container_name: caddy_proxy
# ports for Caddy
ports:
- 80:80
- 443:443
volumes:
# Mount the host Caddyfile
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
# Connect the Caddy container caddy_net
networks:
- caddy_net
volumes:
# persist data caddy_data
caddy_data:
# caddy_config Docker volume
caddy_config:
networks:
# Docker network for Caddy
caddy_net:
In this Compose file, you must note the following:
- Networks - the networks the container should be added to. This will create it as
caddy_net
. This network is important. Any Application that you want to use Caddy reverse proxy must be connected to the same network as Caddy. - Volumes for Caddy must be mounted into the container. They will persist Caddy server data and configurations.
- Note the ports being used. They must be available within your machine.
Building Docker Compose App for Caddy Reverse Proxy
Once Caddy is ready, you will add an application that Caddy will use to reverse proxy. Because you are using Caddy with Docker, the application must be running on Docker as well.
This way, you will be able to add the app as a container and connect to the same network as Caddy.
Let’s assume you want to use a small Next web app. You will need the image ready on a remote registry and add your app using Docker Compose as follows:
At this point, create a docker-compose.yml
file and add your application with Caddy as follows:
Note: This Docker file runs on Port 3000.
version: '3.9'
services:
caddy_reverse_proxy:
# Use the caddy:latest image from Docker Hub
image: caddy:latest
# Restart policy: restart the container unless explicitly stopped
restart: unless-stopped
container_name: caddy_proxy
# ports for Caddy
ports:
- 80:80
- 443:443
volumes:
# Mount the host Caddyfile
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
# Connect the Caddy container caddy_net
networks:
- caddy_net
nextjs_app:
# Remote Docker Hub image
image: rosechege/nextjs-app:latest
pull_policy: always
restart: always
# Connect the container to the existing Docker network caddy_net
networks:
- caddy_net
volumes:
caddy_data:
caddy_config:
networks:
caddy_net:
In this application, you must ensure Caddy and your nextjs-app are running on the same network caddy_net
. Now, you need to make sure you have a DNS record ready pointing to your remote IP address.
Here, you will add an A record for your server and use a star as the host value and thee your public IP as follows:
The reason for using star (*) is to let Caddy specify any subdomain in the Caddyfile and redirect it to any container
Creating Docker Caddyfile for Reverse Proxy
The Caddyfile is used by the Caddy webserver to define how Caddy should serve your websites. This file will include:
- Domains,
- Routes, and
- Proxying to other services.
A Caddyfile will reverse proxying which domains to listen on and how to proxy requests to Docker Compose services. In the same as your docker-compose.yml
file create Caddyfile
as follows:
{
email <add your email here>
}
<your_domainname.tld> {
reverse_proxy nextjs_app:3000
}
In this case, add:
- Your valid email
- Your domain name (it can be a subdomain as well). Here is an Example:
{
email [email protected]
}
nestjs.thriveread.site {
reverse_proxy nextjs_app:3000
}
Note the name nextjs_app:3000
. nextjs_app
is the Docker Compose service name running your web app that you want to reverse proxy to Caddy. The port 3000
is your web app port based on your Docker image.
Deploying Caddy Reverse Proxy to Docker
Once you save your Caddyfile
, go ahead and deploy your Docker Compose file using the following command. This command should run in the path of your docker-compose.yml
file:
sudo docker compose up -d
Next, check and ensure you have Caddy and NestJS app Docker containers ready:
sudo docker ps
At this point, I should be able to access the application on nestjs.thriveread.site
as follows:
The application should be served with SSL/TLS over a valid HTTPS certificate:
How to Add Caddy Reverse Proxy to More Docker Containers
What if you have multiple applications that you want to proxy using Caddy? Here is what you need to do. I will take the Portainer web service as an example. In this case, you will update your docker-compose.yml
file with the Portainer service as follows:
version: '3.9'
services:
caddy_reverse_proxy:
# Use the caddy:latest image from Docker Hub
image: caddy:latest
# Restart policy: restart the container unless explicitly stopped
restart: unless-stopped
container_name: caddy_proxy
# ports for Caddy
ports:
- 80:80
- 443:443
volumes:
# Mount the host Caddyfile
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
# Connect the Caddy container caddy_net
networks:
- caddy_net
nextjs_app:
# Remote Docker Hub image
image: rosechege/nextjs-app:latest
pull_policy: always
restart: always
# Connect the container to the existing Docker network caddy_net
networks:
- caddy_net
portainer:
image: portainer/portainer-ce:latest
restart: always
# Map port 9000
ports:
- "9000:9000"
# Add host directories to the container and persist Portainer data
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
# Add Portainer to the caddy_net network
networks:
- caddy_net
volumes:
caddy_data:
portainer_data:
caddy_config:
networks:
caddy_net:
The point here is that, Because you want to reverse Proxy Portainer with Caddy, Portainer must use the server Docker network (caddy_net
) as Caddy.
You then need to edit your Caddyfile file to include the Portainer service and its port as follows:
{
email [email protected]
}
nestjs.thriveread.site {
reverse_proxy nextjs_app:3000
}
portainer.thriveread.site {
reverse_proxy portainer:9000
}
Finally, make sure you run the Docker Compose command:
sudo docker compose up -d
Now I will be able to use https://portainer.thriveread.site
and access Portainer reverse proxied by Caddy as such:
Conclusion
Caddy is a sweet reverse proxy manager. You have used the Docker Compose file and set up a Caddy server as a reverse proxy with Docker. You’ve learned:
- How to expose the Caddy reverse proxy server with Docker.
- Adding Caddy Proxy to running Docker containers.
- How to handle Caddy reverse proxy with SSL/TLS certificates.
- Managing different Docker compose apps with Caddy reverse proxy.
I hope you found this guide helpful!