Run as non-root user in docker

1. The problem I’m having:

I am trying to run caddy as a non-root user in docker.

The problem is that the mounted volumes still have root permissions unless setup otherwise.

2. Error messages and/or full log output:

caddy   | {"level":"info","ts":1678633797.9128299,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
caddy   | {"level":"info","ts":1678633797.9287152,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Receive-Buffer-Size for details."}
caddy   | {"level":"error","ts":1678633797.9290917,"msg":"unable to autosave config","file":"/config/caddy/autosave.json","error":"open /config/caddy/autosave.json: permission denied"}

3. Caddy version:

caddy:2.6-alpine
v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

docker-compose

a. System environment:

docker 23.0.1 on x86

b. Command:

docker-compose up

or slightly easier for trying

docker run -it --rm --user 65534:65534 --read-only -v ./servers:/servers:ro -v caddy_config:/config -v caddy_date:/data -v ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro caddy:2.6-alpine

c. Service/unit/compose file:

version: '3.6'

volumes:
  caddy_config:
    external: true
  caddy_data:
    external: true

services:
  caddy:
    container_name: caddy
    image: caddy:2.6-alpine
    restart: 'unless-stopped'
    read_only: true
    user: 65534:65534
    network_mode: 'host'
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_config:/config
      - caddy_data:/data

d. My complete Caddy config:

{
	servers {
		metrics
	}
	log {
		format json
		level ERROR
	}
}

5. Links to relevant resources:

See UDP Receive Buffer Size · quic-go/quic-go Wiki · GitHub for how to resolve this one.

Maybe you could try: docker compose run caddy chown -R 65534:65534 /config /data

I just gave up on named volumes and mounted a directory - which makes the uid/gid situation much easier. Otherwise the docker image needs to support specifying the uid/gid.

It’s insane that docker doesn’t allow to specify volume mount permission and ownership details.

I think the permission error might have been because the container already existed because you ran it as root first?

Try deleting the named volumes completely and try again. Might work.

Unfortunately that’s not the problem.

It’s easy to replicate:

$ docker run --rm --user 8000:8000 -v caddy-`date +"%Y%m%dT%H%M%S"`:/foo -it caddy:2.6-alpine /bin/sh
/srv $ ls -la /foo
total 8
drwxr-xr-x    2 root     root          4096 Mar 17 23:50 .
drwxr-xr-x    1 root     root          4096 Mar 17 23:50 ..
/srv $ id
uid=8000 gid=8000 groups=8000
/srv $ touch /foo/bar
touch: /foo/bar: Permission denied

This would need some changes in the image.

I’ll just stick with directory mounts for now.