From 45c818673272eaa8958d50ace5cf2c901d8f72dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CF=BA=CE=9BD=D0=98VTT=CE=9BH?= Date: Wed, 14 Feb 2024 09:46:04 +0100 Subject: [PATCH] Build Unbound Image The UID and GID can be overridden by setting environment variables in your docker-compose file or shell. Thanks to @kernbug for suggesting. Check the examples (https://github.com/madnuttah/unbound-docker/tree/main/doc/examples) to lean how this works. You need to remove the username in your unbound.conf like so `username=""` or there will be warnings in your log. AWK and SED has been added to the image (needed for statistics via healthcheck), ash has been removed --- .github/workflows/build-openssl-buildenv.yaml | 302 ------------------ .github/workflows/build-unbound.yaml | 2 +- README.md | 6 +- doc/DETAILS.md | 3 +- doc/examples/docker-compose.yaml-bridge | 3 + doc/examples/docker-compose.yaml-macvlan | 3 + doc/examples/usr/local/unbound/unbound.conf | 6 +- unbound/Dockerfile | 36 ++- unbound/root/usr/local/unbound/unbound.conf | 2 +- 9 files changed, 38 insertions(+), 325 deletions(-) delete mode 100644 .github/workflows/build-openssl-buildenv.yaml diff --git a/.github/workflows/build-openssl-buildenv.yaml b/.github/workflows/build-openssl-buildenv.yaml deleted file mode 100644 index 4debbed..0000000 --- a/.github/workflows/build-openssl-buildenv.yaml +++ /dev/null @@ -1,302 +0,0 @@ -name: Build OpenSSL Build Environment - -on: - push: - branches: [ main ] - paths: - - '!**' - - '.github/workflows/build-openssl-buildenv.yaml' - -env: - DOCKERHUB_SLUG: "madnuttah/unbound" - VERSION: "3.2.1-1" - -jobs: - linux_x86: - runs-on: ubuntu-latest - steps: - - uses: step-security/harden-runner@v2 - with: - egress-policy: block - disable-telemetry: true - allowed-endpoints: - dl-cdn.alpinelinux.org:443 - github.com:443 - docker.io - index.docker.io - auth.docker.io:443 - registry-1.docker.io:443 - production.cloudflare.docker.com:443 - objects.githubusercontent.com:443 - keys.openpgp.org:443 - keyserver.ubuntu.com:443 - pipelines.actions.githubusercontent.com:443 - www.openssl.org:443 - - - name: Checkout source - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Dockerhub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: linux_x86 - uses: docker/build-push-action@v5 - with: - platforms: linux/386 - builder: ${{ steps.buildx.outputs.name }} - file: ./openssl/linux_x86.Dockerfile - push: ${{ github.event_name != 'pull_request' }} - provenance: false - tags: | - ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-386 - - linux_arm_v6: - runs-on: ubuntu-latest - steps: - - uses: step-security/harden-runner@v2 - with: - egress-policy: block - disable-telemetry: true - allowed-endpoints: - dl-cdn.alpinelinux.org:443 - github.com:443 - docker.io - index.docker.io - auth.docker.io:443 - registry-1.docker.io:443 - production.cloudflare.docker.com:443 - objects.githubusercontent.com:443 - keys.openpgp.org:443 - keyserver.ubuntu.com:443 - pipelines.actions.githubusercontent.com:443 - www.openssl.org:443 - - - name: Checkout source - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Dockerhub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: linux_arm_v6 - uses: docker/build-push-action@v5 - with: - platforms: linux/arm/v6 - builder: ${{ steps.buildx.outputs.name }} - file: ./openssl/linux_arm.Dockerfile - push: ${{ github.event_name != 'pull_request' }} - provenance: false - tags: | - ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-armv6 - - linux_arm_v7: - runs-on: ubuntu-latest - steps: - - uses: step-security/harden-runner@v2 - with: - egress-policy: block - disable-telemetry: true - allowed-endpoints: - dl-cdn.alpinelinux.org:443 - github.com:443 - docker.io - index.docker.io - auth.docker.io:443 - registry-1.docker.io:443 - production.cloudflare.docker.com:443 - objects.githubusercontent.com:443 - keys.openpgp.org:443 - keyserver.ubuntu.com:443 - pipelines.actions.githubusercontent.com:443 - www.openssl.org:443 - - - name: Checkout source - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Dockerhub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: linux_arm_v7 - uses: docker/build-push-action@v5 - with: - platforms: linux/arm/v7 - builder: ${{ steps.buildx.outputs.name }} - file: ./openssl/linux_arm.Dockerfile - push: ${{ github.event_name != 'pull_request' }} - provenance: false - tags: | - ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-armv7 - - linux_arm64: - runs-on: ubuntu-latest - steps: - - uses: step-security/harden-runner@v2 - with: - egress-policy: block - disable-telemetry: true - allowed-endpoints: - dl-cdn.alpinelinux.org:443 - github.com:443 - docker.io - index.docker.io - auth.docker.io:443 - registry-1.docker.io:443 - production.cloudflare.docker.com:443 - objects.githubusercontent.com:443 - keys.openpgp.org:443 - keyserver.ubuntu.com:443 - pipelines.actions.githubusercontent.com:443 - www.openssl.org:443 - - - name: Checkout source - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Dockerhub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: linux_arm64 - uses: docker/build-push-action@v5 - with: - platforms: linux/arm64 - builder: ${{ steps.buildx.outputs.name }} - file: ./openssl/linux_64.Dockerfile - push: ${{ github.event_name != 'pull_request' }} - provenance: false - tags: | - ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-arm64 - - linux_amd64: - runs-on: ubuntu-latest - steps: - - uses: step-security/harden-runner@v2 - with: - egress-policy: block - disable-telemetry: true - allowed-endpoints: - dl-cdn.alpinelinux.org:443 - github.com:443 - docker.io - index.docker.io - auth.docker.io:443 - registry-1.docker.io:443 - production.cloudflare.docker.com:443 - objects.githubusercontent.com:443 - keys.openpgp.org:443 - keyserver.ubuntu.com:443 - pipelines.actions.githubusercontent.com:443 - www.openssl.org:443 - - - name: Checkout source - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Dockerhub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: linux_amd64 - uses: docker/build-push-action@v5 - with: - platforms: linux/amd64 - builder: ${{ steps.buildx.outputs.name }} - file: ./openssl/linux_64.Dockerfile - push: ${{ github.event_name != 'pull_request' }} - provenance: false - tags: | - ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-amd64 - - create-manifest-list: - runs-on: ubuntu-latest - needs: - - linux_x86 - - linux_arm_v6 - - linux_arm_v7 - - linux_arm64 - - linux_amd64 - steps: - - uses: step-security/harden-runner@v2 - with: - egress-policy: block - disable-telemetry: true - allowed-endpoints: - github.com:443 - docker.io - index.docker.io - auth.docker.io:443 - registry-1.docker.io:443 - production.cloudflare.docker.com:443 - objects.githubusercontent.com:443 - pipelines.actions.githubusercontent.com:443 - - - name: Checkout source - uses: actions/checkout@v4 - - - name: Login to Dockerhub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Create and push multiarch manifests - if: github.event_name != 'pull_request' - run: | - docker manifest create ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }} \ - --amend ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-386 \ - --amend ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-arm64 \ - --amend ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-amd64 \ - --amend ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-armv6 \ - --amend ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }}-armv7 - docker manifest push ${{ env.DOCKERHUB_SLUG }}:openssl-buildenv-${{ env.VERSION }} diff --git a/.github/workflows/build-unbound.yaml b/.github/workflows/build-unbound.yaml index 5265512..a17b1ec 100644 --- a/.github/workflows/build-unbound.yaml +++ b/.github/workflows/build-unbound.yaml @@ -9,7 +9,7 @@ on: env: DOCKERHUB_SLUG: "madnuttah/unbound" - VERSION: "1.19.1-0" + VERSION: "1.19.1-1" jobs: build: diff --git a/README.md b/README.md index 7db83c9..a5cce30 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,8 @@ [![GitHub version](https://img.shields.io/github/v/release/madnuttah/unbound-docker?include_prereleases&style=flat-square)](https://github.com/madnuttah/unbound-docker/releases) [![Build Multiarch Unbound Docker Image](https://img.shields.io/github/actions/workflow/status/madnuttah/unbound-docker/build-unbound.yaml?branch=main&label=Unbound%20build%20status&style=flat-square)](https://github.com/madnuttah/unbound-docker/actions/workflows/build-unbound.yaml) -[![Build Multiarch OpenSSL BuildEnv Docker Image](https://img.shields.io/github/actions/workflow/status/madnuttah/unbound-docker/build-openssl-buildenv.yaml?branch=main&label=OpenSSL%20build%20status&style=flat-square)](https://github.com/madnuttah/unbound-docker/actions/workflows/build-openssl-buildenv.yaml) -This is an actively maintained and trustworthy, lightweight Alpine Linux based Docker image that runs [Unbound](https://unbound.net), an open source high-performance DNS resolver brought to you by the nice people [@NLnetLabs](https://github.com/NLnetLabs) running as **your own** recursive DNS server. +This is an actively maintained and trustworthy, lightweight Alpine Linux based Docker image that runs [Unbound](https://unbound.net), an open source high-performance DNS resolver brought to you by the nice people [@NLnetLabs](https://github.com/NLnetLabs) running as **your own** recursive DNS server in an "distroless" scratch image.
@@ -53,7 +52,8 @@ Docker containers are most easily used with docker compose. Tags
- - [1.19.1-0 (latest)](https://hub.docker.com/r/madnuttah/unbound/tags) + - [1.19.1-1 (latest)](https://hub.docker.com/r/madnuttah/unbound/tags) + - [1.19.1-0](https://hub.docker.com/r/madnuttah/unbound/tags) - [1.19.0-5](https://hub.docker.com/r/madnuttah/unbound/tags) - [1.19.0-4](https://hub.docker.com/r/madnuttah/unbound/tags) - [1.19.0-3](https://hub.docker.com/r/madnuttah/unbound/tags) diff --git a/doc/DETAILS.md b/doc/DETAILS.md index c0079a3..6fa1f89 100644 --- a/doc/DETAILS.md +++ b/doc/DETAILS.md @@ -27,7 +27,6 @@ [![Current Alpine Linux release](https://img.shields.io/docker/v/_/alpine/latest?label=Current%20Alpine%20Linux%20release&style=flat-square)](https://github.com/alpinelinux/docker-alpine) [![Current Unbound release](https://img.shields.io/github/v/tag/nlnetlabs/unbound?label=Current%20Unbound%20release&style=flat-square)](https://github.com/NLnetLabs/unbound/tags) -[![Current OpenSSL release](https://img.shields.io/github/v/tag/openssl/openssl?label=Current%20OpenSSL%20release&style=flat-square)](https://github.com/openssl/openssl/tags) ## Table of Contents @@ -54,7 +53,7 @@ Source: [unbound.net](https://unbound.net/) ## About this Image This container image is based on Alpine Linux with focus on security, performance and a small image size. -The unbound process runs in the context of a non-root user, is build with a "distroless" scratch image and makes use of unprivileged ports (5335 tcp/udp). +The unbound process runs in the context of a non-root user, makes use of unprivileged ports (5335 tcp/udp) and the image is built using a "distroless" scratch image. Unbound is configured as an DNSSEC validating DNS resolver, which directly queries DNS root servers utilizing zone transfers holding a local copy of the root zone (see [IETF RFC 8806](https://www.rfc-editor.org/rfc/rfc8806.txt)) as your own recursive upstream DNS server in combination with [Pi-hole](https://pi-hole.net/) for adblocking in mind, but works also as a standalone server. diff --git a/doc/examples/docker-compose.yaml-bridge b/doc/examples/docker-compose.yaml-bridge index bce4494..369c840 100644 --- a/doc/examples/docker-compose.yaml-bridge +++ b/doc/examples/docker-compose.yaml-bridge @@ -64,6 +64,9 @@ services: TZ: #e.g. "America/New_York" ServerIP: #e.g. 172.20.0.253 or fd11:aa:1234:1234::505 VIRTUAL_HOST: + #Optional + UID: + GID: volumes: - ./unbound.conf:/usr/local/unbound/unbound.conf:rw #Your local path to Unbound - ./conf.d/:/usr/local/unbound/conf.d/:rw diff --git a/doc/examples/docker-compose.yaml-macvlan b/doc/examples/docker-compose.yaml-macvlan index 0485fcd..27fc028 100644 --- a/doc/examples/docker-compose.yaml-macvlan +++ b/doc/examples/docker-compose.yaml-macvlan @@ -70,6 +70,9 @@ services: TZ: #e.g. "America/New_York" ServerIP: #e.g. 192.168.1.253 or fd11:aa:1234:1234::505 VIRTUAL_HOST: + #Optional + UID: + GID: volumes: - ./unbound.conf:/usr/local/unbound/unbound.conf:rw #Your local path to Unbound - ./conf.d/:/usr/local/unbound/conf.d/:rw diff --git a/doc/examples/usr/local/unbound/unbound.conf b/doc/examples/usr/local/unbound/unbound.conf index 1a0ab53..a3505c6 100644 --- a/doc/examples/usr/local/unbound/unbound.conf +++ b/doc/examples/usr/local/unbound/unbound.conf @@ -3,8 +3,8 @@ include: "/usr/local/unbound/zones.d/*.conf" server: module-config: "validator iterator" - username: "_unbound" - directory: "/usr/local/unbound" - chroot: "/usr/local/unbound" + username: "" + directory: "/usr/local/unbound" + chroot: "" do-daemonize: no tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt diff --git a/unbound/Dockerfile b/unbound/Dockerfile index 75bd4c1..b8bdd0c 100644 --- a/unbound/Dockerfile +++ b/unbound/Dockerfile @@ -2,25 +2,31 @@ ARG IMAGE_BUILD_DATE="2024-02-14" \ ALPINE_VERSION="3.19.1" \ OPENSSL_VERSION="3.2.1" \ UNBOUND_VERSION="1.19.1" \ - IMAGE_REVISION="0" + IMAGE_REVISION="1" \ + ARG UID=1000 \ + ARG GID=1000 FROM alpine:"${ALPINE_VERSION}" AS buildenv LABEL maintainer="madnuttah" -ARG UNBOUND_VERSION +ARG UNBOUND_VERSION \ + UID \ + GID ENV UNBOUND_VERSION=${UNBOUND_VERSION} \ UNBOUND_DOWNLOAD_URL="https://www.nlnetlabs.nl/downloads/unbound/unbound-"${UNBOUND_VERSION}".tar.gz" \ UNBOUND_PGP="EDFAA3F2CA4E6EB05681AF8E9F6F1C2D7E045F8D" \ UNBOUND_SHA256="bc1d576f3dd846a0739adc41ffaa702404c6767d2b6082deb9f2f97cbb24a3a9" \ - INTERNIC_PGP="F0CB1A326BDF3F3EFA3A01FA937BB869E3A238C5" + INTERNIC_PGP="F0CB1A326BDF3F3EFA3A01FA937BB869E3A238C5" \ + UID="${UID}" \ + GID="${GID}" WORKDIR /tmp/src RUN set -xe; \ - addgroup -S -g 1000 _unbound && \ - adduser -S -H -h /usr/local/unbound -g _unbound -u 1000 -D -G _unbound _unbound && \ + addgroup -S -g "${GID}" _unbound && \ + adduser -S -H -h /usr/local/unbound -g _unbound -u "${UID}" -D -G _unbound _unbound && \ apk --update --no-cache add \ ca-certificates \ gnupg \ @@ -39,7 +45,7 @@ RUN set -xe; \ protobuf-c-dev \ hiredis-dev \ apk-tools && \ - curl -sSL "$UNBOUND_DOWNLOAD_URL" -o unbound.tar.gz && \ + curl -sSL "${UNBOUND_DOWNLOAD_URL}" -o unbound.tar.gz && \ curl -sSL "${UNBOUND_DOWNLOAD_URL}".asc -o unbound.tar.gz.asc && \ echo "${UNBOUND_SHA256} *unbound.tar.gz" | sha256sum -c - && \ GNUPGHOME="$(mktemp -d)" && \ @@ -48,7 +54,7 @@ RUN set -xe; \ gpg --batch --verify unbound.tar.gz.asc unbound.tar.gz && \ tar -xzf unbound.tar.gz && \ rm unbound.tar.gz && \ - cd unbound-${UNBOUND_VERSION} && \ + cd unbound-"${UNBOUND_VERSION}" && \ ./configure \ --prefix=/usr/local/unbound/unbound.d \ --with-run-dir=/usr/local/unbound/unbound.d \ @@ -158,13 +164,13 @@ COPY --from=buildenv /usr/local/unbound/ \ COPY --from=buildenv /lib/*-musl-* \ /app/lib/ -COPY --from=buildenv /bin/sh /bin/ash \ +COPY --from=buildenv /bin/sh /bin/sed \ /app/bin/ COPY --from=buildenv /usr/lib/libgcc_s* /app/lib/ -COPY --from=buildenv /usr/bin/nslookup \ - /app/bin/nslookup +COPY --from=buildenv /usr/bin/nslookup /usr/bin/awk \ + /app/bin/ COPY --from=buildenv /usr/lib/libsodium* \ /usr/lib/libcrypto* \ @@ -193,13 +199,15 @@ FROM scratch as unbound ARG UNBOUND_VERSION \ ALPINE_VERSION \ IMAGE_BUILD_DATE \ - IMAGE_REVISION + IMAGE_REVISION \ + UID ENV BUILD_DATE=${IMAGE_BUILD_DATE} \ IMAGE_REVISION=${IMAGE_REVISION} \ UNBOUND_VERSION=${UNBOUND_VERSION} \ ALPINE_VERSION=${ALPINE_VERSION} \ - PATH=/usr/local/unbound/unbound.d/sbin:"$PATH" + UID="${UID}" \ + PATH=/usr/local/unbound/unbound.d/sbin:"$PATH" LABEL maintainer="madnuttah" \ org.opencontainers.image.title="madnuttah/unbound" \ @@ -217,4 +225,6 @@ LABEL maintainer="madnuttah" \ COPY --from=stage /app/ / -CMD [ "/usr/local/unbound/sbin/unbound.sh" ] +USER "${UID}" + +CMD [ "/usr/local/unbound/sbin/unbound.sh" ] \ No newline at end of file diff --git a/unbound/root/usr/local/unbound/unbound.conf b/unbound/root/usr/local/unbound/unbound.conf index 92e829c..f840dc4 100644 --- a/unbound/root/usr/local/unbound/unbound.conf +++ b/unbound/root/usr/local/unbound/unbound.conf @@ -404,7 +404,7 @@ server: # If you give "" no privileges are dropped. # username: "@UNBOUND_USERNAME@" - username: "_unbound" + username: "" # the working directory. The relative files in this config are # relative to this directory. If you give "" the working directory