Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom entrypoint to generate the configuration #86

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ LABEL maintainer "Abiola Ibrahim <[email protected]>"

LABEL caddy_version="0.10.10"

RUN apk add --no-cache openssh-client git
RUN apk add --no-cache openssh-client git bash

# install caddy
COPY --from=builder /install/caddy /usr/bin/caddy
Expand All @@ -26,12 +26,12 @@ RUN /usr/bin/caddy -version
RUN /usr/bin/caddy -plugins

EXPOSE 80 443 2015
VOLUME /root/.caddy /srv
VOLUME /root/.caddy /srv /etc/caddy
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the config is being auto generated, having it also stored in an docker volume seems somewhat counter-intuitive. Does this provide an advantage for larger installations?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, a volume means read-write data, and the image itself should be read-only.

WORKDIR /srv

COPY Caddyfile /etc/Caddyfile
COPY index.html /srv/index.html
COPY docker-entrypoint.sh /
COPY docker-entrypoint.d /docker-entrypoint.d/

ENTRYPOINT ["/usr/bin/caddy"]
CMD ["--conf", "/etc/Caddyfile", "--log", "stdout"]

ENTRYPOINT ["/bin/bash", "/docker-entrypoint.sh"]
CMD ["/usr/bin/caddy", "--conf", "/etc/caddy/Caddyfile", "--log", "stdout"]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The readme.md has a few mentions where the main config is located in the container. But this change moves it.
The documentation should be updated to remain working with this change.

How would someone use the default config with this pull request?

