How to configure Caddy 2 in docker-compose file to do reverse proxy without a bind mounted Caddyfile?

Max Block picture Max Block · May 15, 2020 · Viewed 15k times · Source

I have a docker-compose file with two services:

  • my webapp, it exposes port 3000
  • caddy, it works as reverse proxy for my web app and gives HTTPS

It works fine if I use a bind mounted Caddyfile:

caddy:
    image: caddy:2.0.0-alpine
    ports:
      - 80:80
      - 443:443
    volumes:
      - caddy:/data
      - .Caddyfile:/etc/caddy/Caddyfile

Caddy file is pretty simple:

my-domain.com {
    reverse_proxy my-app:3000
}

But I'd like to deploy it on the server without uploading Caddyfile. I want to configure my docker-compose.yml something like this:

version: "3"

services:
  my-app:
    image: my-app
    expose:
      - 3000

  caddy:
    image: caddy:2
    ports:
      - 80:80
      - 443:443
    environment:
      - reverse_proxy_from=my-app:3000
      - reverse_proxy_to=my-domain.com
    volumes:
      - caddy:/data


volumes:
  caddy:

Also maybe it's possible to do it via caddy API. When I tried to configure a reversy proxy on bare OS, it works. But when I tried to do it with docker (docker-compose exec caddy caddy reverse-proxy --from my-site.net --to my-app:3000), I got some unclear to me errors messages:

root@test:/xxx# docker-compose exec caddy caddy reverse-proxy --from my-site.net --to app:3000
2020/05/15 11:49:57.787 WARN    admin   admin endpoint disabled
2020/05/15 11:49:57.787 INFO    http    server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {"server_name": "proxy", "https_port": 443}
2020/05/15 11:49:57.787 INFO    http    enabling automatic HTTP->HTTPS redirects    {"server_name": "proxy"}
2020/05/15 11:49:57 [INFO][cache:0xc000726820] Started certificate maintenance routine
2020/05/15 11:49:57.788 INFO    tls cleaned up storage units
reverse-proxy: loading new config: http app module: start: tcp: listening on :80: listen tcp :80: bind: address already in use

Answer

r0tt3n picture r0tt3n · May 28, 2020

This might be of interest:

https://hub.docker.com/r/lucaslorentz/caddy-docker-proxy

Per the description in the github repo it references, how it works is it scans Docker metadata looking for labels indicating that the service or container should be exposed on caddy.

Then it generates an in memory Caddyfile with website entries and proxy directives pointing to each Docker service DNS name or container IP.

Every time a docker object changes, it updates the Caddyfile and triggers a caddy zero-downtime reload.