Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build multi arch images #163

Merged
merged 1 commit into from
Sep 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 110 additions & 36 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,33 @@ on:
schedule:
- cron: '0 0 * * 0'
jobs:
supported-arch-matrix:
name: Supported processor architectures
runs-on: ubuntu-latest
needs:
- lint-dockerfile
outputs:
arch: ${{ steps.supported-arch-matrix.outputs.arch }}
steps:
- uses: actions/checkout@v4
- id: supported-arch-matrix
name: Generate Arch
run: |
echo "arch=[\"linux/amd64\",\"linux/arm64\"]" >> $GITHUB_OUTPUT
registry-matrix:
name: Extract registries from registry secret mapping
if: (github.event_name == 'push' || github.event_name == 'schedule') && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
needs:
- tests
outputs:
registry: ${{ steps.registry-matrix.outputs.registry }}
steps:
- uses: actions/checkout@v4
- id: registry-matrix
name: Extract registries from registry secret mapping
run: |
echo "::set-output name=registry::$(printenv DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING | jq -c 'keys')"
echo "registry=$(printenv DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING | jq -c 'keys')" >> $GITHUB_OUTPUT
generate-image-strategy:
name: Generate Image Strategy
runs-on: ubuntu-latest
Expand All @@ -30,10 +46,12 @@ jobs:
run: |
ls images | jq -csR '. + "random" | split("\n")' > images.list
cat images.list
echo "::set-output name=images::$(cat images.list)"
echo "images=$(cat images.list)" >> $GITHUB_OUTPUT
generate-rule-strategy:
name: Generate Rules Strategy
runs-on: ubuntu-latest
needs:
- scan-vulnerability
outputs:
rules: ${{ steps.generate-rule-strategy.outputs.rules }}
steps:
Expand All @@ -43,7 +61,7 @@ jobs:
run: |
ls tests/rules | jq -csR '. | rtrimstr("\n") | split("\n")' > rules.list
cat rules.list
echo "::set-output name=rules::$(cat rules.list)"
echo "rules=$(cat rules.list)" >> $GITHUB_OUTPUT
lint-dockerfile:
name: Lint ${{ matrix.image }}'s Dockerfile
needs:
Expand All @@ -63,77 +81,107 @@ jobs:
entrypoint: hadolint
args: ./images/${{ matrix.image }}/Dockerfile
build-docker-image:
name: Build ${{ matrix.image }} Docker
name: Build ${{ matrix.image }} Docker (${{ matrix.platform }})
strategy:
fail-fast: false
matrix:
platform: ${{ fromJson(needs.supported-arch-matrix.outputs.arch) }}
image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }}
needs:
- supported-arch-matrix
- generate-image-strategy
- lint-dockerfile
runs-on: ubuntu-latest
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY_IMAGE }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- uses: actions/checkout@v4
- run: cp -R $(echo -e "./images/$(ls ./images/ | shuf -n 1)") ./images/random
if: matrix.image == 'random'
- run: docker image build --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` --build-arg VCS_REF=`git rev-parse --short HEAD` -t "${DOCKER_IMAGE}:${{ matrix.image }}" --no-cache --build-arg VERSION=$TAG_VERSION ./images/${{ matrix.image }}/
- run: mkdir ./docker-image
- run: docker save "${DOCKER_IMAGE}:${{ matrix.image }}" -o ./docker-image/docker_image.tar
- uses: actions/upload-artifact@master
- run: docker image build --platform=${{ matrix.platform }} --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` --build-arg VCS_REF=`git rev-parse --short HEAD` -t "${DOCKER_IMAGE}:${{ matrix.image }}-${{ env.PLATFORM_PAIR }}" --no-cache --build-arg VERSION=$TAG_VERSION ./images/${{ matrix.image }}/
- run: docker save "${DOCKER_IMAGE}:${{ matrix.image }}-${{ env.PLATFORM_PAIR }}" -o ./docker-image/docker_image-${{ env.PLATFORM_PAIR }}.tar
- uses: actions/upload-artifact@v4
with:
name: docker-image-${{ matrix.image }}
name: docker-image-${{ matrix.image }}-${{ env.PLATFORM_PAIR }}
path: ./docker-image
scan-vulnerability:
name: Scan ${{ matrix.image }} for vulnerabilities
name: Scan ${{ matrix.image }} for vulnerabilities (${{ matrix.platform }})
strategy:
fail-fast: false
matrix:
platform: ${{ fromJson(needs.supported-arch-matrix.outputs.arch) }}
image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }}
needs:
- supported-arch-matrix
- generate-image-strategy
- build-docker-image
runs-on: ubuntu-latest
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- uses: actions/checkout@v4
- uses: actions/download-artifact@master
- uses: actions/download-artifact@v4
with:
name: docker-image-${{ matrix.image }}
path: ./docker-image
- run: docker load --input ./docker-image/docker_image.tar
- run: rm -Rf ./docker-image/
- run: echo -e "${DOCKER_IMAGE}:${{ matrix.image }}" | xargs -I % sh -c 'docker run -v /tmp/trivy:/var/lib/trivy -v /var/run/docker.sock:/var/run/docker.sock -t aquasec/trivy:latest --cache-dir /var/lib/trivy image --exit-code 1 --no-progress --format table %'
name: docker-image-${{ matrix.image }}-${{ env.PLATFORM_PAIR }}
path: /tmp/docker-image
- run: docker load --input /tmp/docker-image/docker_image-${{ env.PLATFORM_PAIR }}.tar
- run: rm -Rf /tmp/docker-image/
- run: echo -e "${{ env.DOCKER_IMAGE }}:${{ matrix.image }}-${{ env.PLATFORM_PAIR }}" | xargs -I % sh -c 'docker run -v /tmp/trivy:/var/lib/trivy -v /var/run/docker.sock:/var/run/docker.sock -t aquasec/trivy:latest --cache-dir /var/lib/trivy image --exit-code 1 --no-progress --format table %'
tests:
name: Test ${{ matrix.image }} against ${{ matrix.rule }}
name: Test ${{ matrix.image }} against ${{ matrix.rule }} (${{ matrix.platform }})
needs:
- supported-arch-matrix
- generate-image-strategy
- generate-rule-strategy
- scan-vulnerability
strategy:
fail-fast: false
matrix:
platform: ${{ fromJson(needs.supported-arch-matrix.outputs.arch) }}
image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }}
rule: ${{ fromJson(needs.generate-rule-strategy.outputs.rules) }}
runs-on: ubuntu-latest
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- uses: actions/checkout@v4
- uses: actions/download-artifact@master
- uses: actions/download-artifact@v4
with:
name: docker-image-${{ matrix.image }}
path: ./docker-image
- run: docker load --input ./docker-image/docker_image.tar
- name: Start image ${{ matrix.image }}
run: docker run -d --rm -v ${GITHUB_WORKSPACE}/${REDIRECT_CONFIG_FILE}:/etc/redirect/config.yaml ${DOCKER_IMAGE}:${{ matrix.image }}
name: docker-image-${{ matrix.image }}-${{ env.PLATFORM_PAIR }}
path: /tmp/docker-image
- run: docker load --input /tmp/docker-image/docker_image-${{ env.PLATFORM_PAIR }}.tar
- run: docker image ls -a
- name: Start image ${{ matrix.image }} (${{ matrix.platform }})
run: docker run -d --platform=${{ matrix.platform }} --rm -v ${GITHUB_WORKSPACE}/${REDIRECT_CONFIG_FILE}:/etc/redirect/config.yaml ${{ env.DOCKER_IMAGE }}:${{ matrix.image }}-${{ env.PLATFORM_PAIR }}
env:
IMAGE: ${{ steps.build.outputs.tag }}
REDIRECT_CONFIG_FILE: tests/rules/${{ matrix.rule }}/config.yaml
- name: Get running image ID
id: ps
run: printf "::set-output name=id::%s" $(docker ps --format "{{.ID}}")
run: printf "id=%s" $(docker ps --format "{{.ID}}") >> $GITHUB_OUTPUT
env:
IMAGE: ${{ steps.build.outputs.tag }}
- name: Get running image IP
id: inspect
run: printf "::set-output name=ip::%s" $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${IMAGE_ID})
run: printf "ip=%s" $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${IMAGE_ID}) >> $GITHUB_OUTPUT
env:
IMAGE_ID: ${{ steps.ps.outputs.id }}
- name: Sleep 13 seconds before attempting to connect
Expand All @@ -147,14 +195,14 @@ jobs:
env:
IMAGE_IP: ${{ steps.inspect.outputs.ip }}
- name: Run unit tests ${{ matrix.rule }} against ${{ matrix.image }}
run: docker run -i loadimpact/k6 run -u 1000 -d 30s -e IMAGE_IP=${IMAGE_IP} -< ${SCRIPT_FILEIMAGE}
run: docker run -i loadimpact/k6 run -u 100 -d 30s -e IMAGE_IP=${IMAGE_IP} -< ${SCRIPT_FILEIMAGE}
env:
IMAGE: ${{ matrix.image }}
IMAGE_IP: ${{ steps.inspect.outputs.ip }}
IMAGE_ID: ${{ steps.ps.outputs.id }}
SCRIPT_FILEIMAGE: ./tests/rules/${{ matrix.rule }}/unit.js
- name: Run metrics tests ${{ matrix.rule }} against ${{ matrix.image }}
run: docker run -i loadimpact/k6 run -u 10 -d 10s -e IMAGE_IP=${IMAGE_IP} -< ${SCRIPT_FILEIMAGE}
run: docker run -i loadimpact/k6 run -u 1 -d 10s -e IMAGE_IP=${IMAGE_IP} -< ${SCRIPT_FILEIMAGE}
env:
IMAGE: ${{ matrix.image }}
IMAGE_IP: ${{ steps.inspect.outputs.ip }}
Expand All @@ -173,17 +221,43 @@ jobs:
registry: ${{ fromJson(needs.registry-matrix.outputs.registry) }}
image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }}
needs:
- supported-arch-matrix
- generate-image-strategy
- tests
- registry-matrix
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
- uses: actions/download-artifact@master
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
name: docker-image-${{ matrix.image }}
path: ./docker-image
- run: docker load --input ./docker-image/docker_image.tar
- run: rm -Rf ./docker-image/
driver-opts: network=host
- uses: actions/download-artifact@v4
with:
pattern: docker-image-${{ matrix.image }}-*
path: /tmp/docker-image
merge-multiple: true
- run: ls -lasth /tmp/docker-image/
- run: |
for f in /tmp/docker-image/docker_image-*.tar; do
docker load --input $f
done
- run: rm -Rf /tmp/docker-image/
- run: docker images
- run: |
archs=${{ join(fromJson(needs.supported-arch-matrix.outputs.arch), ',') }}
for arch in ${archs//,/ }
do
docker tag "${{ env.DOCKER_IMAGE }}:${{ matrix.image }}-${arch//\//-}" "localhost:5000/${{ env.DOCKER_IMAGE }}:${{ matrix.image }}-${arch//\//-}"
docker push "localhost:5000/${{ env.DOCKER_IMAGE }}:${{ matrix.image }}-${arch//\//-}"
done
- run: docker images
- name: Login to ${{ matrix.registry }}
run: |
echo "${{ env.DOCKER_PASSWORD }}" | \
Expand All @@ -195,8 +269,8 @@ jobs:
DOCKER_PASSWORD: ${{ secrets[fromJson(env.DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING)[matrix.registry]] }}
- name: Docker info
run: docker info
- run: docker tag ${DOCKER_IMAGE}:${{ matrix.image }} ${{ matrix.registry }}/${DOCKER_IMAGE}:${{ matrix.image }}
- name: Echo full tag
run: echo -e "${{ matrix.registry }}/${DOCKER_IMAGE}:${{ matrix.image }}"
- name: Push image to Docker Hub
run: docker push "${{ matrix.registry }}/${DOCKER_IMAGE}:${{ matrix.image }}"
- name: Create merge Dockerfile
run: echo "FROM localhost:5000/${{ env.DOCKER_IMAGE }}:${{ matrix.image }}-\${TARGETOS}-\${TARGETARCH}" >> docker-file-${{ matrix.registry }}-wyrihaximusnet-redirect-${{ matrix.image }}
- run: cat docker-file-${{ matrix.registry }}-wyrihaximusnet-redirect-${{ matrix.image }}
- name: Merged different arch imags into one
run: docker buildx build -f docker-file-${{ matrix.registry }}-wyrihaximusnet-redirect-${{ matrix.image }} --platform=${{ join(fromJson(needs.supported-arch-matrix.outputs.arch), ',') }} -t ${{ matrix.registry }}/${{ env.DOCKER_IMAGE }}:${{ matrix.image }} . --push