Caddy 2 Reverse Proxy Server with Docker and Docker Compose Example

Posted March 23, 2024
Caddy 2 Reverse Proxy Server with Docker and Docker Compose Example

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:

Deploying Caddy Reverse Proxy to Docker

Ensure You have Docker Compose installed:

docker compose version

Deploying Caddy Reverse Proxy to Docker

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:

Deploying Caddy Reverse Proxy to Docker

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

Deploying Caddy Reverse Proxy to Docker

Next, check and ensure you have Caddy and NestJS app Docker containers ready:

sudo docker ps

How to Add Caddy Reverse Proxy to More Docker Containers

At this point, I should be able to access the application on nestjs.thriveread.site as follows:

How to Add Caddy Reverse Proxy to More Docker Containers

The application should be served with SSL/TLS over a valid HTTPS certificate:

How to Add Caddy Reverse Proxy to More Docker Containers

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:

Related : How to Install Docker and Portainer on Ubuntu

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

How to Add Caddy Reverse Proxy to More Docker Containers

Now I will be able to use https://portainer.thriveread.site and access Portainer reverse proxied by Caddy as such:

How to Add Caddy Reverse Proxy to More Docker Containers

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!

Caddy 2 Reverse Proxy Server with Docker and Docker Compose Example

Written By:

Joseph Chege