Help w/ Caddy's "Getting Started" - it lacks info for docker-user newbies

1. The problem I’m having:

The instructions in Caddy’s “Getting Started” page don’t include info for when I’m running Caddy as a Docker container. My first dilemma of many is this: any step involving a curl command doesn’t work because my Caddy container doesn’t include curl.
I suppose I could just work through the whole “Getting Started” page without using those curl commands, but my goal is to set up Caddy as a reverse proxy for my li’l home server. Initially, I tried several unofficial blog posts to reach this goal, but after they didn’t work, I decided to use the official documentation. (I know, smart idea, right? :slight_smile: ) Since I’m trying to do things systematically – both to get things working and to learn – I’m finding that the documentation, although extremely friendly, assumes some knowledge that I don’t yet have, and I’ve been unable to figure it out by Googling.
Thanks!!

2. Error messages and/or full log output:

geoff@sterver:~$ docker exec -it caddy sh
/srv # curl localhost:2019/config/
sh: curl: not found
/srv # exit
geoff@sterver:~$ curl localhost:2019/config/
curl: (7) Failed to connect to localhost port 2019: Connection refused
geoff@sterver:~$ curl 192.168.50.69:2019/config/
curl: (7) Failed to connect to 192.168.50.69 port 2019: Connection refused
geoff@sterver:~$ curl sterver.local:2019/config/
curl: (7) Failed to connect to sterver.local port 2019: Connection refused


3. Caddy version:

Moreover, the commands in this help-request template say how to check the caddy version, but it’s not working for me:

geoff@sterver:~$ docker exec -it caddy sh
/srv # docker-compose exec caddy caddy version
sh: docker-compose: not found
/srv # exit
geoff@sterver:~$ docker-compose exec caddy caddy version
no configuration file provided: not found

However, as you’ll see in my docker-compose file below, I ought to be running the latest version of caddy.

4. How I installed and ran Caddy:

a. System environment:

OS: Open Media Vault – more specifically…
Operating System: Debian GNU/Linux 11 (bullseye)
Kernel: Linux 6.1.0-0.deb11.21-amd64
Architecture: x86-64

Docker version 27.4.1, build b9d17ea
Docker Compose version v2.32.1

b. Command:

caddy start

c. Service/unit/compose file:

version: '3.9'
services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      #- "443:443/udp"
    networks:
      - caddy_net
    volumes:
      - /srv/dev-disk-by-uuid-9ccb815e-8ccb-4577-b698-1cd0f335afb0/appdata/caddy/Caddyfile:/etc/caddy/Caddyfile
      #- /srv/dev-disk-by-uuid-9ccb815e-8ccb-4577-b698-1cd0f335afb0/appdata/caddy/site:/srv
      - /srv/dev-disk-by-uuid-9ccb815e-8ccb-4577-b698-1cd0f335afb0/appdata/caddy/caddy_data:/data
      - /srv/dev-disk-by-uuid-9ccb815e-8ccb-4577-b698-1cd0f335afb0/appdata/caddy/caddy_config:/config

volumes:
  caddy_data:
  caddy_config:

networks:
  # Docker network for Caddy
  caddy_net:

d. My complete Caddy config:

:2015

respond "Hello, world!"

# Caddyfile
#{
#       email gstanbury@[xxxxx].com
#}
#
#http://navidrome.local {
#    reverse_proxy 192.168.50.69:4533
#}

5. Links to relevant resources:

Yeah, it’s a known gap in our tutorial/getting started.

The best place to start for Docker usage is here:

Two things went wrong here.

You got a shell inside the container, but then you tried to run a docker-compose command inside the container. That doesn’t make sense, docker-compose is a tool that you run on your host, outside the containers, to help you manage your containers.

Then you ran docker-compose outside, but I think you didn’t run it in the same location as your docker-compose.yml file exists, so docker-compose is saying “I can’t find a config to use”.

Here, again two things went wrong. You tried to run curl inside the container, but curl isn’t installed in the container. You could install it with apk add curl if you wanted, then curl localhost:2019/config/ would work, when run inside the container.

But afterwards you tried to do curl outside, which will not work, because port 2019 is not exposed outside the container, and Caddy only listens for localhost:2019 by default, i.e. only connections from inside the container. This is Caddy’s admin API endpoint, so it’s best to keep it protected.

You could change the admin endpoint in the initial config you load, e.g. 0.0.0.0:2019 then add a port mapping on your container, then it would be accessible outside. But that’s risky, and not recommended unless you know that the port won’t be accessible publicly (if it’s publicly accessible, any attacker could change your server config and do bad things).

You’re better off just using the Caddyfile, and not using the admin API at all, especially for beginners.

Thanks for your helpful response. Here’s where I am now after working through your feedback…

Makes sense. I located the docker-compose.yml file that Open Media Vault generates (it does things its own, nonstandard way, naturally) and reran the docker-compose command to check my caddy version. Things look strange–is this how it ought to be?

dockeruser@sterver:/srv/dev-disk-by-uuid-9ccb815e-8ccb-4577-b698-1cd0f335afb0/home/geoff/docker-compose-files/caddy$ docker-compose exec caddy caddy version
WARN[0000] /srv/dev-disk-by-uuid-9ccb815e-8ccb-4577-b698-1cd0f335afb0/home/geoff/docker-compose-files/caddy/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
v2.8.4 h1:xxxxxxxx <-- a long string of random characters that maybe should be kept private(?)

Moving on…

Makes sense. I followed your command to add curl, then I tried that curl command from “Getting Started.” It gave me a “null” output, which seems problematic. (Is it?)

geoff@sterver:~/docker-compose-files$ docker exec -it caddy sh
/srv # apk add curl
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/x86_64/APKINDEX.tar.gz
(1/9) Installing brotli-libs (1.1.0-r2)
(2/9) Installing c-ares (1.33.1-r0)
(3/9) Installing libunistring (1.2-r0)
(4/9) Installing libidn2 (2.3.7-r0)
(5/9) Installing nghttp2-libs (1.62.1-r0)
(6/9) Installing libpsl (0.21.5-r1)
(7/9) Installing zstd-libs (1.5.6-r0)
(8/9) Installing libcurl (8.11.1-r0)
(9/9) Installing curl (8.11.1-r0)
Executing busybox-1.36.1-r29.trigger
OK: 13 MiB in 30 packages
/srv # curl localhost:2019/config/
null

Could you please clarify what you mean by “the admin API”? Does that mean that the instructions in the “Getting Started” page guide people through using the admin API? Or do you mean something else? (I imagine that this question stems from my overlooking something in the documentation… thanks for your patience.)