10

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
Max Block
  • 1,134
  • 3
  • 16
  • 23
  • I'm definitely not a Docker expert, so don't take my word about The Right Way, but in the `services/caddy` section, you could specify a [`command`](https://docs.docker.com/compose/compose-file/#command) option for specifying arguments to pass to the `caddy` command. – λuser May 23 '20 at 21:10

2 Answers2

8

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.

r0tt3n
  • 81
  • 2
4

@λuser was right, you can override a command option and achieve your goal:

caddy:
    image: caddy:2.4.3-alpine
    restart: unless-stopped
    command: caddy reverse-proxy --from https://my-domain.com:443 --to http://my-app:3000
    ports:
      - 80:80
      - 443:443
    volumes:
      - caddy:/data
    depends_on:
      - my-app

> I got some unclear to me errors messages
> listen tcp :80: bind: address already in use

Release port 80 and you're good to go.

limitedeternity
  • 143
  • 1
  • 6
  • 1
    Do you know if it's possible to run two reverse proxies? something like caddy reverse-proxy --from https://my-domain.com:443 --to http://my-app:3000 reverse-proxy --from https://my-domain.com:1234 --to http://my-other-app:4000 – None Oct 07 '22 at 08:16
  • @None https://caddyserver.com/docs/command-line#caddy-reverse-proxy. You'll have to use Caddyfile for that. – limitedeternity Oct 07 '22 at 10:45