diff --git a/.github/workflows/alpine-mainline.yml b/.github/workflows/alpine-mainline.yml index 1c2fad8..527bf99 100644 --- a/.github/workflows/alpine-mainline.yml +++ b/.github/workflows/alpine-mainline.yml @@ -28,7 +28,7 @@ jobs: - name: Parse Alpine version id: distro_version run: | - echo "release=$(cat update.sh | grep -m7 '\[mainline\]=' | tail -n1 | cut -d"'" -f2)" >> "$GITHUB_OUTPUT" + echo "release=$(cat update.sh | grep -m8 '\[mainline\]=' | tail -n1 | cut -d"'" -f2)" >> "$GITHUB_OUTPUT" slim: name: Build Alpine NGINX mainline slim Docker image @@ -383,3 +383,121 @@ jobs: DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID }} DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} NOTARY_TARGETS_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + otel: + name: Build Alpine NGINX mainline otel Docker image + needs: [version, core] + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + steps: + - name: Check out the codebase + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + + - name: Configure AWS credentials + if: ${{ github.event_name != 'pull_request' }} + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1 + with: + aws-region: ${{ secrets.AWS_REGION }} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + - name: Login to Amazon ECR Public Gallery + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: public.ecr.aws + + - name: Login to Docker Hub + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Quay + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_TOKEN }} + + - name: Extract metadata (annotations, labels, tags) for Docker + id: meta + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: | + docker.io/nginxinc/nginx-unprivileged + ghcr.io/nginx/nginx-unprivileged + public.ecr.aws/nginx/nginx-unprivileged + quay.io/nginx/nginx-unprivileged + tags: | + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-alpine-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-alpine${{ needs.version.outputs.distro }}-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-alpine-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-alpine${{ needs.version.outputs.distro }}-otel + type=raw,value=${{ needs.version.outputs.major }}-alpine-otel + type=raw,value=${{ needs.version.outputs.major }}-alpine${{ needs.version.outputs.distro }}-otel + type=raw,value=mainline-alpine-otel + type=raw,value=mainline-alpine${{ needs.version.outputs.distro }}-otel + type=raw,value=alpine-otel + type=raw,value=alpine${{ needs.version.outputs.distro }}-otel + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + + - name: Build and push NGINX mainline otel Alpine image to Amazon ECR Public Gallery, Docker Hub, GitHub Container Registry, and Quay + id: build + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + platforms: linux/amd64, linux/arm64 + context: "{{ defaultContext }}:mainline/alpine-otel" + labels: ${{ steps.meta.outputs.labels }} + annotations: ${{ steps.meta.outputs.annotations }} + tags: ${{ steps.meta.outputs.tags }} + push: ${{ github.event_name != 'pull_request' }} + # cache-from: type=gha,scope=alpine-otel + # cache-to: type=gha,mode=min,scope=alpine-otel + + - name: Sign Docker Hub Manifest + if: ${{ github.event_name != 'pull_request' }} + run: | + set -ex + sudo apt update + sudo apt install -y notary + mkdir -p ~/.docker/trust/private + echo "$DOCKER_CONTENT_TRUST_REPOSITORY_KEY" > ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key + chmod 0400 ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key + docker trust key load ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key --name nginx + DIGEST=$(printf '${{ steps.build.outputs.metadata }}' | jq -r '."containerimage.descriptor".digest' | cut -d ':' -f2) + SIZE=$(printf '${{ steps.build.outputs.metadata }}' | jq -r '."containerimage.descriptor".size') + export NOTARY_AUTH=$(printf "${{ secrets.DOCKERHUB_USERNAME }}:${{ secrets.DOCKERHUB_TOKEN }}" | base64 -w0) + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-alpine-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-alpine${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-alpine-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-alpine${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}-alpine-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}-alpine${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged mainline-alpine-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged mainline-alpine${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged alpine-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged alpine${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + env: + DOCKER_CONTENT_TRUST_REPOSITORY_KEY: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY }} + DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID }} + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + NOTARY_TARGETS_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} diff --git a/.github/workflows/alpine-stable.yml b/.github/workflows/alpine-stable.yml index 717524b..6391d1a 100644 --- a/.github/workflows/alpine-stable.yml +++ b/.github/workflows/alpine-stable.yml @@ -28,7 +28,7 @@ jobs: - name: Parse Alpine version id: distro_version run: | - echo "release=$(cat update.sh | grep -m7 '\[stable\]=' | tail -n1 | cut -d"'" -f2)" >> "$GITHUB_OUTPUT" + echo "release=$(cat update.sh | grep -m8 '\[stable\]=' | tail -n1 | cut -d"'" -f2)" >> "$GITHUB_OUTPUT" slim: name: Build Alpine NGINX stable slim Docker image @@ -359,3 +359,112 @@ jobs: DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID }} DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} NOTARY_TARGETS_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + otel: + name: Build Alpine NGINX stable otel Docker image + needs: [version, core] + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + steps: + - name: Check out the codebase + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + + - name: Configure AWS credentials + if: ${{ github.event_name != 'pull_request' }} + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1 + with: + aws-region: ${{ secrets.AWS_REGION }} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + - name: Login to Amazon ECR Public Gallery + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: public.ecr.aws + + - name: Login to Docker Hub + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Quay + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_TOKEN }} + + - name: Extract metadata (annotations, labels, tags) for Docker + id: meta + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: | + docker.io/nginxinc/nginx-unprivileged + ghcr.io/nginx/nginx-unprivileged + public.ecr.aws/nginx/nginx-unprivileged + quay.io/nginx/nginx-unprivileged + tags: | + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-alpine-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-alpine${{ needs.version.outputs.distro }}-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-alpine-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-alpine${{ needs.version.outputs.distro }}-otel + type=raw,value=stable-alpine-otel + type=raw,value=stable-alpine${{ needs.version.outputs.distro }}-otel + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + + - name: Build and push NGINX stable otel Alpine image to Amazon ECR Public Gallery, Docker Hub, GitHub Container Registry, and Quay + id: build + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + platforms: linux/amd64, linux/arm64 + context: "{{ defaultContext }}:stable/alpine-otel" + labels: ${{ steps.meta.outputs.labels }} + annotations: ${{ steps.meta.outputs.annotations }} + tags: ${{ steps.meta.outputs.tags }} + push: ${{ github.event_name != 'pull_request' }} + # cache-from: type=gha,scope=stable-alpine-otel + # cache-to: type=gha,mode=min,scope=stable-alpine-otel + + - name: Sign Docker Hub Manifest + if: ${{ github.event_name != 'pull_request' }} + run: | + set -ex + sudo apt update + sudo apt install -y notary + mkdir -p ~/.docker/trust/private + echo "$DOCKER_CONTENT_TRUST_REPOSITORY_KEY" > ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key + chmod 0400 ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key + docker trust key load ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key --name nginx + DIGEST=$(printf '${{ steps.build.outputs.metadata }}' | jq -r '."containerimage.descriptor".digest' | cut -d ':' -f2) + SIZE=$(printf '${{ steps.build.outputs.metadata }}' | jq -r '."containerimage.descriptor".size') + export NOTARY_AUTH=$(printf "${{ secrets.DOCKERHUB_USERNAME }}:${{ secrets.DOCKERHUB_TOKEN }}" | base64 -w0) + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-alpine-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-alpine${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-alpine-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-alpine${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged stable-alpine-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged stable-alpine${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + env: + DOCKER_CONTENT_TRUST_REPOSITORY_KEY: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY }} + DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID }} + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + NOTARY_TARGETS_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} diff --git a/.github/workflows/debian-mainline.yml b/.github/workflows/debian-mainline.yml index 339dda6..b94e8a5 100644 --- a/.github/workflows/debian-mainline.yml +++ b/.github/workflows/debian-mainline.yml @@ -28,7 +28,7 @@ jobs: - name: Parse Debian version id: distro_version run: | - echo "release=$(cat update.sh | grep -m6 '\[mainline\]=' | tail -n1 | cut -d"'" -f2)" >> "$GITHUB_OUTPUT" + echo "release=$(cat update.sh | grep -m7 '\[mainline\]=' | tail -n1 | cut -d"'" -f2)" >> "$GITHUB_OUTPUT" core: name: Build Debian NGINX mainline Docker image @@ -267,3 +267,121 @@ jobs: DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID }} DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} NOTARY_TARGETS_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + otel: + name: Build Debian NGINX mainline otel Docker image + needs: [version, core] + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + steps: + - name: Check out the codebase + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + + - name: Configure AWS credentials + if: ${{ github.event_name != 'pull_request' }} + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1 + with: + aws-region: ${{ secrets.AWS_REGION }} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + - name: Login to Amazon ECR Public Gallery + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: public.ecr.aws + + - name: Login to Docker Hub + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Quay + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_TOKEN }} + + - name: Extract metadata (annotations, labels, tags) for Docker + id: meta + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: | + docker.io/nginxinc/nginx-unprivileged + ghcr.io/nginx/nginx-unprivileged + public.ecr.aws/nginx/nginx-unprivileged + quay.io/nginx/nginx-unprivileged + tags: | + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-${{ needs.version.outputs.distro }}-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-${{ needs.version.outputs.distro }}-otel + type=raw,value=${{ needs.version.outputs.major }}-otel + type=raw,value=${{ needs.version.outputs.major }}-${{ needs.version.outputs.distro }}-otel + type=raw,value=mainline-otel + type=raw,value=mainline-${{ needs.version.outputs.distro }}-otel + type=raw,value=otel + type=raw,value=${{ needs.version.outputs.distro }}-otel + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + + - name: Build and push NGINX mainline otel Debian image to Amazon ECR Public Gallery, Docker Hub, GitHub Container Registry, and Quay + id: build + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + platforms: linux/amd64, linux/arm64 + context: "{{ defaultContext }}:mainline/debian-otel" + labels: ${{ steps.meta.outputs.labels }} + annotations: ${{ steps.meta.outputs.annotations }} + tags: ${{ steps.meta.outputs.tags }} + push: ${{ github.event_name != 'pull_request' }} + # cache-from: type=gha,scope=debian-otel + # cache-to: type=gha,mode=min,scope=debian-otel + + - name: Sign Docker Hub Manifest + if: ${{ github.event_name != 'pull_request' }} + run: | + set -ex + sudo apt update + sudo apt install -y notary + mkdir -p ~/.docker/trust/private + echo "$DOCKER_CONTENT_TRUST_REPOSITORY_KEY" > ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key + chmod 0400 ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key + docker trust key load ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key --name nginx + DIGEST=$(printf '${{ steps.build.outputs.metadata }}' | jq -r '."containerimage.descriptor".digest' | cut -d ':' -f2) + SIZE=$(printf '${{ steps.build.outputs.metadata }}' | jq -r '."containerimage.descriptor".size') + export NOTARY_AUTH=$(printf "${{ secrets.DOCKERHUB_USERNAME }}:${{ secrets.DOCKERHUB_TOKEN }}" | base64 -w0) + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}-${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged mainline-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged mainline-${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + env: + DOCKER_CONTENT_TRUST_REPOSITORY_KEY: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY }} + DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID }} + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + NOTARY_TARGETS_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} diff --git a/.github/workflows/debian-stable.yml b/.github/workflows/debian-stable.yml index b969e79..7bb80e6 100644 --- a/.github/workflows/debian-stable.yml +++ b/.github/workflows/debian-stable.yml @@ -25,10 +25,10 @@ jobs: echo "minor=$(cat update.sh | grep -m1 '\[stable\]=' | cut -d"'" -f2 | cut -d"." -f2)" >> "$GITHUB_OUTPUT" echo "patch=$(cat update.sh | grep -m1 '\[stable\]=' | cut -d"'" -f2 | cut -d"." -f3)" >> "$GITHUB_OUTPUT" - - name: Parse Alpine version + - name: Parse Debian version id: distro_version run: | - echo "release=$(cat update.sh | grep -m6 '\[stable\]=' | tail -n1 | cut -d"'" -f2)" >> "$GITHUB_OUTPUT" + echo "release=$(cat update.sh | grep -m7 '\[stable\]=' | tail -n1 | cut -d"'" -f2)" >> "$GITHUB_OUTPUT" core: name: Build Debian NGINX stable Docker image @@ -251,3 +251,113 @@ jobs: DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID }} DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} NOTARY_TARGETS_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + otel: + name: Build Debian NGINX stable otel Docker image + needs: [version, core] + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + steps: + - name: Check out the codebase + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + + - name: Configure AWS credentials + if: ${{ github.event_name != 'pull_request' }} + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1 + with: + aws-region: ${{ secrets.AWS_REGION }} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + - name: Login to Amazon ECR Public Gallery + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: public.ecr.aws + + - name: Login to Docker Hub + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Quay + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_TOKEN }} + + - name: Extract metadata (annotations, labels, tags) for Docker + id: meta + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 + with: + images: | + docker.io/nginxinc/nginx-unprivileged + ghcr.io/nginx/nginx-unprivileged + public.ecr.aws/nginx/nginx-unprivileged + quay.io/nginx/nginx-unprivileged + tags: | + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-${{ needs.version.outputs.distro }}-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-otel + type=raw,value=${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-${{ needs.version.outputs.distro }}-otel + type=raw,value=stable-otel + type=raw,value=stable-${{ needs.version.outputs.distro }}-otel + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + + - name: Build and push NGINX stable otel Debian image to Amazon ECR Public Gallery, Docker Hub, GitHub Container Registry, and Quay + id: build + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + platforms: linux/amd64, linux/arm64 + context: "{{ defaultContext }}:stable/debian-otel" + labels: ${{ steps.meta.outputs.labels }} + annotations: ${{ steps.meta.outputs.annotations }} + tags: ${{ steps.meta.outputs.tags }} + push: ${{ github.event_name != 'pull_request' }} + # cache-from: type=gha,scope=stable-debian-otel + # cache-to: type=gha,mode=min,scope=stable-debian-otel + + - name: Sign Docker Hub Manifest + if: ${{ github.event_name != 'pull_request' }} + run: | + set -ex + sudo apt update + sudo apt install -y notary + mkdir -p ~/.docker/trust/private + echo "$DOCKER_CONTENT_TRUST_REPOSITORY_KEY" > ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key + chmod 0400 ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key + docker trust key load ~/.docker/trust/private/$DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID.key --name nginx + DIGEST=$(printf '${{ steps.build.outputs.metadata }}' | jq -r '."containerimage.descriptor".digest' | cut -d ':' -f2) + SIZE=$(printf '${{ steps.build.outputs.metadata }}' | jq -r '."containerimage.descriptor".size') + export NOTARY_AUTH=$(printf "${{ secrets.DOCKERHUB_USERNAME }}:${{ secrets.DOCKERHUB_TOKEN }}" | base64 -w0) + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}.${{ needs.version.outputs.patch }}-${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged ${{ needs.version.outputs.major }}.${{ needs.version.outputs.minor }}-${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged stable-otel $SIZE --sha256 $DIGEST --publish --verbose + notary -d ~/.docker/trust/ -s https://notary.docker.io addhash docker.io/nginxinc/nginx-unprivileged stable-${{ needs.version.outputs.distro }}-otel $SIZE --sha256 $DIGEST --publish --verbose + env: + DOCKER_CONTENT_TRUST_REPOSITORY_KEY: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY }} + DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_KEY_ID }} + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + NOTARY_TARGETS_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} diff --git a/Dockerfile-alpine-otel.template b/Dockerfile-alpine-otel.template new file mode 100644 index 0000000..14212a0 --- /dev/null +++ b/Dockerfile-alpine-otel.template @@ -0,0 +1,74 @@ +ARG IMAGE=nginxinc/nginx-unprivileged:%%NGINX_VERSION%%-alpine +FROM $IMAGE + +ENV OTEL_VERSION=%%OTEL_VERSION%% + +ARG UID=101 +ARG GID=101 + +USER root + +RUN set -x \ + && apkArch="$(cat /etc/apk/arch)" \ + && nginxPackages="%%PACKAGES%% + " \ +# install prerequisites for public key and pkg-oss checks + && apk add --no-cache --virtual .checksum-deps \ + openssl \ + && case "$apkArch" in \ + x86_64|aarch64) \ +# arches officially built by upstream + apk add -X "%%PACKAGEREPO%%v$(egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" --no-cache $nginxPackages \ + ;; \ + *) \ +# we're on an architecture upstream doesn't officially build for +# let's build binaries from the published packaging sources + set -x \ + && tempDir="$(mktemp -d)" \ + && chown nobody:nobody $tempDir \ + && apk add --no-cache --virtual .build-deps \ + gcc \ + libc-dev \ + make \ + openssl-dev \ + pcre2-dev \ + zlib-dev \ + linux-headers \ + cmake \ + bash \ + alpine-sdk \ + findutils \ + curl \ + xz \ + protobuf-dev \ + grpc-dev \ + && su nobody -s /bin/sh -c " \ + export HOME=${tempDir} \ + && cd ${tempDir} \ + && curl -f -L -O https://github.com/nginx/pkg-oss/archive/%%REVISION%%.tar.gz \ + && PKGOSSCHECKSUM=\"%%PKGOSSCHECKSUM%% *%%REVISION%%.tar.gz\" \ + && if [ \"\$(openssl sha512 -r %%REVISION%%.tar.gz)\" = \"\$PKGOSSCHECKSUM\" ]; then \ + echo \"pkg-oss tarball checksum verification succeeded!\"; \ + else \ + echo \"pkg-oss tarball checksum verification failed!\"; \ + exit 1; \ + fi \ + && tar xzvf %%REVISION%%.tar.gz \ + && cd pkg-oss-%%REVISION%% \ + && cd alpine \ + && make %%BUILDTARGET%% \ + && apk index --allow-untrusted -o ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz ${tempDir}/packages/alpine/${apkArch}/*.apk \ + && abuild-sign -k ${tempDir}/.abuild/abuild-key.rsa ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz \ + " \ + && cp ${tempDir}/.abuild/abuild-key.rsa.pub /etc/apk/keys/ \ + && apk del --no-network .build-deps \ + && apk add -X ${tempDir}/packages/alpine/ --no-cache $nginxPackages \ + ;; \ + esac \ +# remove checksum deps + && apk del --no-network .checksum-deps \ +# if we have leftovers from building, let's purge them (including extra, unnecessary build deps) + && if [ -n "$tempDir" ]; then rm -rf "$tempDir"; fi \ + && if [ -f "/etc/apk/keys/abuild-key.rsa.pub" ]; then rm -f /etc/apk/keys/abuild-key.rsa.pub; fi + +USER $UID diff --git a/Dockerfile-debian-otel.template b/Dockerfile-debian-otel.template new file mode 100644 index 0000000..93b8ea1 --- /dev/null +++ b/Dockerfile-debian-otel.template @@ -0,0 +1,97 @@ +ARG IMAGE=nginxinc/nginx-unprivileged:%%NGINX_VERSION%% +FROM $IMAGE + +ENV OTEL_VERSION=%%OTEL_VERSION%% + +ARG UID=101 +ARG GID=101 + +USER root + +RUN set -x; \ + NGINX_GPGKEY_PATH=/etc/apt/keyrings/nginx-archive-keyring.gpg; \ + dpkgArch="$(dpkg --print-architecture)" \ + && nginxPackages="%%PACKAGES%% + " \ + && case "$dpkgArch" in \ + amd64|arm64) \ +# arches officially built by upstream + echo "deb [signed-by=$NGINX_GPGKEY_PATH] %%PACKAGEREPO%% %%DEBIAN_VERSION%% nginx" >> /etc/apt/sources.list.d/nginx.list \ + && apt-get update \ + ;; \ + *) \ +# we're on an architecture upstream doesn't officially build for +# let's build binaries from the published packaging sources +# new directory for storing sources and .deb files + tempDir="$(mktemp -d)" \ + && chmod 777 "$tempDir" \ +# (777 to ensure APT's "_apt" user can access it too) + \ +# save list of currently-installed packages so build dependencies can be cleanly removed later + && savedAptMark="$(apt-mark showmanual)" \ + \ +# build .deb files from upstream's packaging sources + && apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + curl \ + devscripts \ + equivs \ + git \ + libxml2-utils \ + lsb-release \ + xsltproc \ + && ( \ + cd "$tempDir" \ + && REVISION="%%REVISION%%" \ + && REVISION=${REVISION%~*} \ + && curl -f -L -O https://github.com/nginx/pkg-oss/archive/${REVISION}.tar.gz \ + && PKGOSSCHECKSUM="%%PKGOSSCHECKSUM%% *${REVISION}.tar.gz" \ + && if [ "$(openssl sha512 -r ${REVISION}.tar.gz)" = "$PKGOSSCHECKSUM" ]; then \ + echo "pkg-oss tarball checksum verification succeeded!"; \ + else \ + echo "pkg-oss tarball checksum verification failed!"; \ + exit 1; \ + fi \ + && tar xzvf ${REVISION}.tar.gz \ + && cd pkg-oss-${REVISION} \ + && cd debian \ + && for target in %%BUILDTARGET%%; do \ + make rules-$target; \ + mk-build-deps --install --tool="apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes" \ + debuild-$target/nginx-$NGINX_VERSION/debian/control; \ + done \ + && make %%BUILDTARGET%% \ + ) \ +# we don't remove APT lists here because they get re-downloaded and removed later + \ +# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies +# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) + && apt-mark showmanual | xargs apt-mark auto > /dev/null \ + && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \ + \ +# create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) + && ls -lAFh "$tempDir" \ + && ( cd "$tempDir" && dpkg-scanpackages . > Packages ) \ + && grep '^Package: ' "$tempDir/Packages" \ + && echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list \ +# work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") +# Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) +# ... +# E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) + && apt-get -o Acquire::GzipIndexes=false update \ + ;; \ + esac \ + \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + $nginxPackages \ + gettext-base \ + curl \ + && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \ + \ +# if we have leftovers from building, let's purge them (including extra, unnecessary build deps) + && if [ -n "$tempDir" ]; then \ + apt-get purge -y --auto-remove \ + && rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ + fi + +USER $UID diff --git a/Dockerfile-debian-perl.template b/Dockerfile-debian-perl.template index 764c208..fa99560 100644 --- a/Dockerfile-debian-perl.template +++ b/Dockerfile-debian-perl.template @@ -13,7 +13,7 @@ RUN set -x; \ " \ && case "$dpkgArch" in \ amd64|arm64) \ -# arches officialy built by upstream +# arches officially built by upstream echo "deb [signed-by=$NGINX_GPGKEY_PATH] %%PACKAGEREPO%% %%DEBIAN_VERSION%% nginx" >> /etc/apt/sources.list.d/nginx.list \ && apt-get update \ ;; \ diff --git a/Dockerfile-debian.template b/Dockerfile-debian.template index 92788e8..ae3bd5b 100644 --- a/Dockerfile-debian.template +++ b/Dockerfile-debian.template @@ -41,7 +41,7 @@ RUN set -x \ " \ && case "$dpkgArch" in \ amd64|arm64) \ -# arches officialy built by upstream +# arches officially built by upstream echo "deb [signed-by=$NGINX_GPGKEY_PATH] %%PACKAGEREPO%% %%DEBIAN_VERSION%% nginx" >> /etc/apt/sources.list.d/nginx.list \ && apt-get update \ ;; \ diff --git a/mainline/alpine-otel/Dockerfile b/mainline/alpine-otel/Dockerfile new file mode 100644 index 0000000..2082114 --- /dev/null +++ b/mainline/alpine-otel/Dockerfile @@ -0,0 +1,85 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "update.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# +ARG IMAGE=nginxinc/nginx-unprivileged:1.27.5-alpine +FROM $IMAGE + +ENV OTEL_VERSION=0.1.2 + +ARG UID=101 +ARG GID=101 + +USER root + +RUN set -x \ + && apkArch="$(cat /etc/apk/arch)" \ + && nginxPackages=" \ + nginx=${NGINX_VERSION}-r${PKG_RELEASE} \ + nginx-module-xslt=${NGINX_VERSION}-r${DYNPKG_RELEASE} \ + nginx-module-geoip=${NGINX_VERSION}-r${DYNPKG_RELEASE} \ + nginx-module-image-filter=${NGINX_VERSION}-r${DYNPKG_RELEASE} \ + nginx-module-njs=${NGINX_VERSION}.${NJS_VERSION}-r${NJS_RELEASE} \ + nginx-module-otel=${NGINX_VERSION}.${OTEL_VERSION}-r${PKG_RELEASE} \ + " \ +# install prerequisites for public key and pkg-oss checks + && apk add --no-cache --virtual .checksum-deps \ + openssl \ + && case "$apkArch" in \ + x86_64|aarch64) \ +# arches officially built by upstream + apk add -X "https://nginx.org/packages/mainline/alpine/v$(egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" --no-cache $nginxPackages \ + ;; \ + *) \ +# we're on an architecture upstream doesn't officially build for +# let's build binaries from the published packaging sources + set -x \ + && tempDir="$(mktemp -d)" \ + && chown nobody:nobody $tempDir \ + && apk add --no-cache --virtual .build-deps \ + gcc \ + libc-dev \ + make \ + openssl-dev \ + pcre2-dev \ + zlib-dev \ + linux-headers \ + cmake \ + bash \ + alpine-sdk \ + findutils \ + curl \ + xz \ + protobuf-dev \ + grpc-dev \ + && su nobody -s /bin/sh -c " \ + export HOME=${tempDir} \ + && cd ${tempDir} \ + && curl -f -L -O https://github.com/nginx/pkg-oss/archive/${NGINX_VERSION}-${PKG_RELEASE}.tar.gz \ + && PKGOSSCHECKSUM=\"c773d98b567bd585c17f55702bf3e4c7d82b676bfbde395270e90a704dca3c758dfe0380b3f01770542b4fd9bed1f1149af4ce28bfc54a27a96df6b700ac1745 *${NGINX_VERSION}-${PKG_RELEASE}.tar.gz\" \ + && if [ \"\$(openssl sha512 -r ${NGINX_VERSION}-${PKG_RELEASE}.tar.gz)\" = \"\$PKGOSSCHECKSUM\" ]; then \ + echo \"pkg-oss tarball checksum verification succeeded!\"; \ + else \ + echo \"pkg-oss tarball checksum verification failed!\"; \ + exit 1; \ + fi \ + && tar xzvf ${NGINX_VERSION}-${PKG_RELEASE}.tar.gz \ + && cd pkg-oss-${NGINX_VERSION}-${PKG_RELEASE} \ + && cd alpine \ + && make module-otel \ + && apk index --allow-untrusted -o ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz ${tempDir}/packages/alpine/${apkArch}/*.apk \ + && abuild-sign -k ${tempDir}/.abuild/abuild-key.rsa ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz \ + " \ + && cp ${tempDir}/.abuild/abuild-key.rsa.pub /etc/apk/keys/ \ + && apk del --no-network .build-deps \ + && apk add -X ${tempDir}/packages/alpine/ --no-cache $nginxPackages \ + ;; \ + esac \ +# remove checksum deps + && apk del --no-network .checksum-deps \ +# if we have leftovers from building, let's purge them (including extra, unnecessary build deps) + && if [ -n "$tempDir" ]; then rm -rf "$tempDir"; fi \ + && if [ -f "/etc/apk/keys/abuild-key.rsa.pub" ]; then rm -f /etc/apk/keys/abuild-key.rsa.pub; fi + +USER $UID diff --git a/mainline/debian-otel/Dockerfile b/mainline/debian-otel/Dockerfile new file mode 100644 index 0000000..9939d9f --- /dev/null +++ b/mainline/debian-otel/Dockerfile @@ -0,0 +1,108 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "update.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# +ARG IMAGE=nginxinc/nginx-unprivileged:1.27.5 +FROM $IMAGE + +ENV OTEL_VERSION=0.1.2 + +ARG UID=101 +ARG GID=101 + +USER root + +RUN set -x; \ + NGINX_GPGKEY_PATH=/etc/apt/keyrings/nginx-archive-keyring.gpg; \ + dpkgArch="$(dpkg --print-architecture)" \ + && nginxPackages=" \ + nginx=${NGINX_VERSION}-${PKG_RELEASE} \ + nginx-module-xslt=${NGINX_VERSION}-${DYNPKG_RELEASE} \ + nginx-module-geoip=${NGINX_VERSION}-${DYNPKG_RELEASE} \ + nginx-module-image-filter=${NGINX_VERSION}-${DYNPKG_RELEASE} \ + nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${NJS_RELEASE} \ + nginx-module-otel=${NGINX_VERSION}+${OTEL_VERSION}-${PKG_RELEASE} \ + " \ + && case "$dpkgArch" in \ + amd64|arm64) \ +# arches officially built by upstream + echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \ + && apt-get update \ + ;; \ + *) \ +# we're on an architecture upstream doesn't officially build for +# let's build binaries from the published packaging sources +# new directory for storing sources and .deb files + tempDir="$(mktemp -d)" \ + && chmod 777 "$tempDir" \ +# (777 to ensure APT's "_apt" user can access it too) + \ +# save list of currently-installed packages so build dependencies can be cleanly removed later + && savedAptMark="$(apt-mark showmanual)" \ + \ +# build .deb files from upstream's packaging sources + && apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + curl \ + devscripts \ + equivs \ + git \ + libxml2-utils \ + lsb-release \ + xsltproc \ + && ( \ + cd "$tempDir" \ + && REVISION="${NGINX_VERSION}-${PKG_RELEASE}" \ + && REVISION=${REVISION%~*} \ + && curl -f -L -O https://github.com/nginx/pkg-oss/archive/${REVISION}.tar.gz \ + && PKGOSSCHECKSUM="c773d98b567bd585c17f55702bf3e4c7d82b676bfbde395270e90a704dca3c758dfe0380b3f01770542b4fd9bed1f1149af4ce28bfc54a27a96df6b700ac1745 *${REVISION}.tar.gz" \ + && if [ "$(openssl sha512 -r ${REVISION}.tar.gz)" = "$PKGOSSCHECKSUM" ]; then \ + echo "pkg-oss tarball checksum verification succeeded!"; \ + else \ + echo "pkg-oss tarball checksum verification failed!"; \ + exit 1; \ + fi \ + && tar xzvf ${REVISION}.tar.gz \ + && cd pkg-oss-${REVISION} \ + && cd debian \ + && for target in module-otel; do \ + make rules-$target; \ + mk-build-deps --install --tool="apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes" \ + debuild-$target/nginx-$NGINX_VERSION/debian/control; \ + done \ + && make module-otel \ + ) \ +# we don't remove APT lists here because they get re-downloaded and removed later + \ +# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies +# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) + && apt-mark showmanual | xargs apt-mark auto > /dev/null \ + && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \ + \ +# create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) + && ls -lAFh "$tempDir" \ + && ( cd "$tempDir" && dpkg-scanpackages . > Packages ) \ + && grep '^Package: ' "$tempDir/Packages" \ + && echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list \ +# work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") +# Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) +# ... +# E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) + && apt-get -o Acquire::GzipIndexes=false update \ + ;; \ + esac \ + \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + $nginxPackages \ + gettext-base \ + curl \ + && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \ + \ +# if we have leftovers from building, let's purge them (including extra, unnecessary build deps) + && if [ -n "$tempDir" ]; then \ + apt-get purge -y --auto-remove \ + && rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ + fi + +USER $UID diff --git a/mainline/debian-perl/Dockerfile b/mainline/debian-perl/Dockerfile index cf083b3..c724679 100644 --- a/mainline/debian-perl/Dockerfile +++ b/mainline/debian-perl/Dockerfile @@ -24,7 +24,7 @@ RUN set -x; \ " \ && case "$dpkgArch" in \ amd64|arm64) \ -# arches officialy built by upstream +# arches officially built by upstream echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \ && apt-get update \ ;; \ diff --git a/mainline/debian/Dockerfile b/mainline/debian/Dockerfile index 2cca5ea..9503ba7 100644 --- a/mainline/debian/Dockerfile +++ b/mainline/debian/Dockerfile @@ -51,7 +51,7 @@ RUN set -x \ " \ && case "$dpkgArch" in \ amd64|arm64) \ -# arches officialy built by upstream +# arches officially built by upstream echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \ && apt-get update \ ;; \ diff --git a/stable/alpine-otel/Dockerfile b/stable/alpine-otel/Dockerfile new file mode 100644 index 0000000..f3d1ea6 --- /dev/null +++ b/stable/alpine-otel/Dockerfile @@ -0,0 +1,85 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "update.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# +ARG IMAGE=nginxinc/nginx-unprivileged:1.28.0-alpine +FROM $IMAGE + +ENV OTEL_VERSION=0.1.2 + +ARG UID=101 +ARG GID=101 + +USER root + +RUN set -x \ + && apkArch="$(cat /etc/apk/arch)" \ + && nginxPackages=" \ + nginx=${NGINX_VERSION}-r${PKG_RELEASE} \ + nginx-module-xslt=${NGINX_VERSION}-r${DYNPKG_RELEASE} \ + nginx-module-geoip=${NGINX_VERSION}-r${DYNPKG_RELEASE} \ + nginx-module-image-filter=${NGINX_VERSION}-r${DYNPKG_RELEASE} \ + nginx-module-njs=${NGINX_VERSION}.${NJS_VERSION}-r${NJS_RELEASE} \ + nginx-module-otel=${NGINX_VERSION}.${OTEL_VERSION}-r${PKG_RELEASE} \ + " \ +# install prerequisites for public key and pkg-oss checks + && apk add --no-cache --virtual .checksum-deps \ + openssl \ + && case "$apkArch" in \ + x86_64|aarch64) \ +# arches officially built by upstream + apk add -X "https://nginx.org/packages/alpine/v$(egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" --no-cache $nginxPackages \ + ;; \ + *) \ +# we're on an architecture upstream doesn't officially build for +# let's build binaries from the published packaging sources + set -x \ + && tempDir="$(mktemp -d)" \ + && chown nobody:nobody $tempDir \ + && apk add --no-cache --virtual .build-deps \ + gcc \ + libc-dev \ + make \ + openssl-dev \ + pcre2-dev \ + zlib-dev \ + linux-headers \ + cmake \ + bash \ + alpine-sdk \ + findutils \ + curl \ + xz \ + protobuf-dev \ + grpc-dev \ + && su nobody -s /bin/sh -c " \ + export HOME=${tempDir} \ + && cd ${tempDir} \ + && curl -f -L -O https://github.com/nginx/pkg-oss/archive/${NGINX_VERSION}-${PKG_RELEASE}.tar.gz \ + && PKGOSSCHECKSUM=\"517bc18954ccf4efddd51986584ca1f37966833ad342a297e1fe58fd0faf14c5a4dabcb23519dca433878a2927a95d6bea05a6749ee2fa67a33bf24cdc41b1e4 *${NGINX_VERSION}-${PKG_RELEASE}.tar.gz\" \ + && if [ \"\$(openssl sha512 -r ${NGINX_VERSION}-${PKG_RELEASE}.tar.gz)\" = \"\$PKGOSSCHECKSUM\" ]; then \ + echo \"pkg-oss tarball checksum verification succeeded!\"; \ + else \ + echo \"pkg-oss tarball checksum verification failed!\"; \ + exit 1; \ + fi \ + && tar xzvf ${NGINX_VERSION}-${PKG_RELEASE}.tar.gz \ + && cd pkg-oss-${NGINX_VERSION}-${PKG_RELEASE} \ + && cd alpine \ + && make module-otel \ + && apk index --allow-untrusted -o ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz ${tempDir}/packages/alpine/${apkArch}/*.apk \ + && abuild-sign -k ${tempDir}/.abuild/abuild-key.rsa ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz \ + " \ + && cp ${tempDir}/.abuild/abuild-key.rsa.pub /etc/apk/keys/ \ + && apk del --no-network .build-deps \ + && apk add -X ${tempDir}/packages/alpine/ --no-cache $nginxPackages \ + ;; \ + esac \ +# remove checksum deps + && apk del --no-network .checksum-deps \ +# if we have leftovers from building, let's purge them (including extra, unnecessary build deps) + && if [ -n "$tempDir" ]; then rm -rf "$tempDir"; fi \ + && if [ -f "/etc/apk/keys/abuild-key.rsa.pub" ]; then rm -f /etc/apk/keys/abuild-key.rsa.pub; fi + +USER $UID diff --git a/stable/debian-otel/Dockerfile b/stable/debian-otel/Dockerfile new file mode 100644 index 0000000..4eb0b52 --- /dev/null +++ b/stable/debian-otel/Dockerfile @@ -0,0 +1,108 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "update.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# +ARG IMAGE=nginxinc/nginx-unprivileged:1.28.0 +FROM $IMAGE + +ENV OTEL_VERSION=0.1.2 + +ARG UID=101 +ARG GID=101 + +USER root + +RUN set -x; \ + NGINX_GPGKEY_PATH=/etc/apt/keyrings/nginx-archive-keyring.gpg; \ + dpkgArch="$(dpkg --print-architecture)" \ + && nginxPackages=" \ + nginx=${NGINX_VERSION}-${PKG_RELEASE} \ + nginx-module-xslt=${NGINX_VERSION}-${DYNPKG_RELEASE} \ + nginx-module-geoip=${NGINX_VERSION}-${DYNPKG_RELEASE} \ + nginx-module-image-filter=${NGINX_VERSION}-${DYNPKG_RELEASE} \ + nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${NJS_RELEASE} \ + nginx-module-otel=${NGINX_VERSION}+${OTEL_VERSION}-${PKG_RELEASE} \ + " \ + && case "$dpkgArch" in \ + amd64|arm64) \ +# arches officially built by upstream + echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \ + && apt-get update \ + ;; \ + *) \ +# we're on an architecture upstream doesn't officially build for +# let's build binaries from the published packaging sources +# new directory for storing sources and .deb files + tempDir="$(mktemp -d)" \ + && chmod 777 "$tempDir" \ +# (777 to ensure APT's "_apt" user can access it too) + \ +# save list of currently-installed packages so build dependencies can be cleanly removed later + && savedAptMark="$(apt-mark showmanual)" \ + \ +# build .deb files from upstream's packaging sources + && apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + curl \ + devscripts \ + equivs \ + git \ + libxml2-utils \ + lsb-release \ + xsltproc \ + && ( \ + cd "$tempDir" \ + && REVISION="${NGINX_VERSION}-${PKG_RELEASE}" \ + && REVISION=${REVISION%~*} \ + && curl -f -L -O https://github.com/nginx/pkg-oss/archive/${REVISION}.tar.gz \ + && PKGOSSCHECKSUM="517bc18954ccf4efddd51986584ca1f37966833ad342a297e1fe58fd0faf14c5a4dabcb23519dca433878a2927a95d6bea05a6749ee2fa67a33bf24cdc41b1e4 *${REVISION}.tar.gz" \ + && if [ "$(openssl sha512 -r ${REVISION}.tar.gz)" = "$PKGOSSCHECKSUM" ]; then \ + echo "pkg-oss tarball checksum verification succeeded!"; \ + else \ + echo "pkg-oss tarball checksum verification failed!"; \ + exit 1; \ + fi \ + && tar xzvf ${REVISION}.tar.gz \ + && cd pkg-oss-${REVISION} \ + && cd debian \ + && for target in module-otel; do \ + make rules-$target; \ + mk-build-deps --install --tool="apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes" \ + debuild-$target/nginx-$NGINX_VERSION/debian/control; \ + done \ + && make module-otel \ + ) \ +# we don't remove APT lists here because they get re-downloaded and removed later + \ +# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies +# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) + && apt-mark showmanual | xargs apt-mark auto > /dev/null \ + && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \ + \ +# create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) + && ls -lAFh "$tempDir" \ + && ( cd "$tempDir" && dpkg-scanpackages . > Packages ) \ + && grep '^Package: ' "$tempDir/Packages" \ + && echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list \ +# work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") +# Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) +# ... +# E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) + && apt-get -o Acquire::GzipIndexes=false update \ + ;; \ + esac \ + \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + $nginxPackages \ + gettext-base \ + curl \ + && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \ + \ +# if we have leftovers from building, let's purge them (including extra, unnecessary build deps) + && if [ -n "$tempDir" ]; then \ + apt-get purge -y --auto-remove \ + && rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ + fi + +USER $UID diff --git a/stable/debian-perl/Dockerfile b/stable/debian-perl/Dockerfile index 9d11815..89777a7 100644 --- a/stable/debian-perl/Dockerfile +++ b/stable/debian-perl/Dockerfile @@ -24,7 +24,7 @@ RUN set -x; \ " \ && case "$dpkgArch" in \ amd64|arm64) \ -# arches officialy built by upstream +# arches officially built by upstream echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \ && apt-get update \ ;; \ diff --git a/stable/debian/Dockerfile b/stable/debian/Dockerfile index 7217d8b..ec7a4e9 100644 --- a/stable/debian/Dockerfile +++ b/stable/debian/Dockerfile @@ -51,7 +51,7 @@ RUN set -x \ " \ && case "$dpkgArch" in \ amd64|arm64) \ -# arches officialy built by upstream +# arches officially built by upstream echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \ && apt-get update \ ;; \ diff --git a/update.sh b/update.sh index 1b5fcf0..9db599a 100755 --- a/update.sh +++ b/update.sh @@ -29,6 +29,12 @@ declare -A njspkg=( [stable]='1' ) +# Current otel versions +declare -A otel=( + [mainline]='0.1.2' + [stable]='0.1.2' +) + # Current nginx package patchlevel version # Remember to update pkgosschecksum when changing this. declare -A pkg=( @@ -75,6 +81,8 @@ get_packages() { shift local branch="$1" shift + local bn="" + local otel= local perl= local r= local sep= @@ -93,6 +101,10 @@ get_packages() { *-perl) perl="nginx-module-perl" ;; + *-otel) + otel="nginx-module-otel" + bn="\n" + ;; esac echo -n ' \\\n' @@ -110,16 +122,21 @@ get_packages() { echo -n ' '"$p"'=${NGINX_VERSION}-'"$r"'${DYNPKG_RELEASE} \\\n' done for p in nginx-module-njs; do - echo -n ' '"$p"'=${NGINX_VERSION}'"$sep"'${NJS_VERSION}-'"$r"'${NJS_RELEASE} \\' + echo -n ' '"$p"'=${NGINX_VERSION}'"$sep"'${NJS_VERSION}-'"$r"'${NJS_RELEASE} \\'"$bn" + done + for p in $otel; do + echo -n ' '"$p"'=${NGINX_VERSION}'"$sep"'${OTEL_VERSION}-'"$r"'${PKG_RELEASE} \\' done ;; esac } get_packagerepo() { - local distro="${1%-perl}" - distro="${distro%-slim}" + local distro="$1" shift + distro="${distro%-perl}" + distro="${distro%-otel}" + distro="${distro%-slim}" local branch="$1" shift @@ -129,8 +146,11 @@ get_packagerepo() { } get_packagever() { - local distro="${1%-perl}" + local distro="$1" shift + distro="${distro%-perl}" + distro="${distro%-otel}" + distro="${distro%-slim}" local branch="$1" shift local package="$1" @@ -154,6 +174,7 @@ get_packagever() { get_buildtarget() { local distro="$1" + shift case "$distro" in alpine-slim) echo base @@ -167,6 +188,9 @@ get_buildtarget() { *-perl) echo module-perl ;; + *-otel) + echo module-otel + ;; esac } @@ -182,15 +206,15 @@ __EOF__ for branch in "${branches[@]}"; do for variant in \ - alpine{,-perl,-slim} \ - debian{,-perl}; do + alpine{,-perl,-otel,-slim} \ + debian{,-perl,-otel}; do echo "$branch: $variant dockerfiles" dir="$branch/$variant" variant="$(basename "$variant")" [ -d "$dir" ] || continue - template="Dockerfile-${variant%}.template" + template="Dockerfile-${variant}.template" { generated_warning cat "$template" @@ -200,6 +224,7 @@ for branch in "${branches[@]}"; do alpinever="${alpine[$branch]}" nginxver="${nginx[$branch]}" njsver="${njs[${branch}]}" + otelver="${otel[${branch}]}" revver="${rev[${branch}]}" pkgosschecksumver="${pkgosschecksum[${branch}]}" @@ -217,6 +242,7 @@ for branch in "${branches[@]}"; do -e 's,%%NGINX_VERSION%%,'"$nginxver"',' \ -e 's,%%NJS_VERSION%%,'"$njsver"',' \ -e 's,%%NJS_RELEASE%%,'"$njspkgver"',' \ + -e 's,%%OTEL_VERSION%%,'"$otelver"',' \ -e 's,%%PKG_RELEASE%%,'"$packagever"',' \ -e 's,%%PACKAGES%%,'"$packages"',' \ -e 's,%%PACKAGEREPO%%,'"$packagerepo"',' \ @@ -225,7 +251,7 @@ for branch in "${branches[@]}"; do -e 's,%%BUILDTARGET%%,'"$buildtarget"',' \ "$dir/Dockerfile" - done + done for variant in \ alpine-slim \