Skip to content

Commit

Permalink
Merge pull request #2 from humenius/feature/container-restart
Browse files Browse the repository at this point in the history
Add container restart functionality
  • Loading branch information
kereis authored Mar 21, 2020
2 parents 6653c78 + 1247437 commit 58d020b
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 16 deletions.
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
FROM ldez/traefik-certs-dumper
FROM docker:19.03.8
LABEL maintainer="Humenius <[email protected]>"

RUN apk --no-cache add inotify-tools util-linux bash

COPY run.sh /

RUN ["chmod", "+x", "/run.sh"]

COPY --from=ldez/traefik-certs-dumper:v2.7.0 /usr/bin/traefik-certs-dumper /usr/bin/traefik-certs-dumper

VOLUME ["/traefik"]
VOLUME ["/output"]

Expand Down
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,48 @@
# traefik-certs-dumper

[![Docker Layers](https://images.microbadger.com/badges/image/humenius/traefik-certs-dumper.svg)](https://hub.docker.com/r/humenius/traefik-certs-dumper)
[![Docker Image Latest Version](https://images.microbadger.com/badges/version/humenius/traefik-certs-dumper:1.1.svg)](https://hub.docker.com/r/humenius/traefik-certs-dumper)

Dumps Let's Encrypt certificates of a specified domain to `.pem` and `.key` files which Traefik stores in `acme.json`.

This images derrivates from [mailu/traefik-certdumper](https://hub.docker.com/r/mailu/traefik-certdumper). Special thanks to them!
This image uses:
- a bash script that derrivates from [mailu/traefik-certdumper](https://hub.docker.com/r/mailu/traefik-certdumper)
- [ldez's traefik-certs-dumper](https://github.com/ldez/traefik-certs-dumper)
Special thanks to them!

**IMPORTANT**: It's supposed to work with Traefik **v2** or higher! If you want to use this certificate dumper with **v1**, you can simply change the image to [mailu/traefik-certdumper](https://hub.docker.com/r/mailu/traefik-certdumper).

## Usage
### Basic setup
Mount your ACME folder into `/traefik` and output folder to `/output`. Here's an example for docker-compose:
```yaml
version: '3.7'

services:
certdumper:
image: humenius/traefik-certs-dumper
image: humenius/traefik-certs-dumper:latest
container_name: traefik_certdumper
volumes:
- ./traefik/acme:/traefik:ro
- ./output:/output:rw
environment:
- DOMAIN=example.org
```
### Automatic container restart
If you want to have containers restarted after dumping certificates into your output folder, you can specify their names as comma-separated value and pass them through via optional parameter `-r | --restart-containers`. In this case, you must pass the Docker socket (or override `$DOCKER_HOST` if you use a Docker socket proxy). For instance:
```yaml
version: '3.7'
services:
certdumper:
image: humenius/traefik-certs-dumper:latest
container_name: traefik_certdumper
command: --restart-containers container1,container2,container3
volumes:
- ./traefik/acme:/traefik:ro
- ./output:/output:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- DOMAIN=example.org
```
Expand Down
148 changes: 135 additions & 13 deletions run.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,25 +1,147 @@
#!/bin/bash

function dump() {
echo "$(date) Dumping certificates"
WORKDIR=/tmp/work/

traefik-certs-dumper file --version v2 --crt-name "cert" --crt-ext ".pem" --key-name "key" --key-ext ".pem" --domain-subdir --dest /tmp/work --source /traefik/acme.json > /dev/null
###############################################
#### DUMPING LOGIC ####
###############################################

if [[ -f /tmp/work/${DOMAIN}/cert.pem && -f /tmp/work/${DOMAIN}/key.pem && -f /output/cert.pem && -f /output/key.pem ]] && \
diff -q /tmp/work/${DOMAIN}/cert.pem /output/cert.pem >/dev/null && \
diff -q /tmp/work/${DOMAIN}/key.pem /output/key.pem >/dev/null ; \
then
echo "$(date) Certificate and key still up to date, doing nothing"
dump() {
log "Clearing dumping directory"
rm -rf $WORKDIR/*

log "Dumping certificates"
traefik-certs-dumper file --version v2 --crt-name "cert" --crt-ext ".pem" --key-name "key" --key-ext ".pem" --domain-subdir --dest /tmp/work --source /traefik/acme.json >/dev/null

if
[[ -f /tmp/work/${DOMAIN}/cert.pem && -f /tmp/work/${DOMAIN}/key.pem && -f /output/cert.pem && -f /output/key.pem ]] && \
diff -q ${WORKDIR}/${DOMAIN}/cert.pem /output/cert.pem >/dev/null && \
diff -q ${WORKDIR}/${DOMAIN}/key.pem /output/key.pem >/dev/null
then
log "Certificate and key still up to date, doing nothing"
else
log "Certificate or key differ, updating"
mv ${WORKDIR}/${DOMAIN}/*.pem /output/

if [ ! -z "${CONTAINERS#}" ]; then
log "Trying to restart containers"
restart_containers
fi
fi
}

restart_containers() {
for i in "${CONTAINERS[@]}"; do
log "Looking up container with name ${i}"

local found_container=$(docker ps -qaf name="${i}")
if [ ! -z "${found_container}" ]; then
log "Found '${found_container}'. Restarting now..."

docker restart ${found_container}

if [ $? -eq 0 ]; then
log "Restarting container '${found_container}' was successful"
else
err "
Something went wrong while restarting '${found_container}'
Please check health of containers and consider restarting them manually.
"
fi
else
echo "$(date) Certificate or key differ, updating"
mv /tmp/work/${DOMAIN}/*.pem /output/
err "Container '${i}' could not be found. Omitting container..."
fi
done

log "Container restarting process done."
}

err() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}

mkdir -p /tmp/work
log() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*"
}

###############################################
#### COMMAND LINE ARGS PARSING ####
###############################################

die() {
local _ret=$2
test -n "$_ret" || _ret=1
test "$_PRINT_HELP" = yes && print_help >&2
echo "$1" >&2
exit ${_ret}
}

begins_with_short_option() {
local first_option all_short_options='rh'
first_option="${1:0:1}"
test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}

_arg_restart_containers=

print_help() {
printf '%s\n' "traefik-certs-dumper bash script by Humenius <[email protected]>"
printf 'Usage: %s [-r|--restart-containers <arg>] [-h|--help]\n' "$0"
printf '\t%s\n' "-r, --restart-containers: Restart containers passed as comma-separated container names (no default)"
printf '\t%s\n' "-h, --help: Prints help"
}

parse_commandline() {
while test $# -gt 0; do
_key="$1"
case "$_key" in
-r | --restart-containers)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_restart_containers="$2"
shift
;;
--restart-containers=*)
_arg_restart_containers="${_key##--restart-containers=}"
;;
-r*)
_arg_restart_containers="${_key##-r}"
;;
-h | --help)
print_help
exit 0
;;
-h*)
print_help
exit 0
;;
*)
_PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
;;
esac
shift
done
}

split_list() {
IFS=',' read -ra CONTAINERS <<<"$1"
log "Values split! Got '${CONTAINERS[@]}'"
}

###############################################

parse_commandline "$@"

if [ -z "${_arg_restart_containers}" ]; then
log "--restart-containers is empty. Won't restart containers."
else
log "Got value of --restart-containers: ${_arg_restart_containers}. Splitting values."
split_list "${_arg_restart_containers}"
fi

mkdir -p ${WORKDIR}
dump

while true; do
inotifywait -qq -e modify /traefik/acme.json
dump
inotifywait -qq -e modify /traefik/acme.json
dump
done

0 comments on commit 58d020b

Please sign in to comment.