caddyserver / caddy-docker

Source for the official Caddy v2 Docker Image
https://hub.docker.com/_/caddy
Apache License 2.0
427 stars 75 forks source link

Using caddy as entrypoint #72

Open ebati opened 4 years ago

ebati commented 4 years ago

You can use caddy command as ENTRYPOINT and give default options in CMD that would simplify running with other options and also remove duplicate caddy (one for image name one for executable name) in examples.

hairyhenderson commented 4 years ago

@ebati you are correct. Is this a request to do that, or is there a use-case that you need to enable with this?

Setting ENTRYPOINTs can be a bit tricky to deal with unless there's a good entrypoint script written to handle all the different ways an image could be called. It's important (especially in an official image) that users be able to just do something like docker run caddy /bin/sh to troubleshoot or explore.

I did have an entrypoint script at some point (in #8, though some of the history is lost), but there were some difficulties in getting it to work with all cases. We discussed the specifics and for now it seemed a fair tradeoff to just accept the repetition of the word caddy in the command 😉

That being said, I wouldn't be opposed to accepting a PR that includes a well-written entrypoint script that:

mholt commented 4 years ago

I'm not super inclined to change the command package to accommodate a niche use case at this point, but if there's a compelling reason to, we can definitely consider it as long as it's backwards-compatible.

(this'd probably need some changes to the caddy command itself to be able to report what subcommands it supports)

caddy help
francislavoie commented 4 years ago

I think it would be reasonably simple to have a caddy help --commands that spits out a (tab?) delimited list of the supported commands (to make scripting easier)

mholt commented 4 years ago

Probably newline-delimited. Does it need the command descriptions too?

francislavoie commented 4 years ago

IMO no, we only need to know the words that need to be allowed to pass through to the caddy command, and anything else gets executed as-is in the container. Anything extra would just make it a bit more tedious to parse (not really that hard, bash is powerful, but simplicity is ideal here IMO)

hairyhenderson commented 4 years ago

So @francislavoie and I are chatting about this in Slack and it may be possible to accomplish this in a way similar to how traefik does it.

Basically it depends on caddy <subcommand> --help exiting with a different code depending on whether the subcommand is valid or not.

In Caddy's case, we get a 2 when help is printed, so it'd require a slightly different script. But I think it's probably worth it...

Note that it does involve slightly more execution time though. 🤷‍♂️

ebati commented 4 years ago

I must be missing some point but ...

Can't we just give caddy command as ENTRYPOINT ["caddy"] and add CMD ["run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"] (which are the current default parameters). If someone wants to run any other command they need to change entrypoint by docker run --entrypoint /bin/sh caddy. If they want to change options they can give the arguments, for example to get the help message docker run caddy help

By the way, I don't want to waste your time, if this requires a complex script, we can just close this issue as this is not something important. 😄

francislavoie commented 4 years ago

Having to override the entrypoint like that isn't as nice I'd say.

ebati commented 4 years ago

You are right, use case with override is not nice. But I think most people will use this image without changing entrypoint, as this is a single purpose image.

hairyhenderson commented 4 years ago

By the way, I don't want to waste your time, if this requires a complex script, we can just close this issue as this is not something important. 😄

This absolutely isn't a waste of time! While it might seem like it's not very important, you're not the only one to want this, so it is IMO worth exploring.

But I think most people will use this image without changing entrypoint, as this is a single purpose image.

It's important that we support a better user experience with this image, since it's an official Docker image. It needs to behave similarly to other official images, which quite often have entrypoint scripts.

And regardless of those reasons, the current image behaves a certain way, and I think it's most crucial that we not break current users.

serverwentdown commented 4 years ago

Official reference: https://github.com/docker-library/official-images#consistency

hairyhenderson commented 4 years ago

Thanks for the link @serverwentdown

rugk commented 3 years ago

Official reference: https://github.com/docker-library/official-images#consistency

So if I read that correctly, this supports the argument that ENTRYPOINT should be used, should not it?

serverwentdown commented 3 years ago

@rugk I would say that by Docker recommendations, the caddy docker image ships with a shell and therefore the entrypoint shouldn't be caddy (point 3).

And since no initialisation is necessary before running caddy in the caddy docker image, an entrypoint script is not very necessary (point 2).

So I'd think better to keep it simple with no :sparkles:magic:sparkles: entrypoint involved.

But, traefik's entrypoint is a neat solution!

rugk commented 3 years ago

Oh yeah, you're right, then it is indeed "If the startup process does not need arguments" (point 1) and the thing is fine as it is…

I wodner what exactly the use case of the OP was here. Even with CMD you should be able to run caddy as docker run official-image --arg1 --arg2 (as the guide says), so what is the actual problem here, …?


Ah also looking at traefik now again and yeah, that's sleek…

serverwentdown commented 3 years ago

@rugk At the moment, unlike traefik and some other images, to run caddy requires including caddy as the first argument as in docker run caddy:latest caddy file-server, which might be a little repetitive, when compared to docker run caddy:latest file-server

isujtauke commented 1 year ago

This issue feels related to something I'm running into.

I'm having trouble passing --envfile to caddy using this docker image.

It seems no matter what I do, specifying a command: in a docker compose file leads to an error. Is this supposed to be possible?

Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "caddy run --config /etc/caddy/Caddyfile --adapter caddyfile --envfile /run/secrets/acme_secret": stat caddy run --config /etc/caddy/Caddyfile --adapter caddyfile --envfile /run/secrets/acme_secret: no such file or directory: unknown

  caddy:
    image: caddy:2.6.4
    container_name: caddy
    ports:
      - "443:443"
    volumes:
      - ./caddy:/etc/caddy
      - caddy_data:/data
      - caddy_config:/config
    command:
      - 'caddy run --config /etc/caddy/Caddyfile --adapter caddyfile --envfile /run/secrets/acme_secret'
    restart: unless-stopped
    networks:
      - monitor-net
    labels:
      org.label-schema.group: "monitoring"
    secrets:
      - acme_secret
francislavoie commented 1 year ago

@isujtauke you need to specify the full path to the binary, i.e. /usr/bin/caddy. That's not related to this issue. Please ask your usage questions on the forums https://caddy.community

dimkasta commented 1 year ago

For what it's worth, one can go beyond just an entrypoint. I was playing with a multistage Dockerfile and on the last stage I tried this

FROM scratch as mini
ENV XDG_CONFIG_HOME /config
ENV XDG_DATA_HOME /data

COPY --from=dev /usr/local/bin/caddy /

EXPOSE 80 443 443/udp 2019
ENTRYPOINT ["/caddy"]

CMD ["run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]

Which ended up in a nice small 40MB image. You just have to attach all the directories in your dockerfile

So far I have no issues with it on my caddy/php-fpm/mariadb stack. Perhaps this is nice for an extra tag/image for those that want an absolutely minimal option.

There is no bash, and commands seem to work ok but are not executed in the context of the running container. caddy stop does close the process through

docker exec -it proxy caddy reload --config /etc/caddy/Caddyfile
francislavoie commented 1 year ago

@dimkasta you're missing mailcap (for Content-Type header for file server) and ca-certificates (necessary to connect to servers like ACME issuers, or proxy to upstreams with HTTPS). That's the main reason for not using scratch. And also it makes debugging harder if you ever need a shell to play around.

dimkasta commented 1 year ago

For debugging all you have to do is change the target of your compose to the full image or dev on the multistage Dockerfile. You can even target an image with go and xcaddy installed.

For ca-certificates and mailcap, thanks for letting me know. I am not familiar with the code base and thought the binary had all it needed statically compiled.

francislavoie commented 1 year ago

The program has no dynamically linked libraries, but it does load additional system-shipped files that are best maintained externally (CA cert bundles are kinda large for example).