From f383b448bd140cfe7432bed3086af9e2c7806699 Mon Sep 17 00:00:00 2001 From: ElevenNotes Date: Fri, 18 Oct 2024 11:35:35 +0200 Subject: [PATCH] add switch for dropping dns records --- README.md | 56 +++++++++++++++++++++++++------- arm64v8.dockerfile | 4 +-- compose.yaml | 33 +++++++++++++++++++ hooks/post_push | 5 --- multi-arch-manifest-latest.yaml | 4 +-- multi-arch-manifest-version.yaml | 6 ++-- rootfs/labels/etc/config.yaml | 2 ++ rootfs/labels/main.js | 6 ++-- 8 files changed, 89 insertions(+), 27 deletions(-) create mode 100644 compose.yaml delete mode 100644 hooks/post_push diff --git a/README.md b/README.md index 6219f4c..f63ce93 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ ![Banner](https://github.com/11notes/defaults/blob/main/static/img/banner.png?raw=true) # 🏔️ Alpine - Traefik Labels -![size](https://img.shields.io/docker/image-size/11notes/traefik-labels/0.3.0?color=0eb305) ![version](https://img.shields.io/docker/v/11notes/traefik-labels/0.3.0?color=eb7a09) ![pulls](https://img.shields.io/docker/pulls/11notes/traefik-labels?color=2b75d6) ![activity](https://img.shields.io/github/commit-activity/m/11notes/docker-traefik-labels?color=c91cb8) ![commit-last](https://img.shields.io/github/last-commit/11notes/docker-traefik-labels?color=c91cb8) ![stars](https://img.shields.io/docker/stars/11notes/traefik-labels?color=e6a50e) +![size](https://img.shields.io/docker/image-size/11notes/traefik-labels/0.3.0?color=0eb305) ![version](https://img.shields.io/docker/v/11notes/traefik-labels/0.3.0?color=eb7a09) ![pulls](https://img.shields.io/docker/pulls/11notes/traefik-labels?color=2b75d6) + +**Export Traefik labels from any Docker node to a central location** # SYNOPSIS What can I do with this? This image will connect to all your Docker nodes and read their labels. It will then use the labels to update your Traefik configuration in Redis automatically and dynamically on each container start, stop or timeout. It also supports updating your internal and external DNS servers too, so you can use labels for everything. If a container is removed the image will automatically reverse any `nsupdate update add` to `nsupdate update delete` so entries are removed too. -In order to use this image, you need to setup Traefik with a Redis provider and then point this image via redis.url to the same Redis instance. Each entry will have an expire timer set in Redis, so that if a container is removed by a server crashing, Redis will automatically remove stale entries as well. Entries are refreshed every 300 seconds or on all docker container events (create, run, kill, stop, restart, ...). As for nsupdate, you need to setup tsig authentication in your NS servers and add the keys to the zones you want to be able to update, you can restrict the keys by using update-policy if you use BIND. +In order to use this image, you need to setup Traefik with a Redis provider and then point this image via redis.url to the same Redis instance. Each entry will have an expire timer set in Redis, so that if a container is removed by a server crashing, Redis will automatically remove stale entries as well. Entries are refreshed every 300 seconds or on all docker container events (create, run, kill, stop, restart, ...). As for nsupdate, you need to setup tsig authentication in your NS servers and add the keys to the zones you want to be able to update, you can restrict the keys by using update-policy if you use Bind from ISC. This image provides the ability to call a webhook for each container for each event or poll after the data was updates in Redis and or nsupdate. @@ -16,12 +18,41 @@ Each node gets its own worker thread for better scalability. If you have 10 node * **/labels/etc** - Directory of config.yaml * **/labels/ssl** - Directory of ssl certificates for TLS1 -# RUN -```shell -docker run --name traefik-labels \ - -v .../etc:/labels/etc \ - -v .../ssl:/labels/ssl \ - -d 11notes/traefik-labels:[tag] +# COMPOSE +```yaml +name: "traefik-labels" +services: + redis: + image: "11notes/redis:7.2.5" + container_name: "redis" + environment: + REDIS_PASSWORD: "**************" + TZ: Europe/Zurich + volumes: + - "redis.etc:/redis/etc" + - "redis.var:/redis/var" + networks: + - redis + restart: always + labels: + image: "11notes/traefik-labels:0.3.0" + container_name: "labels" + environment: + TZ: Europe/Zurich + volumes: + - "labels.etc:/labels/etc" + networks: + - redis + - nodes + restart: always +volumes: + redis.etc: + redis.var: + labels:etc: +networks: + redis: + internal: true + nodes: ``` # EXAMPLES @@ -47,6 +78,8 @@ labels: rfc2136: # only nsupdate on entries which are different (do not update same data) verify: false + # remove DNS entry if container is unreachable + remove: false poll: # polling all containers on a node every {n} seconds interval: 300 @@ -109,6 +142,9 @@ docker run --name traefik-rfc2136-demo \ | `TZ` | [Time Zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | | | `DEBUG` | Show debug information | | +# SOURCE +* [11notes/traefik-labels:0.3.0](https://github.com/11notes/docker-traefik-labels/tree/0.3.0) + # PARENT IMAGE * [11notes/node:stable](https://hub.docker.com/r/11notes/node) @@ -119,8 +155,6 @@ docker run --name traefik-rfc2136-demo \ * [alpine](https://alpinelinux.org) # TIPS -* Only use rootless container runtime (podman, rootless docker) -* Allow non-root ports < 1024 via `echo "net.ipv4.ip_unprivileged_port_start=53" > /etc/sysctl.d/ports.conf` * Use a reverse proxy like Traefik, Nginx to terminate TLS with a valid certificate * Use Let’s Encrypt certificates to protect your SSL endpoints @@ -138,5 +172,5 @@ docker run --name traefik-rfc2136-demo \ ``` # ElevenNotes™️ -This image is provided to you at your own risk. Always make backups before updating an image to a new version. Check the changelog for breaking changes. +This image is provided to you at your own risk. Always make backups before updating an image to a new version. Check the changelog for breaking changes. You can find all my repositories on [github](https://github.com/11notes). \ No newline at end of file diff --git a/arm64v8.dockerfile b/arm64v8.dockerfile index 3ac0914..93287fd 100644 --- a/arm64v8.dockerfile +++ b/arm64v8.dockerfile @@ -6,11 +6,11 @@ git; \ git clone https://github.com/11notes/util.git; -# :: Arch +# :: QEMU FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu # :: Header - FROM 11notes/node:arm64v8-stable + FROM --platform=linux/arm64 11notes/node:stable COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin ENV APP_ROOT=/labels diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..475e47f --- /dev/null +++ b/compose.yaml @@ -0,0 +1,33 @@ +name: "traefik-labels" +services: + redis: + image: "11notes/redis:7.2.5" + container_name: "redis" + environment: + REDIS_PASSWORD: "**************" + TZ: Europe/Zurich + volumes: + - "redis.etc:/redis/etc" + - "redis.var:/redis/var" + networks: + - redis + restart: always + labels: + image: "11notes/traefik-labels:0.3.0" + container_name: "labels" + environment: + TZ: Europe/Zurich + volumes: + - "labels.etc:/labels/etc" + networks: + - redis + - nodes + restart: always +volumes: + redis.etc: + redis.var: + labels:etc: +networks: + redis: + internal: true + nodes: \ No newline at end of file diff --git a/hooks/post_push b/hooks/post_push deleted file mode 100644 index fb92dee..0000000 --- a/hooks/post_push +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - curl -Lo manifest-tool https://github.com/estesp/manifest-tool/releases/download/v0.9.0/manifest-tool-linux-amd64 - chmod +x manifest-tool - ./manifest-tool push from-spec multi-arch-manifest-version.yaml - ./manifest-tool push from-spec multi-arch-manifest-latest.yaml \ No newline at end of file diff --git a/multi-arch-manifest-latest.yaml b/multi-arch-manifest-latest.yaml index 1d583e1..f0cf302 100644 --- a/multi-arch-manifest-latest.yaml +++ b/multi-arch-manifest-latest.yaml @@ -1,10 +1,10 @@ image: 11notes/traefik-labels:latest manifests: - - image: 11notes/traefik-labels:amd64-0.3.0 + - image: 11notes/traefik-labels:amd64-latest platform: architecture: amd64 os: linux - - image: 11notes/traefik-labels:arm64v8-0.3.0 + - image: 11notes/traefik-labels:arm64v8-latest platform: architecture: arm64 os: linux diff --git a/multi-arch-manifest-version.yaml b/multi-arch-manifest-version.yaml index 7f2b556..b0df03f 100644 --- a/multi-arch-manifest-version.yaml +++ b/multi-arch-manifest-version.yaml @@ -1,10 +1,10 @@ -image: 11notes/traefik-labels:0.3.0 +image: 11notes/traefik-labels:0.3.0" manifests: - - image: 11notes/traefik-labels:amd64-0.3.0 + - image: 11notes/traefik-labels:0.3.0" platform: architecture: amd64 os: linux - - image: 11notes/traefik-labels:arm64v8-0.3.0 + - image: 11notes/traefik-labels:0.3.0" platform: architecture: arm64 os: linux diff --git a/rootfs/labels/etc/config.yaml b/rootfs/labels/etc/config.yaml index c719dfb..6607e46 100644 --- a/rootfs/labels/etc/config.yaml +++ b/rootfs/labels/etc/config.yaml @@ -18,6 +18,8 @@ labels: rfc2136: # only nsupdate on entries which are different (do not update same data) verify: false + # remove DNS entry if container is unreachable + remove: false poll: # polling all containers on a node every {n} seconds interval: 300 diff --git a/rootfs/labels/main.js b/rootfs/labels/main.js index a6796fc..ae08922 100644 --- a/rootfs/labels/main.js +++ b/rootfs/labels/main.js @@ -29,7 +29,7 @@ class Labels{ this.#config.webhook.headers['Authorization'] = 'Basic ' + Buffer.from(config.webhook.auth.basic).toString('base64'); elevenLogJSON('info', `using webhook ${this.#config.webhook.url} with basic authentication`); } - this.#config.rfc2136 = {verify:(config?.rfc2136?.verify || false)}; + this.#config.rfc2136 = {verify:(config?.rfc2136?.verify || false), remove:(config?.rfc2136?.remove || false)}; this.#config.poll = {interval:(config?.poll?.interval || 300)}; this.#config.ping = {interval:(config?.ping?.interval || 2.5)}; this.#config.port = (config?.port || 2376); @@ -156,7 +156,7 @@ class Labels{ break; default: - if(!container.start){ + if(!container.start && this.#config.rfc2136.remove){ container.labels[label] = container.labels[label].replace(/update add/i, 'update delete'); } rfc2136[type].commands.push(container.labels[label]); @@ -173,8 +173,6 @@ class Labels{ await this.#webhook(container); } - elevenLogJSON('info', `[${container.worker.node}] container [${container.name}] event [${container.event}]; Traefik: add ${counter.add} / del ${counter.del}; rfc2136: WAN ${rfc2136.WAN.commands.length} / LAN ${rfc2136.LAN.commands.length}`); - }catch(e){ elevenLogJSON('error', {inspect:e.toString(), exception:e}); }