48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,54 @@ Check [abiosoft/caddy:builder](https://github.com/abiosoft/caddy-docker/blob/mas

This image is built from [source code](https://github.com/mholt/caddy). As such, it is subject to the project's [Apache 2.0 license](https://github.com/mholt/caddy/blob/baf6db5b570e36ea2fee30d50f879255a5895370/LICENSE.txt), but it neither contains nor is subject to [the EULA for Caddy's official binary distributions](https://github.com/mholt/caddy/blob/545fa844bbd188c1e5bff6926e5c410e695571a0/dist/EULA.txt).

## Proxy Configuration

The configuration file `/etc/caddy/Caddyfile` is autogenerated using a simple template that lookup environment variables .

The templating supports defining multiple hostnames and multiple filters and proxies for each hostname.
Example environment variables:

```sh
CADDY_ENTRY0_HOSTNAME=foo.bar.baz
CADDY_ENTRY0_MODE=self_signed
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not read CADDY_ENTRY0_TLS_MODE?

CADDY_ENTRY0_AUTH0_PATH=/
CADDY_ENTRY0_AUTH0_USERNAME=foo
CADDY_ENTRY0_AUTH0_PASSWORD=bar
CADDY_ENTRY0_PROXY0_PATH=/
CADDY_ENTRY0_PROXY0_DEST='http://localhost:8080'
CADDY_ENTRY0_FILTER0_PATH=/
CADDY_ENTRY0_FILTER0_CONTENT_TYPE='text/html.*'
CADDY_ENTRY0_FILTER0_SEARCH_PATTERN="=\" /"
CADDY_ENTRY0_FILTER0_REPLACEMENT="=\" /mesos/"
CADDY_ENTRY0_PROXY0_WEBSOCKET=yes
CADDY_ENTRY0_PROXY0_WITHOUT="/mesos"
CADDY_ENTRY0_PROXY0_TRANSPARENT="yes"
```

Which will create the following configuration::
```
foo.bar.baz {
filter rule {
path /
content_type text/html.*
search_pattern =" /
replacement =" /mesos/
}
basicauth / foo bar
tls self_signed
log stdout
errors stderr
proxy / http://localhost:8080 {
without /mesos
websocket
transparent
}
}
```

For other definitions use `CADDY_ENTRY1` `CADDY_ENTRY2` etc and for filters and proxies you can also increment the id to have multiple definitions.

Custom configuration can be inserted using `CADDY_ENTRY0_CUSTOM0` and each line will be displayed in order at the bottom of the configuration of the hostname.

## Getting Started

Expand Down
Empty file added docker-entrypoint.d/.keep
Empty file.
1 change: 1 addition & 0 deletions docker-entrypoint.d/00-prelude.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
## This file was autogenerated by /entrypoint.sh
18 changes: 18 additions & 0 deletions docker-entrypoint.d/40-listen-points.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
offset=0
while true; do
BASEVAR="CADDY_ENTRY${offset}"
HOSTNAME="${BASEVAR}_HOSTNAME"
if [ -z ${!HOSTNAME} ]; then
break
fi
echo "${!HOSTNAME} {"
for each in $(find /docker-entrypoint.d/40-listen-points/ | sort -n); do
case $each in
*.part)
source $each
;;
esac
done
echo "}"
offset=$((offset + 1))
done
2 changes: 2 additions & 0 deletions docker-entrypoint.d/40-listen-points/00-prelude.part
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
echo " log stdout"
echo " errors stderr"
7 changes: 7 additions & 0 deletions docker-entrypoint.d/40-listen-points/20-tls.part
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
TLS_VAR=$"{BASEVAR}_TLS_MODE"
TLS="${!TLS_VAR}"
if [ -z "${TLS}" ]; then
TLS="self_signed"
fi

echo " tls $TLS"
22 changes: 22 additions & 0 deletions docker-entrypoint.d/40-listen-points/40-filter.part
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FILTER_MAXBUFFER_SIZE="${BASEVAR}_FILTER_MAXBUFFER_SIZE"
if [ ! -z "${!FILTER_MAXBUFFER_SIZE}" ]; then
echo " filter max_buffer_size ${!FILTER_MAXBUFFER_SIZE}"
fi

inneroffset=0
while true; do
FILTER_PATH="${BASEVAR}_FILTER${inneroffset}_PATH"
FILTER_CONTENT_TYPE="${BASEVAR}_FILTER${inneroffset}_CONTENT_TYPE"
FILTER_SEARCH_PATTERN="${BASEVAR}_FILTER${inneroffset}_SEARCH_PATTERN"
FILTER_REPLACEMENT="${BASEVAR}_FILTER${inneroffset}_REPLACEMENT"
if [ -z "${!FILTER_PATH}" ] || [ -z "${!FILTER_CONTENT_TYPE}" ] || [ -z "${!FILTER_SEARCH_PATTERN}" ] || [ -z "${!FILTER_REPLACEMENT}" ]; then
break
fi
echo " filter rule {"
echo " path ${!FILTER_PATH}"
echo " content_type ${!FILTER_CONTENT_TYPE}"
echo " search_pattern ${!FILTER_SEARCH_PATTERN}"
echo " replacement ${!FILTER_REPLACEMENT}"
echo " }"
inneroffset=$((inneroffset + 1))
done
11 changes: 11 additions & 0 deletions docker-entrypoint.d/40-listen-points/50-authentication.part
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
inneroffset=0
while true; do
USERNAME="${BASEVAR}_AUTH${inneroffset}_USERNAME"
HTTP_PATH="${BASEVAR}_AUTH${inneroffset}_PATH"
PASSWORD="${BASEVAR}_AUTH${inneroffset}_PASSWORD"
if [ -z "${!USERNAME}" ] || [ -z "${!HTTP_PATH}" ] || [ -z "${!PASSWORD}" ]; then
break
fi
echo " basicauth ${!HTTP_PATH} ${!USERNAME} ${!PASSWORD}"
inneroffset=$((inneroffset + 1))
done
25 changes: 25 additions & 0 deletions docker-entrypoint.d/40-listen-points/70-proxy.part
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
inneroffset=0
while true; do
PROXY_BASEVAR="${BASEVAR}_PROXY${inneroffset}"
PROXY_PATH="${PROXY_BASEVAR}_PATH"
PROXY_DEST="${PROXY_BASEVAR}_DEST"
if [ -z "${!PROXY_PATH}" ] || [ -z "${!PROXY_DEST}" ]; then
break
fi
echo " proxy ${!PROXY_PATH} ${!PROXY_DEST} {"
WITHOUT="${PROXY_BASEVAR}_WITHOUT"
if [ ! -z "${!WITHOUT}" ]; then
echo " without ${!WITHOUT}"
fi
WEBSOCKET="${PROXY_BASEVAR}_WEBSOCKET"
if [ ! -z "${!WEBSOCKET}" ]; then
echo " websocket"
fi
TRANSPARENT="${PROXY_BASEVAR}_TRANSPARENT"
if [ ! -z "${!TRANSPARENT}" ]; then
echo " transparent"
fi
echo " }"
inneroffset=$((inneroffset + 1))
done

9 changes: 9 additions & 0 deletions docker-entrypoint.d/40-listen-points/90-custom.part
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
inneroffset=0
while true; do
CUSTOM="${BASEVAR}_CUSTOM${inneroffset}"
if [ -z "${!CUSTOM}" ]; then
break
fi
echo " ${!CUSTOM}"
inneroffset=$((inneroffset + 1))
done
Empty file added docker-entrypoint.d/99-end.conf
Empty file.
15 changes: 15 additions & 0 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

rm -f /etc/caddy/Caddyfile
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this affect people using one of the recommended run commands (https://github.com/abiosoft/caddy-docker#using-local-caddyfile-and-sites-root)?
Looking this code over I would reason their config is just ignored. And an empty one generated instead.

Disabling an docker entrypoint command is somewhat awkward to do with the docker command. Perhaps an check could be added to see if the any of the env vars are present before rewriting the config.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a backward compatibility mode, enabled by default.

for each in $(find /docker-entrypoint.d/ | sort -n) ; do
case $each in
*.sh)
source "$each" >> /etc/caddy/Caddyfile
;;
*.conf)
cat "$each" >> /etc/caddy/Caddyfile
;;
esac
done

exec $@