Getting Caddy to work with docker compose

Ok, full noob problems following. I’m new at Linux, Docker AND Caddy, so what could go wrong? Thanks in advance for your patience!

1. The problem I’m having:

Getting Caddy off the ground after installing it with docker compose.
Caddyfile and changes therein seem to be ignored.
Also commands like caddy --watch are getting error messages.
Navigating to the ip address shows the “caddy works” page.

2. Error messages and/or full log output:

After entering caddy run --watch
I get the error Command 'caddy' not found, but can be installed with: sudo apt install caddy

3. Caddy version:

2.9-alpine

4. How I installed and ran Caddy:

a. System environment:

OS: Linux Mint 22 x86_64
Kernel: 6.8.0-49-generic
Docker version 27.3.1, build ce12230
Docker Compose version v2.29.7

b. Command:

docker compose up -d

c. Service/unit/compose file:

services:
  caddy:
    image: caddy:2.9-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/opt/caddy/Caddyfile
      - ./site:/srv
      - caddy_data:/data
      - caddy_config:/config

volumes:
  caddy_data:
  caddy_config:

d. My complete Caddy config:

localhost {
    respond "Hello World!"
}

5. Links to relevant resources:

Change where you’re mounting the Caddyfile:

      - ./Caddyfile:/etc/caddy/Caddyfile

I changed the compose.yml accordingly and copied the Caddyfile to said directory (btw: what is wrong with mounting the Caddyfile under /opt/caddy/ - that’s where the docker compose lives as well!?).

I ran the command docker compose down followed by sudo docker compose up -d to be sure the configuration is as changed, but now I’m getting another error and I can’t even reach the “Caddy works” site anymore…

docker compose up -d
[+] Running 1/2
 ✔ Network caddy_default    Created
                                                                                                   0.1s
 ⠼ Container caddy-caddy-1  Starting
                                                                                                   0.3s
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/opt/caddy/Caddyfile" to rootfs at "/etc/caddy/Caddyfile": create mountpoint for /etc/caddy/Caddyfile mount: cannot create subdirectories in "/var/lib/docker/overlay2/f943ef9380499c47ddd7262e634a8935d9cfe64a43c4c549db070e1a64234216/merged/etc/caddy/Caddyfile": not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type

My suggestion was wrong, I guess.

In my docker-compose caddy setups, I have Caddyfile mounted into /etc/caddy/

What do you mean that’s where the docker compose lives as well?

I mean I created and started caddy in the directory /opt/caddy/ so the compose.yml is saved under /opt/caddy/compose.yml and the corresponding Caddyfile was saaved under /opt/caddy/Caddyfile (now moved to /etc/caddy/Caddyfile).

Edit: Ok, I started from scratch and put everything back in /opt/caddy/ and I can acces the “Caddy working” page, but everything else doesn’t seem to work.

Maybe you’re not clear about where the container started by Docker Compose is expecting its files to be. You’re seeing the “Caddy working” page because that’s created by the default configs.

Read this: https://hub.docker.com/_/caddy

Specifically:

To override the default Caddyfile⁠, you can create one in the subfolder conf at $PWD/conf/Caddyfile and mount this folder at /etc/caddy:

$ docker run -d -p 80:80 \
    -v $PWD/conf:/etc/caddy \
    -v caddy_data:/data \
    caddy
⚠️ Do not mount the Caddyfile directly at /etc/caddy/Caddyfile

Your Caddyfile is showing up in the container at /opt/caddy/Caddyfile - and the caddy process, in the container, is looking at its own /etc/caddy/Caddyfile.

So my first suggestion was incorrect, but what you want to do is to set up a conf/ directory where you store the Caddyfile, and mount that into /etc/caddy so if you change the file, caddy will autmaticaly pick it up.

To verify what I’m saying, you can use:

docker compose exec caddy /bin/sh

to run a shell in the caddy container and look around. There will likely be an /etc/caddy/Caddyfile and also an /opt/caddy/Caddyfile there.

Ok, I changed the compose.yml to (after reading a bit more I changed the image to 2.9 (non-alpine):

services:
  caddy:
    image: caddy:2.9
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - $PWD/conf:/etc/caddy
      - $PWD/site:/srv
      - caddy_data:/data
      - caddy_config:/config

volumes:
  caddy_data:
  caddy_config:

networks:
  default:
    name: caddy_net
    external: true

and the Caddyfile (in /opt/caddy/conf/) reads:

localhost {
    respond "Hello World!"
}

But starting the container back up I get the warning WARN[0000] The "PWD" variable is not set. Defaulting to a blank string. and caddy has a status Restarting (1) for 10 minutes.
I thought $PWD is set automatically. :man_shrugging:

PWD would not be set automatically, but you can always do something like this in your Docker compose file:

environment:
      - PWD=${PWD}

Or you could simplify things and just remove the $PWD/ altogether, as it’s kind of redundant. (or replace it with “./”)

You can’t run caddy commands on your host machine if you’re running Caddy inside Docker. You don’t have Caddy outside of the container.

If you ran the container, then Caddy is running, no need to run caddy run by hand. If you need to reload your config, run the command found in the docs: Keep Caddy Running — Caddy Documentation