{"id":16963284,"url":"https://github.com/ruzickap/container-build","last_synced_at":"2025-10-08T09:31:24.522Z","repository":{"id":63583057,"uuid":"557166774","full_name":"ruzickap/container-build","owner":"ruzickap","description":"Container build repository","archived":false,"fork":false,"pushed_at":"2025-01-12T01:14:38.000Z","size":281,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-12T02:25:49.804Z","etag":null,"topics":["container","containers","cosign","docker","docker-image","image","pipeline","scan","security","trivy"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruzickap.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-25T07:39:51.000Z","updated_at":"2024-12-29T01:13:40.000Z","dependencies_parsed_at":"2023-10-17T06:47:06.014Z","dependency_job_id":"3d64a0f0-b7e7-4d17-9bf8-48fc6e6c07fa","html_url":"https://github.com/ruzickap/container-build","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fcontainer-build","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fcontainer-build/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fcontainer-build/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fcontainer-build/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruzickap","download_url":"https://codeload.github.com/ruzickap/container-build/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235700108,"owners_count":19031668,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container","containers","cosign","docker","docker-image","image","pipeline","scan","security","trivy"],"created_at":"2024-10-13T23:24:15.004Z","updated_at":"2025-10-08T09:31:19.253Z","avatar_url":"https://github.com/ruzickap.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Container build process\n\n[![container-build](https://github.com/ruzickap/container-build/actions/workflows/container-build.yml/badge.svg)](https://github.com/ruzickap/container-build/actions/workflows/container-build.yml)\n\nThe source code was taken from: \u003chttps://github.com/paulbouwer/hello-kubernetes\u003e\n\nRepository with images: \u003chttps://quay.io/repository/petr_ruzicka/myc-hello-kubernetes?tab=tags\u003e\n\n## Requirements\n\n### Generic\n\n- Multiple Dockerfile files / sources in one git repository\n- Multi-arch container images for each Dockerfile\n- Image should be signed ([cosign](https://github.com/sigstore/cosign))\n- [SBOM](https://www.cisa.gov/sbom) (Software Bill Of Materials)\n- [SLSA Provenance](https://slsa.dev/provenance/v0.1)\n- Build process should never overwrite existing tags (1.2.3) in container\n  repository (doesn't apply for \"latest\" or \"br-\")\n- Container image should be scanned for \"Critical\" vulnerabilities before it\n  is pushed to container registry\n- There should be a way to push container to registry also with CRITICAL\n  vulnerabilities (how to progress when there are CRITICAL vulnerabilities which\n  can not be fixed \"immediately\")\n  - Set `container_image_vulnerability_checks=false`\n\n### Tag specific\n\n- I want to build test container for specific PR / branch with expiration date\n- I want to build only `latest` tag manually (form `main` branch)\n- Newly released images must create/update following tags in container\n  repository (example):\n  - `1`\n  - `1.2`\n  - `1.2.1`\n  - `latest`\n\n## Local tests\n\nBuild commands:\n\n```bash\ndocker build -f ./src/app/Dockerfile -t myc-hello-kubernetes:latest src/app\ndocker build -f ./src/app/Dockerfile-node-18-alpine -t myc-hello-kubernetes:latest-alpine src/app\ndocker build -f ./src/app/Dockerfile-node-18-debian-slim -t myc-hello-kubernetes:latest-debian-slim src/app\ndocker build -f ./src/app/Dockerfile-nodejs18-distroless -t myc-hello-kubernetes:latest-distroless src/app\ndocker build -f ./src/app/Dockerfile-nodejs-16-ubi -t myc-hello-kubernetes:latest-ubi src/app\n```\n\nRun commands:\n\n```bash\ndocker run -p 8080:8080 --rm myc-hello-kubernetes:latest\ndocker run -p 8080:8080 --rm myc-hello-kubernetes:latest-alpine\ndocker run -p 8080:8080 --rm myc-hello-kubernetes:latest-debian-slim\ndocker run -p 8080:8080 --rm myc-hello-kubernetes:latest-distroless\ndocker run -p 8080:8080 --rm myc-hello-kubernetes:latest-ubi\n\ncurl http://localhost:8080/\n```\n\nDebug container:\n\n```bash\ndocker run -it --rm --entrypoint=/bin/sh --user root -p 8080:8080 myc-hello-kubernetes:latest\n```\n\nRun in Kubernetes:\n\n```bash\nkubectl run myc-hello-kubernetes --image=quay.io/petr_ruzicka/myc-hello-kubernetes\n```\n\n## Cosign - verify signatures / SBOMs\n\nExample repositories:\n\n- \u003chttps://quay.io/repository/cilium/cilium?tab=tags\u003e\n- \u003chttps://quay.io/repository/metallb/controller?tab=tags\u003e\n- \u003chttps://quay.io/repository/kubescape/kubescape?tab=tags\u003e\n- \u003chttps://quay.io/repository/costoolkit/elemental-operator?tab=tags\u0026tag=latest\u003e\n- \u003chttps://hub.docker.com/r/bridgecrew/checkov/tags\u003e\n\nNotes:\n\n- [Attest and verify artifacts](https://rewanthtammana.com/sigstore-the-easy-way/cosign/attest-and-verify-artifacts/)\n- \u003chttps://github.com/marco-lancini/utils/blob/main/ci/github/docker-build-sign-sbom/reusable-docker.yml\u003e\n\nTest commands:\n\n```bash\nIMAGE=\"bridgecrew/checkov\"\nIMAGE=\"quay.io/petr_ruzicka/malware-cryptominer-container:2.0.0\"\nIMAGE=\"ghcr.io/external-secrets/external-secrets:v0.7.1\"\n\ndocker buildx imagetools inspect \"${IMAGE}\"\ncosign verify \"${IMAGE}\" | jq\ncosign verify \"${IMAGE}\" | jq -r '.[].optional| .Issuer + \" | \" + .Subject + \" | \" + .githubWorkflowRef + \" | https://rekor.tlog.dev/?logIndex=\" + (.Bundle.Payload.logIndex|tostring)'\ncosign triangulate \"${IMAGE}\"\ncosign tree \"${IMAGE}\"\ncosign verify-attestation --type slsaprovenance \"${IMAGE}\"\ncosign verify-attestation --type slsaprovenance \"${IMAGE}\" | jq '.payload |= @base64d | .payload | fromjson'\ncosign verify-attestation --type cyclonedx \"${IMAGE}\"\ncosign verify-attestation --type cyclonedx \"${IMAGE}\" | jq '.payload |= @base64d | .payload | fromjson'\ntrivy image --debug --sbom-sources rekor \"${IMAGE}\"\ncosign verify-attestation --type cyclonedx \"${IMAGE}\" | jq -r '.payload' | base64 -d | jq -r '.predicate.Data' \u003e /tmp/sbom.cdx.json\ntrivy sbom /tmp/sbom.cdx.json\ntrivy image --scanners license \"${IMAGE}\"\ntrivy image --compliance docker-cis \"${IMAGE}\"\ntrivy image --scanners none --image-config-scanners config \"${IMAGE}\"\ntrivy image --scanners none --image-config-scanners secret \"${IMAGE}\"\n```\n\nTest commands with other images:\n\n```bash\nIMAGE=\"registry.k8s.io/kube-apiserver-amd64:v1.24.0\"\nIMAGE=\"quay.io/petr_ruzicka/malware-cryptominer-container:2.0.0\"\nIMAGE=\"quay.io/cilium/cilium:v1.13.0\"\nIMAGE=\"quay.io/metallb/controller:latest\"\nIMAGE=\"quay.io/costoolkit/elemental-operator:v1.1.0\"\nIMAGE=\"ghcr.io/fluxcd/source-controller:v0.34.0\"\nIMAGE=\"bridgecrew/checkov\"\n\nskopeo inspect --raw \"docker://${IMAGE}\"\ncosign verify \"${IMAGE}\" | jq\ncosign verify \"${IMAGE}\" | jq -r '.[].optional| .Issuer + \"-\" + .Subject'\ncosign triangulate \"${IMAGE}\"\ncosign tree \"${IMAGE}\"\n\nrekor-cli get --uuid 68a53d0e75463d805dc9437dda5815171502475dd704459a5ce3078edba96226 --format json | jq -r .Attestation | base64 --decode | jq\ncurl -s https://rekor.sigstore.dev/api/v1/log/entries/68a53d0e75463d805dc9437dda5815171502475dd704459a5ce3078edba96226 | jq\n\nrekor-cli search --email petr.ruzicka@gmail.com\n# https://rekor.tlog.dev/?email=petr.ruzicka@gmail.com\n\nrekor-cli get --log-index 8757761\n\ndocker manifest inspect \"${IMAGE}\"\ncosign download sbom --platform=linux/amd64 ghcr.io/google/ko\ncosign download sbom --platform=linux/amd64 cgr.dev/chainguard/node\ncosign download sbom \"${IMAGE}\"\n\n# Image Manifest\ncurl -s -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \"https://quay.io/v2/jetstack/cert-manager-controller/manifests/v1.9.1\" | jq\n# Manifest List\ncurl -s -H 'Accept: application/vnd.docker.distribution.manifest.list.v2+json' \"https://quay.io/v2/jetstack/cert-manager-controller/manifests/v1.9.1\" | jq\ncurl -s -H 'Accept: application/vnd.oci.image.index.v1+json' \"https://quay.io/v2/jetstack/cert-manager-controller/manifests/v1.9.1\" | jq\n\n# Verify SBOM attestation\ncosign verify-attestation --type cyclonedx bridgecrew/checkov | jq '.payload |= @base64d | .payload | fromjson | select(.predicateType == \"https://cyclonedx.org/schema\") | .predicate.Data'\ncosign verify-attestation --type slsaprovenance --key https://ftp.suse.com/pub/projects/security/keys/container–key.pem registry.suse.com/bci/golang@sha256:35bc38ce40811b587a56bcfa328ef077c0703732e3bbedf4dbdf47f612cca04b | jq # DevSkim: ignore DS117838\ncosign verify-attestation --type slsaprovenance ghcr.io/thomasvitale/band-service@sha256:388e8d292b55a7934bdaf11277ea9f33c3533258de92eb4b12085717dbdbd875 | jq '.payload |= @base64d | .payload | fromjson'\n\ndocker manifest inspect quay.io/jetstack/cert-manager-controller:v1.9.1\n\nslsa-verifier verify-image \"ghcr.io/chgl/kube-powertools@sha256:b76dc742957ae883f3ed0c4fe89b54d5c9a9de69a8bc531f9ee12ec995dab10d\" --source-uri github.com/chgl/kube-powertools\n\n# https://unifiedguru.com/highlights-from-the-buildkit-v0-11-release-docker/\ndocker buildx imagetools inspect moby/buildkit:latest --format '{{ json .Provenance }}'\ndocker buildx imagetools inspect moby/buildkit:latest --format '{{ json (index .Provenance \"linux/amd64\").SLSA.invocation.configSource }}'\ndocker buildx imagetools inspect moby/buildkit:latest --format '{{ (index .Provenance \"linux/amd64\").SLSA.builder.id }}'\ndocker buildx imagetools inspect moby/buildkit:latest --format '{{ range (index .SBOM \"linux/amd64\").SPDX.packages }}{{ println .name }}{{ end }}'\n\ndocker buildx imagetools inspect ghcr.io/fluxcd/source-controller:v0.34.0 --format \"{{ json (index .Provenance \\\"linux/amd64\\\").SLSA}}\"\ndocker buildx imagetools inspect ghcr.io/fluxcd/source-controller:v0.34.0 --format \"{{ json (index .SBOM \\\"linux/amd64\\\").SPDX}}\"\ndocker sbom fluxcd/source-controller:v0.34.0\n\n# https://registry-ui.chainguard.app/?image=quay.io/petr_ruzicka/malware-cryptominer-container:1\n# https://registry-ui.chainguard.app/?image=cgr.dev/chainguard/nginx:latest\n\ncosign verify --certificate-github-workflow-repository cilium/cilium --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-github-workflow-name \"Image Release Build\" --certificate-github-workflow-ref refs/tags/v1.13.0 quay.io/cilium/cilium:v1.13.0 | jq\ncosign verify --certificate-github-workflow-repository cilium/cilium --certificate-oidc-issuer https://token.actions.githubusercontent.com --attachment sbom quay.io/cilium/cilium:v1.13.0 | jq\n```\n\n## Container scanners\n\nI was looking for the vulnerability which affects only the specific architecture\n(for example: `arm`):\n\n\u003chttps://security.snyk.io/vuln/SNYK-DEBIAN10-GLIBC-564233\u003e\n\n```bash\ntrivy image --severity HIGH,CRITICAL --platform=linux/amd64 node:18.10.0-buster-slim | grep CVE-2020-6096\ntrivy image --severity HIGH,CRITICAL --platform=linux/arm64 node:18.10.0-buster-slim | grep CVE-2020-6096\n```\n\n## Possible build examples\n\n- Build container images with tag latest form main branch and ignore\n  vulnerability scanners\n\n  ```bash\n  gh workflow run container-build.yml -f container_registry_push=true -f container_image_expires_after=30 -f container_image_skip_vulnerability_checks=true\n  sleep 100\n  ```\n\n- Tag \"main\" branch\n\n  ```bash\n  TAG=\"8.0.55\"\n\n  git tag \"v${TAG}-beta.0\" \u0026\u0026 git push origin \"v${TAG}-beta.0\"\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  # In case some containers has security vulnerabilities they will not be pushed to Container Registry by default\n  # If you want to do a force push please use something like:\n  gh workflow run container-build.yml --ref=\"v${TAG}-beta.0\" -f container_registry_push=true -f container_image_expires_after=365 -f container_image_skip_vulnerability_checks=true\n  sleep 100\n\n  git tag \"v${TAG}-beta.1\" \u0026\u0026 git push origin \"v${TAG}-beta.1\"\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  gh workflow run container-build.yml --ref=\"v${TAG}-beta.1\" -f container_registry_push=true -f container_image_expires_after=365 -f container_image_skip_vulnerability_checks=true\n  sleep 100\n\n  git tag \"v${TAG}-rc.0\" \u0026\u0026 git push origin \"v${TAG}-rc.0\"\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  gh workflow run container-build.yml --ref=\"v${TAG}-rc.0\" -f container_registry_push=true -f container_image_expires_after=365 -f container_image_skip_vulnerability_checks=true\n  sleep 100\n\n  git tag \"v${TAG}-rc.1\" \u0026\u0026 git push origin \"v${TAG}-rc.1\"\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  gh workflow run container-build.yml --ref=\"v${TAG}-rc.1\" -f container_registry_push=true -f container_image_expires_after=365 -f container_image_skip_vulnerability_checks=true\n  sleep 100\n\n  git tag \"v${TAG}\" \u0026\u0026 git push origin \"v${TAG}\"\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  gh workflow run container-build.yml --ref=\"v${TAG}\" -f container_registry_push=true -f container_image_expires_after=365 -f container_image_skip_vulnerability_checks=true\n  ```\n\n- Run build process form \"main\" branch - expires in 300 days\n\n  ```bash\n  gh workflow run container-build.yml -f container_registry_push=true -f container_image_expires_after=300 -f container_image_skip_vulnerability_checks=true\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  ```\n\n- Run build process form \"fix\" branch - expires in 30 days (manual workflow\n  execution is needed)\n\n  ```bash\n  git checkout -b fix \u0026\u0026 git push\n  gh workflow run container-build.yml --ref=fix -f container_registry_push=true -f container_image_expires_after=30 -f container_image_skip_vulnerability_checks=true\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  git checkout main \u0026\u0026 git branch -d fix \u0026\u0026 git push origin -d fix\n  ```\n\n- Run build process form \"fix2\" branch form PR - expires in 30 days\n  (manual workflow execution is needed)\n\n  ```bash\n  git checkout -b fix2\n  date \u003e date.txt\n  git add date.txt \u0026\u0026 git commit -m \"fix(container-build): date\" \u0026\u0026 git push\n  PR_URL=$(gh pr create --fill)\n  gh workflow run container-build.yml --ref=fix2 -f container_registry_push=true -f container_image_expires_after=30 -f container_image_skip_vulnerability_checks=true\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  date \u003e date.txt\n  git add date.txt \u0026\u0026 git commit -m \"fix(container-build): date2\" \u0026\u0026 git push\n  gh workflow run container-build.yml --ref=fix2 -f container_registry_push=true -f container_image_expires_after=30 -f container_image_skip_vulnerability_checks=true\n  sleep 10\n  WORKLOAD_ID=$(gh run list --workflow=container-build.yml --limit 1 --json databaseId | jq -r '.[].databaseId')\n  gh run watch \"${WORKLOAD_ID}\"\n  gh pr close --delete-branch \"${PR_URL}\"\n  ```\n\n- Scheduled build - expires in 300 days\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruzickap%2Fcontainer-build","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruzickap%2Fcontainer-build","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruzickap%2Fcontainer-build/lists"}