From f46a357ec01596c31460ac16427b7d0c52909927 Mon Sep 17 00:00:00 2001 From: Elijah Zupancic Date: Thu, 4 Sep 2025 12:18:53 -0700 Subject: [PATCH 1/3] refactor: simplify docker build process This change does the following: * Migrates to using the official NGINX Plus Docker images as base images * Removes the distinction between BuildKit and non-BuildKit builds for Plus images (OSS never had this) * Adds support for license validation for Plus images * Introduces a multi-stage build for Plus images Signed-off-by: Elijah Zupancic --- Dockerfile.buildkit.plus | 104 ------------------ Dockerfile.latest-njs | 5 +- Dockerfile.oss | 22 ++-- Dockerfile.plus | 95 ++++------------ .../00-check-for-required-env.sh | 18 --- .../01-set-defaults.envsh} | 62 +++-------- .../docker-entrypoint.d/99-output-settings.sh | 36 ++++++ docs/getting_started.md | 29 +---- .../10-listen-on-ipv6-by-default.sh | 77 ------------- .../20-envsubst-on-templates.sh | 48 -------- plus/etc/nginx/nginx-license.conf | 15 +++ test.sh | 38 +++++-- 12 files changed, 128 insertions(+), 421 deletions(-) delete mode 100644 Dockerfile.buildkit.plus rename common/{docker-entrypoint.sh => docker-entrypoint.d/01-set-defaults.envsh} (64%) create mode 100644 common/docker-entrypoint.d/99-output-settings.sh delete mode 100644 plus/docker-entrypoint.d/10-listen-on-ipv6-by-default.sh delete mode 100644 plus/docker-entrypoint.d/20-envsubst-on-templates.sh create mode 100644 plus/etc/nginx/nginx-license.conf diff --git a/Dockerfile.buildkit.plus b/Dockerfile.buildkit.plus deleted file mode 100644 index 6f5d8c93..00000000 --- a/Dockerfile.buildkit.plus +++ /dev/null @@ -1,104 +0,0 @@ -FROM debian:bookworm-slim@sha256:b1211f6d19afd012477bd34fdcabb6b663d680e0f4b0537da6e6b0fd057a3ec3 - -# Create RELEASE argument -ARG RELEASE=bookworm - -# NJS env vars -ENV NGINX_VERSION=34 -ENV NGINX_PKG_RELEASE=1~${RELEASE} -ENV NJS_VERSION=0.9.0 -ENV NJS_PKG_RELEASE=1~${RELEASE} - -# Proxy cache env vars -ENV PROXY_CACHE_MAX_SIZE=10g -ENV PROXY_CACHE_INACTIVE=60m -ENV PROXY_CACHE_SLICE_SIZE=1m -ENV PROXY_CACHE_VALID_OK=1h -ENV PROXY_CACHE_VALID_NOTFOUND=1m -ENV PROXY_CACHE_VALID_FORBIDDEN=30s - -# CORS env vars -ENV CORS_ENABLED=0 -ENV CORS_ALLOW_PRIVATE_NETWORK_ACCESS="" - -# S3 proxy env vars -ENV DIRECTORY_LISTING_PATH_PREFIX="" -ENV STRIP_LEADING_DIRECTORY_PATH="" -ENV PREFIX_LEADING_DIRECTORY_PATH="" - -# We create an NGINX Plus image based on the official NGINX Plus Dockerfiles (https://gist.github.com/nginx-gists/36e97fc87efb5cf0039978c8e41a34b5) and modify it by: -# 1. Explicitly installing the version of njs coded in the environment variable above. -# 2. Adding configuration files needed for proxying private S3 buckets. -# 3. Adding a directory for proxied objects to be stored. -# 4. Adding the entrypoint scripts found in the base NGINX OSS Docker image with a modified version that explicitly sets resolvers. - -# Download your NGINX license certificate and key from the F5 customer portal (https://account.f5.com) and copy it to the build context -RUN --mount=type=secret,id=nginx-crt,dst=nginx-repo.crt \ - --mount=type=secret,id=nginx-key,dst=nginx-repo.key \ - set -x \ -# Create nginx user/group first, to be consistent throughout Docker variants - && groupadd --system --gid 101 nginx \ - && useradd --system --gid nginx --no-create-home --home /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ - && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg1 lsb-release \ - && \ - NGINX_GPGKEYS="573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 8540A6F18833A80E9C1653A42FD21310B49F6B46 9E9BE90EACBCDE69FE9B204CBCDCD8A38D88A2B3"; \ - NGINX_GPGKEY_PATH=/etc/apt/keyrings/nginx-archive-keyring.gpg; \ - export GNUPGHOME="$(mktemp -d)"; \ - found=''; \ - for NGINX_GPGKEY in $NGINX_GPGKEYS; do \ - for server in \ - hkp://keyserver.ubuntu.com:80 \ - pgp.mit.edu \ - ; do \ - echo "Fetching GPG key $NGINX_GPGKEY from $server"; \ - gpg1 --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \ - done; \ - test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \ - done; \ - gpg1 --export $NGINX_GPGKEYS > "$NGINX_GPGKEY_PATH" ; \ - rm -rf "$GNUPGHOME"; \ - apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \ -# Install the latest release of NGINX Plus and/or NGINX Plus modules (written and maintained by F5) - && nginxPackages=" \ - nginx-plus=${NGINX_VERSION}-${NGINX_PKG_RELEASE} \ - nginx-plus-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${NJS_PKG_RELEASE} \ - nginx-plus-module-xslt=${NGINX_VERSION}-${NGINX_PKG_RELEASE} \ - " \ - && echo "Acquire::https::pkgs.nginx.com::Verify-Peer \"true\";" > /etc/apt/apt.conf.d/90nginx \ - && echo "Acquire::https::pkgs.nginx.com::Verify-Host \"true\";" >> /etc/apt/apt.conf.d/90nginx \ - && echo "Acquire::https::pkgs.nginx.com::SslCert \"/etc/ssl/nginx/nginx-repo.crt\";" >> /etc/apt/apt.conf.d/90nginx \ - && echo "Acquire::https::pkgs.nginx.com::SslKey \"/etc/ssl/nginx/nginx-repo.key\";" >> /etc/apt/apt.conf.d/90nginx \ - && echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://pkgs.nginx.com/plus/debian `lsb_release -cs` nginx-plus\n" > /etc/apt/sources.list.d/nginx-plus.list \ - && mkdir -p /etc/ssl/nginx \ - && cat nginx-repo.crt > /etc/ssl/nginx/nginx-repo.crt \ - && cat nginx-repo.key > /etc/ssl/nginx/nginx-repo.key \ - && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y $nginxPackages curl gettext-base \ - && apt-get remove --purge -y lsb-release \ - && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx-plus.list \ - && rm -rf /etc/apt/apt.conf.d/90nginx /etc/ssl/nginx \ -# Forward request logs to Docker log collector - && ln -sf /dev/stdout /var/log/nginx/access.log \ - && ln -sf /dev/stderr /var/log/nginx/error.log - -EXPOSE 80 - -STOPSIGNAL SIGTERM - -CMD ["nginx", "-g", "daemon off;"] - -# Copy files from the OSS NGINX Docker container such that the container -# startup is the same. -COPY plus/etc/nginx /etc/nginx -COPY common/etc /etc -COPY common/docker-entrypoint.sh /docker-entrypoint.sh -COPY common/docker-entrypoint.d /docker-entrypoint.d/ -COPY plus/docker-entrypoint.d /docker-entrypoint.d/ - -RUN set -x \ - && mkdir -p /var/cache/nginx/s3_proxy \ - && chown nginx:nginx /var/cache/nginx/s3_proxy \ - && chmod -R -v +x /docker-entrypoint.sh /docker-entrypoint.d/*.sh; - -ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/Dockerfile.latest-njs b/Dockerfile.latest-njs index 8f263c6c..4234d4b3 100644 --- a/Dockerfile.latest-njs +++ b/Dockerfile.latest-njs @@ -6,7 +6,10 @@ FROM nginx-s3-gateway RUN set -eux \ export DEBIAN_FRONTEND=noninteractive; \ apt-get update -qq; \ - apt-get install --no-install-recommends --no-install-suggests --yes make gcc libc6-dev curl expect libpcre2-dev libpcre3-dev libedit-dev libreadline-dev libssl-dev libpcre2-posix3 libxml2-dev libxslt1-dev zlib1g-dev; \ + apt-get install --no-install-recommends --no-install-suggests --yes --allow-change-held-packages \ + make gcc libc6-dev curl expect libpcre2-dev \ + libpcre3-dev libedit-dev libreadline-dev libssl-dev libpcre2-posix3 libxml2-dev libxslt1-dev zlib1g-dev \ + libgcrypt20 libicu-dev libssl-dev libxslt1-dev- libxml2-dev-; \ mkdir -p /tmp/nginx /tmp/njs-latest; \ curl --retry 6 --location "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" \ | gunzip | tar --extract --strip-components=1 --directory /tmp/nginx; \ diff --git a/Dockerfile.oss b/Dockerfile.oss index 9b24480e..e4db0a1a 100644 --- a/Dockerfile.oss +++ b/Dockerfile.oss @@ -1,8 +1,4 @@ -FROM nginx:1.29.0@sha256:f5c017fb33c6db484545793ffb67db51cdd7daebee472104612f73a85063f889 - -# NJS env vars -ENV NJS_VERSION=0.9.0 -ENV NJS_RELEASE=1~bookworm +FROM nginx:1.29.1@sha256:d5f28ef21aabddd098f3dbc21fe5b7a7d7a184720bc07da0b6c9b9820e97f25e # Proxy cache env vars ENV PROXY_CACHE_MAX_SIZE=10g @@ -27,20 +23,20 @@ ENV PREFIX_LEADING_DIRECTORY_PATH="" # 3. Adding a directory for proxied objects to be stored. # 4. Replacing the entrypoint script with a modified version that explicitly sets resolvers. +# Note: the PKG_RELEASE environment variable is inherited + RUN set -x \ - && echo "deb [signed-by=/etc/apt/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/mainline/debian/ $(echo $PKG_RELEASE | cut -f2 -d~) nginx" >> /etc/apt/sources.list.d/nginx.list; \ - apt-get update \ + && echo "deb [signed-by=/etc/apt/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/mainline/debian/ $(echo $PKG_RELEASE | cut -f2 -d~) nginx" >> /etc/apt/sources.list.d/nginx.list \ + && apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y \ - libedit2 \ - nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${NJS_RELEASE} \ - && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list + libedit2 nginx-module-njs nginx-module-xslt \ + && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* -COPY oss/etc /etc +COPY oss/etc/nginx /etc/nginx COPY common/etc /etc -COPY common/docker-entrypoint.sh /docker-entrypoint.sh COPY common/docker-entrypoint.d /docker-entrypoint.d/ RUN set -x \ && mkdir -p /var/cache/nginx/s3_proxy \ && chown nginx:nginx /var/cache/nginx/s3_proxy \ - && chmod -R -v +x /docker-entrypoint.sh /docker-entrypoint.d/*.sh; + && find /docker-entrypoint.d -type f \( -name '*.sh' -or -name '*.envsh' \) -exec chmod -v +x {} \; diff --git a/Dockerfile.plus b/Dockerfile.plus index a81682be..53ab2c20 100644 --- a/Dockerfile.plus +++ b/Dockerfile.plus @@ -1,13 +1,7 @@ -FROM debian:bookworm-slim@sha256:b1211f6d19afd012477bd34fdcabb6b663d680e0f4b0537da6e6b0fd057a3ec3 +# Pull from NGINX image that provides the XSLT module and supporting libraries +FROM private-registry.nginx.com/nginx-plus/modules:r35-xslt-debian@sha256:3eaa85dca47e31b9a6648bcaf6034f076cd59be9b1510b25fd1bbe1144f0bb48 AS xslt -# Create RELEASE argument -ARG RELEASE=bookworm - -# NJS env vars -ENV NGINX_VERSION=34 -ENV NGINX_PKG_RELEASE=1~${RELEASE} -ENV NJS_VERSION=0.9.0 -ENV NJS_PKG_RELEASE=1~${RELEASE} +FROM private-registry.nginx.com/nginx-plus/base:r35-debian-bookworm@sha256:9a82ad3f96d58be861257efd621f215d599e226ebedd24d9f3211bdd743c3c27 # Proxy cache env vars ENV PROXY_CACHE_MAX_SIZE=10g @@ -26,76 +20,25 @@ ENV DIRECTORY_LISTING_PATH_PREFIX="" ENV STRIP_LEADING_DIRECTORY_PATH="" ENV PREFIX_LEADING_DIRECTORY_PATH="" -# We create an NGINX Plus image based on the official NGINX Plus Dockerfiles (https://gist.github.com/nginx-gists/36e97fc87efb5cf0039978c8e41a34b5) and modify it by: -# 1. Explicitly installing the version of njs coded in the environment variable above. -# 2. Adding configuration files needed for proxying private S3 buckets. -# 3. Adding a directory for proxied objects to be stored. -# 4. Adding the entrypoint scripts found in the base NGINX OSS Docker image with a modified version that explicitly sets resolvers. - -# Download your NGINX license certificate and key from the F5 customer portal (https://account.f5.com) and copy it to the build context -COPY plus/etc/ssl /etc/ssl - -RUN set -x \ -# Create nginx user/group first, to be consistent throughout Docker variants - && groupadd --system --gid 101 nginx \ - && useradd --system --gid nginx --no-create-home --home /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \ - && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg1 lsb-release \ - && \ - NGINX_GPGKEYS="573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 8540A6F18833A80E9C1653A42FD21310B49F6B46 9E9BE90EACBCDE69FE9B204CBCDCD8A38D88A2B3"; \ - NGINX_GPGKEY_PATH=/etc/apt/keyrings/nginx-archive-keyring.gpg; \ - export GNUPGHOME="$(mktemp -d)"; \ - found=''; \ - for NGINX_GPGKEY in $NGINX_GPGKEYS; do \ - for server in \ - hkp://keyserver.ubuntu.com:80 \ - pgp.mit.edu \ - ; do \ - echo "Fetching GPG key $NGINX_GPGKEY from $server"; \ - gpg1 --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \ - done; \ - test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \ - done; \ - gpg1 --export $NGINX_GPGKEYS > "$NGINX_GPGKEY_PATH" ; \ - rm -rf "$GNUPGHOME"; \ - apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \ -# Install the latest release of NGINX Plus and/or NGINX Plus modules (written and maintained by F5) - && nginxPackages=" \ - nginx-plus=${NGINX_VERSION}-${NGINX_PKG_RELEASE} \ - nginx-plus-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${NJS_PKG_RELEASE} \ - nginx-plus-module-xslt=${NGINX_VERSION}-${NGINX_PKG_RELEASE} \ - " \ - && echo "Acquire::https::pkgs.nginx.com::Verify-Peer \"true\";" > /etc/apt/apt.conf.d/90nginx \ - && echo "Acquire::https::pkgs.nginx.com::Verify-Host \"true\";" >> /etc/apt/apt.conf.d/90nginx \ - && echo "Acquire::https::pkgs.nginx.com::SslCert \"/etc/ssl/nginx/nginx-repo.crt\";" >> /etc/apt/apt.conf.d/90nginx \ - && echo "Acquire::https::pkgs.nginx.com::SslKey \"/etc/ssl/nginx/nginx-repo.key\";" >> /etc/apt/apt.conf.d/90nginx \ - && echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://pkgs.nginx.com/plus/debian `lsb_release -cs` nginx-plus\n" > /etc/apt/sources.list.d/nginx-plus.list \ - && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y $nginxPackages curl gettext-base \ - && apt-get remove --purge -y lsb-release \ - && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx-plus.list \ - && rm -rf /etc/apt/apt.conf.d/90nginx /etc/ssl/nginx \ -# Forward request logs to Docker log collector - && ln -sf /dev/stdout /var/log/nginx/access.log \ - && ln -sf /dev/stderr /var/log/nginx/error.log - -EXPOSE 80 - -STOPSIGNAL SIGTERM - -CMD ["nginx", "-g", "daemon off;"] - # Copy files from the OSS NGINX Docker container such that the container # startup is the same. +COPY --from=xslt / / + COPY plus/etc/nginx /etc/nginx COPY common/etc /etc -COPY common/docker-entrypoint.sh /docker-entrypoint.sh COPY common/docker-entrypoint.d /docker-entrypoint.d/ -COPY plus/docker-entrypoint.d /docker-entrypoint.d/ - -RUN set -x \ - && mkdir -p /var/cache/nginx/s3_proxy \ - && chown nginx:nginx /var/cache/nginx/s3_proxy \ - && chmod -R -v +x /docker-entrypoint.sh /docker-entrypoint.d/*.sh; -ENTRYPOINT ["/docker-entrypoint.sh"] +RUN <> /etc/nginx/nginx.conf; \ + rm /etc/nginx/nginx-license.conf; \ + mkdir -p /var/cache/nginx/s3_proxy; \ + chown nginx:nginx /var/cache/nginx/s3_proxy; \ + find /docker-entrypoint.d -type f \( -name '*.sh' -or -name '*.envsh' \) -exec chmod -v +x {} \; +EOF diff --git a/common/docker-entrypoint.d/00-check-for-required-env.sh b/common/docker-entrypoint.d/00-check-for-required-env.sh index 61b249c0..491c2107 100755 --- a/common/docker-entrypoint.d/00-check-for-required-env.sh +++ b/common/docker-entrypoint.d/00-check-for-required-env.sh @@ -130,21 +130,3 @@ fi if [ $failed -gt 0 ]; then exit 1 fi - -echo "S3 Backend Environment" -echo "Service: ${S3_SERVICE:-s3}" -echo "Access Key ID: ${AWS_ACCESS_KEY_ID}" -echo "Origin: ${S3_SERVER_PROTO}://${S3_BUCKET_NAME}.${S3_SERVER}:${S3_SERVER_PORT}" -echo "Region: ${S3_REGION}" -echo "Addressing Style: ${S3_STYLE}" -echo "AWS Signatures Version: v${AWS_SIGS_VERSION}" -echo "DNS Resolvers: ${DNS_RESOLVERS}" -echo "Directory Listing Enabled: ${ALLOW_DIRECTORY_LIST}" -echo "Directory Listing Path Prefix: ${DIRECTORY_LISTING_PATH_PREFIX}" -echo "Provide Index Pages Enabled: ${PROVIDE_INDEX_PAGE}" -echo "Append slash for directory enabled: ${APPEND_SLASH_FOR_POSSIBLE_DIRECTORY}" -echo "Stripping the following headers from responses: x-amz-;${HEADER_PREFIXES_TO_STRIP}" -echo "Allow the following headers from responses (these take precedence over the above): ${HEADER_PREFIXES_ALLOWED}" -echo "CORS Enabled: ${CORS_ENABLED}" -echo "CORS Allow Private Network Access: ${CORS_ALLOW_PRIVATE_NETWORK_ACCESS}" -echo "Proxy cache using stale setting: ${PROXY_CACHE_USE_STALE}" diff --git a/common/docker-entrypoint.sh b/common/docker-entrypoint.d/01-set-defaults.envsh similarity index 64% rename from common/docker-entrypoint.sh rename to common/docker-entrypoint.d/01-set-defaults.envsh index 6908d72d..b50fbfe2 100644 --- a/common/docker-entrypoint.sh +++ b/common/docker-entrypoint.d/01-set-defaults.envsh @@ -1,4 +1,4 @@ -#!/usr/bin/bash +#!/bin/sh # # Copyright 2020 F5 Networks # @@ -15,9 +15,7 @@ # limitations under the License. # -# vim:sw=4:ts=4:et - -set -e +set -eu parseBoolean() { case "$1" in @@ -31,7 +29,7 @@ parseBoolean() { } # This line is an addition to the NGINX Docker image's entrypoint script. -if [ -z ${DNS_RESOLVERS+x} ]; then +if [ "${DNS_RESOLVERS+x}" = "" ]; then resolvers="" # This method of pulling individual nameservers from @@ -46,17 +44,19 @@ if [ -z ${DNS_RESOLVERS+x} ]; then resolvers="$resolvers $ip" fi done - export DNS_RESOLVERS="${resolvers}" + DNS_RESOLVERS="${resolvers}" + export DNS_RESOLVERS fi # Normalize the CORS_ENABLED environment variable to a numeric value # so that it can be easily parsed in the nginx configuration. -export CORS_ENABLED="$(parseBoolean "${CORS_ENABLED}")" +CORS_ENABLED="$(parseBoolean "${CORS_ENABLED}")" +export CORS_ENABLED # By enabling CORS, we also need to enable the OPTIONS method which # is not normally used as part of the gateway. The following variable # defines the set of acceptable headers. -if [ "${CORS_ENABLED}" == "1" ]; then +if [ "${CORS_ENABLED}" = "1" ]; then export LIMIT_METHODS_TO="GET HEAD OPTIONS" export LIMIT_METHODS_TO_CSV="GET, HEAD, OPTIONS" else @@ -64,13 +64,13 @@ else export LIMIT_METHODS_TO_CSV="GET, HEAD" fi -if [ -z "${CORS_ALLOWED_ORIGIN+x}" ]; then +if [ "${CORS_ALLOWED_ORIGIN+x}" = "" ]; then export CORS_ALLOWED_ORIGIN="*" fi # See documentation for this feature. We do not parse this as a boolean # since "true" and "false" are the required values of the header this populates -if [ "${CORS_ALLOW_PRIVATE_NETWORK_ACCESS}" != "true" ] && [ "${CORS_ALLOW_PRIVATE_NETWORK_ACCESS}" != "false" ]; then +if [ "${CORS_ALLOW_PRIVATE_NETWORK_ACCESS+x}" != "true" ] && [ "${CORS_ALLOW_PRIVATE_NETWORK_ACCESS+x}" != "false" ]; then export CORS_ALLOW_PRIVATE_NETWORK_ACCESS="" fi @@ -83,10 +83,10 @@ fi # S3_UPSTREAM needs the port specified. The port must # correspond to https/http in the proxy_pass directive. -if [ "${S3_STYLE}" == "virtual-v2" ]; then +if [ "${S3_STYLE}" = "virtual-v2" ]; then export S3_UPSTREAM="${S3_BUCKET_NAME}.${S3_SERVER}:${S3_SERVER_PORT}" export S3_HOST_HEADER="${S3_BUCKET_NAME}.${S3_SERVER}:${S3_SERVER_PORT}" -elif [ "${S3_STYLE}" == "path" ]; then +elif [ "${S3_STYLE}" = "path" ]; then export S3_UPSTREAM="${S3_SERVER}:${S3_SERVER_PORT}" export S3_HOST_HEADER="${S3_SERVER}:${S3_SERVER_PORT}" else @@ -95,42 +95,6 @@ else fi # Use default proxy_cache_use_stale settings if the variable is not defined -if [[ ! -v PROXY_CACHE_USE_STALE ]]; then +if [ "${PROXY_CACHE_USE_STALE+x}" = "" ]; then export PROXY_CACHE_USE_STALE="error timeout http_500 http_502 http_503 http_504" fi - -# Nothing is modified under this line - -if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then - exec 3>&1 -else - exec 3>/dev/null -fi - -if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then - if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - echo >&3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration" - - echo >&3 "$0: Looking for shell scripts in /docker-entrypoint.d/" - find "/docker-entrypoint.d/" -follow -type f -print | sort -n | while read -r f; do - case "$f" in - *.sh) - if [ -x "$f" ]; then - echo >&3 "$0: Launching $f"; - "$f" - else - # warn on shell scripts without exec bit - echo >&3 "$0: Ignoring $f, not executable"; - fi - ;; - *) echo >&3 "$0: Ignoring $f";; - esac - done - - echo >&3 "$0: Configuration complete; ready for start up" - else - echo >&3 "$0: No files found in /docker-entrypoint.d/, skipping configuration" - fi -fi - -exec "$@" diff --git a/common/docker-entrypoint.d/99-output-settings.sh b/common/docker-entrypoint.d/99-output-settings.sh new file mode 100644 index 00000000..1500d711 --- /dev/null +++ b/common/docker-entrypoint.d/99-output-settings.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Copyright 2025 F5 Networks +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +cat <&3 "$ME: error: ipv6 not available" - exit 0 -fi - -if [ ! -f "/$DEFAULT_CONF_FILE" ]; then - echo >&3 "$ME: error: /$DEFAULT_CONF_FILE is not a file or does not exist" - exit 0 -fi - -# check if the file can be modified, e.g. not on a r/o filesystem -touch /$DEFAULT_CONF_FILE 2>/dev/null || { echo >&3 "$ME: error: can not modify /$DEFAULT_CONF_FILE (read-only file system?)"; exit 0; } - -# check if the file is already modified, e.g. on a container restart -grep -q "listen \[::]\:80;" /$DEFAULT_CONF_FILE && { echo >&3 "$ME: error: IPv6 listen already enabled"; exit 0; } - -if [ -f "/etc/os-release" ]; then - . /etc/os-release -else - echo >&3 "$ME: error: can not guess the operating system" - exit 0 -fi - -echo >&3 "$ME: Getting the checksum of /$DEFAULT_CONF_FILE" - -case "$ID" in - "debian") - CHECKSUM=$(dpkg-query --show --showformat='${Conffiles}\n' nginx | grep $DEFAULT_CONF_FILE | cut -d' ' -f 3) - echo "$CHECKSUM /$DEFAULT_CONF_FILE" | md5sum -c - >/dev/null 2>&1 || { - echo >&3 "$ME: error: /$DEFAULT_CONF_FILE differs from the packaged version" - exit 0 - } - ;; - "alpine") - CHECKSUM=$(apk manifest nginx 2>/dev/null| grep $DEFAULT_CONF_FILE | cut -d' ' -f 1 | cut -d ':' -f 2) - echo "$CHECKSUM /$DEFAULT_CONF_FILE" | sha1sum -c - >/dev/null 2>&1 || { - echo >&3 "$ME: error: /$DEFAULT_CONF_FILE differs from the packages version" - exit 0 - } - ;; - *) - echo >&3 "$ME: error: Unsupported distribution" - exit 0 - ;; -esac - -# enable ipv6 on default.conf listen sockets -sed -i -E 's,listen 80;,listen 80;\n listen [::]:80;,' /$DEFAULT_CONF_FILE - -echo >&3 "$ME: Enabled listen on IPv6 in /$DEFAULT_CONF_FILE" - -exit 0 diff --git a/plus/docker-entrypoint.d/20-envsubst-on-templates.sh b/plus/docker-entrypoint.d/20-envsubst-on-templates.sh deleted file mode 100644 index c57faed6..00000000 --- a/plus/docker-entrypoint.d/20-envsubst-on-templates.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -# -# Copyright 2020 F5 Networks -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set -e - -ME=$(basename $0) - -auto_envsubst() { - local template_dir="${NGINX_ENVSUBST_TEMPLATE_DIR:-/etc/nginx/templates}" - local suffix="${NGINX_ENVSUBST_TEMPLATE_SUFFIX:-.template}" - local output_dir="${NGINX_ENVSUBST_OUTPUT_DIR:-/etc/nginx/conf.d}" - - local template defined_envs relative_path output_path subdir - defined_envs=$(printf '${%s} ' $(env | cut -d= -f1)) - [ -d "$template_dir" ] || return 0 - if [ ! -w "$output_dir" ]; then - echo >&3 "$ME: ERROR: $template_dir exists, but $output_dir is not writable" - return 0 - fi - find "$template_dir" -follow -type f -name "*$suffix" -print | while read -r template; do - relative_path="${template#$template_dir/}" - output_path="$output_dir/${relative_path%$suffix}" - subdir=$(dirname "$relative_path") - # create a subdirectory where the template file exists - mkdir -p "$output_dir/$subdir" - echo >&3 "$ME: Running envsubst on $template to $output_path" - envsubst "$defined_envs" < "$template" > "$output_path" - done -} - -auto_envsubst - -exit 0 diff --git a/plus/etc/nginx/nginx-license.conf b/plus/etc/nginx/nginx-license.conf new file mode 100644 index 00000000..0e09a704 --- /dev/null +++ b/plus/etc/nginx/nginx-license.conf @@ -0,0 +1,15 @@ + +#mgmt { + # Uncomment to change default reporting values + #usage_report endpoint=product.connect.nginx.com; + #license_token /etc/nginx/license.jwt; + + # Set to 'off' to begin the 180-day reporting enforcement grace period. + # Reporting must begin or resume before the end of the grace period + # to ensure continued operation. + #enforce_initial_report on; + + # Set to 'off' to trust all SSL certificates (not recommended). + # Useful for reporting to NGINX Instance Manager without a local PKI. + #ssl_verify on; +#} diff --git a/test.sh b/test.sh index 772b9cff..4dadf7fa 100755 --- a/test.sh +++ b/test.sh @@ -36,6 +36,8 @@ nginx_server_port="8989" test_server="${nginx_server_proto}://${nginx_server_host}:${nginx_server_port}" test_fail_exit_code=2 no_dep_exit_code=3 +build_dep_exit_code=4 + script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" test_dir="${script_dir}/test" test_compose_config="${test_dir}/docker-compose.yaml" @@ -197,6 +199,22 @@ compose() { export NGINX_INTERNAL_PORT=80 fi + if [ "${nginx_type}" == "plus" ]; then + if [ -f /etc/nginx/license.jwt ]; then + NGINX_LICENSE_JWT="$(cat /etc/nginx/license.jwt)" + elif [ -f license.jwt ]; then + NGINX_LICENSE_JWT="$(cat license.jwt)" + else + e "NGINX Plus license file not found: /etc/nginx/license.jwt or $(pwd)/license.jwt" + exit ${build_dep_exit_code} + fi + + else + NGINX_LICENSE_JWT="" + fi + + export NGINX_LICENSE_JWT + ${docker_compose_cmd} -f "${test_compose_config}" -p "${test_compose_project}" "$@" } @@ -213,7 +231,7 @@ integration_test_data() { p "Starting Docker Compose Environment" # COMPOSE_COMPATIBILITY=true Supports older style compose filenames with _ vs - COMPOSE_COMPATIBILITY=true compose up -d - + if [ "${wait_for_it_installed}" ]; then # Hit minio's health check end point to see if it has started up for (( i=1; i<=3; i++ )) @@ -252,7 +270,7 @@ integration_test() { printf "\e[1m Integration test suite with STRIP_LEADING_DIRECTORY_PATH=%s\e[22m\n" "$5" printf "\033[34;1m▶\033[0m" printf "\e[1m Integration test suite with PREFIX_LEADING_DIRECTORY_PATH=%s\e[22m\n" "$6" - + p "Starting Docker Compose Environment" # COMPOSE_COMPATIBILITY=true Supports older style compose filenames with _ vs - @@ -306,24 +324,20 @@ else if docker buildx > /dev/null 2>&1; then p "Building using BuildKit" export DOCKER_BUILDKIT=1 - docker buildx build -f Dockerfile.buildkit.${nginx_type} \ + docker buildx build -f "Dockerfile.${nginx_type}" \ --secret id=nginx-crt,src=plus/etc/ssl/nginx/nginx-repo.crt \ --secret id=nginx-key,src=plus/etc/ssl/nginx/nginx-repo.key \ - --no-cache \ - --tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} . + --tag nginx-s3-gateway --tag "nginx-s3-gateway:${nginx_type}" . else - docker build -f Dockerfile.${nginx_type} \ - --tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} . + e "Only BuildKit builds are supported with NGINX Plus image" + exit ${build_dep_exit_code} fi else - docker build -f Dockerfile.${nginx_type} \ - --tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} . + docker build -f "Dockerfile.${nginx_type}" \ + --tag nginx-s3-gateway --tag "nginx-s3-gateway:${nginx_type}" . fi - unit_test_command="-t module -p '/etc/nginx'" - if [ ${njs_latest} -eq 1 ]; then - unit_test_command="-m -p '/etc/nginx'" p "Layering in latest NJS build" docker build -f Dockerfile.latest-njs \ --tag nginx-s3-gateway --tag nginx-s3-gateway:latest-njs-${nginx_type} . From fcc9614d1d2b48e9efe460b3367ec20e0fbd2dd0 Mon Sep 17 00:00:00 2001 From: Elijah Zupancic Date: Mon, 8 Sep 2025 17:35:16 -0700 Subject: [PATCH 2/3] chore: remove deprecated version parameter from docker-compose.yaml Signed-off-by: Elijah Zupancic --- test/docker-compose.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/docker-compose.yaml b/test/docker-compose.yaml index 2faa9c8a..3ce82e86 100644 --- a/test/docker-compose.yaml +++ b/test/docker-compose.yaml @@ -1,5 +1,3 @@ -version: "3" - services: nginx-s3-gateway: # If minio client is up and running properly, we are reasonably sure that @@ -37,6 +35,7 @@ services: PROXY_CACHE_VALID_OK: "1h" PROXY_CACHE_VALID_NOTFOUND: "1m" PROXY_CACHE_VALID_FORBIDDEN: "30s" + NGINX_LICENSE_JWT: "${NGINX_LICENSE_JWT}" minio: image: quay.io/minio/minio:RELEASE.2023-06-09T07-32-12Z From e8138d2c2733bcfacce8378ae7436e067cd6cdeb Mon Sep 17 00:00:00 2001 From: Elijah Zupancic Date: Tue, 9 Sep 2025 15:35:50 -0700 Subject: [PATCH 3/3] fix: use nginx version reported by binary instead of env var By using the version reported by NGINX rather than the environment variable it allows for a more reliable setting and less complexity. Signed-off-by: Elijah Zupancic --- Dockerfile.latest-njs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile.latest-njs b/Dockerfile.latest-njs index 4234d4b3..4a4bd4d7 100644 --- a/Dockerfile.latest-njs +++ b/Dockerfile.latest-njs @@ -4,7 +4,8 @@ FROM nginx-s3-gateway RUN set -eux \ - export DEBIAN_FRONTEND=noninteractive; \ + export DEBIAN_FRONTEND=noninteractive; \ + export NGINX_VERSION="$(nginx -V 2>&1 | grep 'nginx version' | awk -F'[/ ]' '{print $4}')"; \ apt-get update -qq; \ apt-get install --no-install-recommends --no-install-suggests --yes --allow-change-held-packages \ make gcc libc6-dev curl expect libpcre2-dev \