├── .chainguard └── source.yaml ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── external-bug-or-feedback.yml │ └── new-image-request.yml ├── PULL_REQUEST_TEMPLATE.md ├── chainguard │ ├── digestabot.sts.yaml │ └── public-copy.sts.yaml ├── dependabot.yml ├── readme-template.md └── workflows │ ├── digestabot.yaml │ ├── presubmit-readme.yaml │ ├── reinstate-images.yaml │ ├── release.yaml │ ├── withdraw-images.yaml │ └── withdraw-repos.yaml ├── .gitignore ├── .terraform.lock.hcl ├── .yam.yaml ├── BEST_PRACTICES.md ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── WITHDRAWING_IMAGES.md ├── generated.tf ├── go.mod ├── go.sum ├── images ├── TEMPLATE │ ├── README.md │ ├── config │ │ └── main.tf.tpl │ ├── generated.tf │ ├── main.tf.tpl │ ├── metadata.yaml.tpl │ └── tests │ │ └── main.tf ├── apko │ ├── README.md │ ├── config │ │ └── main.tf │ ├── examples │ │ └── wolfi-base.yaml │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── aspnet-runtime │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── bash │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── busybox │ ├── README.md │ ├── config │ │ └── wolfi │ │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ ├── tests │ │ ├── main.tf │ │ └── test.sh │ └── wolfi.tf ├── cosign │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── crane │ ├── .configs │ │ └── crane.unresolved.yaml │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── smoke.sh ├── curl │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── test.sh ├── dfc │ ├── .configs │ │ └── dfc.unresolved.yaml │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── dive │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── test.sh ├── docker-dind │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── dotnet │ ├── README.md │ ├── configs │ │ ├── runtime │ │ │ └── main.tf │ │ └── sdk │ │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ ├── runtime.tf │ ├── sdk.tf │ └── tests │ │ ├── keypairs.sh │ │ ├── main.tf │ │ ├── setup.sh │ │ ├── src │ │ ├── keypair.cs │ │ └── tzdata.cs │ │ └── tzdata.sh ├── gcc-glibc │ ├── README.md │ ├── config │ │ └── main.tf │ ├── examples │ │ └── hello │ │ │ └── main.c │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── git │ ├── LICENSE │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ ├── tests │ │ ├── main.tf │ │ └── smoke.sh │ └── wolfi.tf ├── glibc-dynamic │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 01-runs.sh │ │ └── main.tf ├── go │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── hello │ │ ├── .gitignore │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ │ ├── main.tf │ │ └── smoke.sh ├── gradle │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── test.sh ├── grype │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── smoke.sh ├── haproxy │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── slim │ │ ├── haproxy.cfg │ │ ├── haproxy.yaml │ │ └── main.tf ├── helm │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── test.sh ├── hugo │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── jdk │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── jre │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── HelloWorld.java │ │ └── main.tf ├── k3s │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── k3s.tf │ ├── main.tf │ ├── metadata.yaml │ ├── static.tf │ └── tests │ │ ├── main.tf │ │ └── smoke.sh ├── ko │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── build.sh │ │ ├── example │ │ ├── go.mod │ │ └── main.go │ │ └── main.tf ├── kubectl │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── test │ │ └── config ├── laravel │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 01-fpm-server.sh │ │ ├── 02-shutdown.sh │ │ └── main.tf ├── malcontent │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── mariadb │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 02-runs.sh │ │ └── main.tf ├── maven │ ├── README.md │ ├── config │ │ └── main.tf │ ├── docs │ │ └── png │ │ │ ├── spring_initializr.png │ │ │ └── spring_whitelabel.png │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── melange │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── build.sh │ │ ├── main.tf │ │ └── minimal.yaml ├── min-toolkit-debug │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── docker-test.sh │ │ └── main.tf ├── mongodb │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── check.sh │ │ └── main.tf ├── nginx │ ├── README.md │ ├── config │ │ └── main.tf │ ├── examples │ │ └── hello-world │ │ │ └── site-content │ │ │ └── index.html │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── node │ ├── README.md │ ├── config │ │ └── main.tf │ ├── example │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ └── server.js │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 01-dockerfile.sh │ │ └── main.tf ├── openscap │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── opentelemetry-collector-contrib │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── custom-deploy-config.yaml │ │ ├── custom-ds-config.yaml │ │ └── main.tf ├── php │ ├── README.md │ ├── config │ │ ├── fpm │ │ │ └── main.tf │ │ └── main.tf │ ├── fpm.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 01-fpm-server.sh │ │ ├── 02-shutdown.sh │ │ └── main.tf ├── postgres │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ ├── query.sh │ │ └── tls.sh ├── python │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 02-check-pip.sh │ │ ├── 03-check-numpy.sh │ │ ├── 04-build.sh │ │ ├── Dockerfile │ │ ├── hello.py │ │ ├── main.tf │ │ └── requirements.txt ├── pytorch │ ├── README.md │ ├── TESTING.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ ├── model_builder.py │ └── tests │ │ ├── check-pytorch.sh │ │ ├── main.tf │ │ ├── quickstart.py │ │ └── torch_optim.py ├── redis │ ├── README.md │ ├── configs │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 02-server.sh │ │ ├── 03-server-activedefrag.sh │ │ └── main.tf ├── ruby │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 02-hello-world.sh │ │ ├── 03-base-image.sh │ │ └── main.tf ├── rust │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── smoke.sh ├── static │ ├── LICENSE │ ├── README.md │ ├── configs │ │ └── wolfi.apko.yaml │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ ├── tests │ │ ├── 01-multi-dockerfile-build.sh │ │ ├── examples │ │ │ ├── Dockerfile.c │ │ │ ├── Dockerfile.golang │ │ │ ├── Dockerfile.rust │ │ │ ├── hello.c │ │ │ └── main.go │ │ ├── main.tf │ │ └── test.sh │ └── wolfi.tf ├── stunnel │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── test.sh ├── tomcat │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── smoke.sh ├── valkey │ ├── README.md │ ├── configs │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── 02-server.sh │ │ └── main.tf ├── wait-for-it │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ └── main.tf ├── wolfi-base │ ├── README.md │ ├── config │ │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ │ ├── main.tf │ │ └── runs.sh └── wordpress │ ├── README.md │ ├── config │ └── main.tf │ ├── generated.tf │ ├── main.tf │ ├── metadata.yaml │ └── tests │ ├── main.tf │ └── test.sh ├── main.tf ├── policies ├── 01-is-signed.yaml ├── 03-has-sbom-attestation.yaml ├── 04-has-slsa-attestation.yaml ├── README.md └── main.tf ├── reinstated-images.txt ├── tflib ├── accts │ └── main.tf ├── helm-cleanup │ └── main.tf ├── imagetest │ ├── checks │ │ ├── main.tf │ │ ├── providers.tf │ │ └── variables.tf │ ├── harnesses │ │ ├── docker │ │ │ └── main.tf │ │ ├── k3s │ │ │ └── main.tf │ │ └── pterraform │ │ │ ├── .gitignore │ │ │ └── gpu │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── startup.sh.tftpl │ │ │ ├── tests │ │ │ ├── integration.tftest.hcl │ │ │ └── verify │ │ │ │ └── main.tf │ │ │ └── variables.tf │ ├── helm │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── libs │ │ ├── cypress.sh │ │ ├── libs.sh │ │ └── main.tf │ ├── playwright │ │ └── main.tf │ ├── sandboxes │ │ └── bash │ │ │ └── main.tf │ └── tests │ │ ├── docker-in-docker │ │ └── main.tf │ │ ├── eks-with-eksctl │ │ └── main.tf │ │ ├── helm │ │ ├── helm.sh │ │ ├── inventory │ │ │ └── plugin.yaml │ │ └── main.tf │ │ └── k3s-in-docker │ │ └── main.tf ├── publisher │ ├── chainguard.tf │ ├── check-reproducibility.sh │ ├── main.tf │ └── providers.tf ├── tagger │ └── main.tf └── versions │ └── main.tf ├── withdrawn-images.txt └── withdrawn-repos.txt /.chainguard/source.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Chainguard, Inc. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | spec: 5 | authorities: 6 | - keyless: 7 | # allow commits signed by users using GitHub or Google OIDC 8 | identities: 9 | - issuer: https://accounts.google.com 10 | - issuer: https://github.com/login/oauth 11 | - issuer: https://token.actions.githubusercontent.com 12 | subject: https://github.com/chainguard-images/images/.github/workflows/digestabot.yaml@refs/heads/main 13 | - key: 14 | # allow commits signed by GitHub, e.g. the UI 15 | kms: https://github.com/web-flow.gpg 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | generated.tf linguist-generated=true 2 | **/generated.tf linguist-generated=true 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/external-bug-or-feedback.yml: -------------------------------------------------------------------------------- 1 | name: External Bug/Feedback report 2 | description: Use this form to file an issue or feature request for one of our Chainguard Images 3 | title: "Describe the issue/request" 4 | labels: ["needs-triage"] 5 | body: 6 | - type: textarea 7 | id: affected-image 8 | attributes: 9 | label: "Which image/versions are related to this issue/feature request?" 10 | - type: textarea 11 | id: issue-details 12 | attributes: 13 | label: "Issue/Feature description" 14 | description: "Tell us about the issue you are having or the feature you'd like." 15 | placeholder: "For issues please include information such as environment (OS, version, shell), any commands used, logs output." 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new-image-request.yml: -------------------------------------------------------------------------------- 1 | name: New Chainguard Images Request 2 | description: Use this form to request a new kind of [Chainguard Image](github.com/chainguard-images/) 3 | title: "[Image Request]: $IMAGE_NAME" 4 | labels: [ "image-request", "needs-triage" ] 5 | assignees: 6 | - amdawson 7 | body: 8 | - type: textarea 9 | id: image-description 10 | attributes: 11 | label: "What software would you like us to add to our image catalog? (one per issue please)" 12 | validations: 13 | required: true 14 | - type: input 15 | id: image-versions 16 | attributes: 17 | label: "which versions of the containerized software do you need?" 18 | - type: textarea 19 | id: image-justification 20 | attributes: 21 | label: "Add some justification for why this specific image and versions are important." 22 | -------------------------------------------------------------------------------- /.github/chainguard/digestabot.sts.yaml: -------------------------------------------------------------------------------- 1 | issuer: https://token.actions.githubusercontent.com 2 | subject: repo:chainguard-images/images:ref:refs/heads/main 3 | claim_pattern: 4 | job_workflow_ref: chainguard-images/images/.github/workflows/digestabot.yaml@refs/heads/main 5 | 6 | permissions: 7 | contents: write 8 | pull_requests: write 9 | workflows: write 10 | -------------------------------------------------------------------------------- /.github/chainguard/public-copy.sts.yaml: -------------------------------------------------------------------------------- 1 | issuer: https://token.actions.githubusercontent.com 2 | subject: repo:chainguard-images/images-private:ref:refs/heads/main 3 | claim_pattern: 4 | job_workflow_ref: chainguard-images/images-private/.github/workflows/public-copy.yaml@refs/heads/main 5 | 6 | permissions: 7 | contents: write 8 | pull_requests: write 9 | workflows: write 10 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | open-pull-requests-limit: 10 8 | groups: 9 | actions: 10 | update-types: 11 | - "minor" 12 | - "patch" 13 | -------------------------------------------------------------------------------- /.github/workflows/presubmit-readme.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | 4 | permissions: {} 5 | 6 | jobs: 7 | presubmit-readme: 8 | runs-on: ubuntu-latest 9 | 10 | permissions: 11 | contents: read 12 | 13 | steps: 14 | - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 15 | with: 16 | egress-policy: audit 17 | 18 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 19 | 20 | - id: changed 21 | uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 # v45.0.1 22 | with: 23 | files_yaml: | 24 | automated: 25 | - ./images/** 26 | - ./tflib/** 27 | - ./.terraform.lock.hcl 28 | - ./Makefile 29 | - ./main.tf 30 | - ./generated.tf 31 | - ./go.mod 32 | - ./go.sum 33 | - ./withdrawn-images.txt 34 | - ./withdrawn-repos.txt 35 | - ./reinstated-images.txt 36 | 37 | - if: ${{ steps.changed.outputs.automated == 'true' }} 38 | run: | 39 | echo "You have made changes to files that are managed by automation." 40 | exit 1 41 | -------------------------------------------------------------------------------- /.github/workflows/withdraw-repos.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | inputs: 4 | dry_run: 5 | type: boolean 6 | default: true 7 | description: If true, just log 8 | 9 | permissions: {} 10 | 11 | jobs: 12 | withdraw: 13 | runs-on: ubuntu-latest 14 | 15 | permissions: 16 | id-token: write 17 | contents: read 18 | 19 | steps: 20 | - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 21 | with: 22 | egress-policy: audit 23 | 24 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 25 | with: 26 | persist-credentials: false 27 | 28 | - uses: chainguard-dev/setup-chainctl@272698817627c158bbd813cb783b62a4b9bbbc67 # v0.3.1 29 | with: 30 | identity: 720909c9f5279097d847ad02a2f24ba8f59de36a/b6461e99e132298f 31 | - run: | 32 | for repo in $(grep -v '\#' withdrawn-repos.txt); do 33 | if [[ "${{ github.event.inputs.dry_run }}" == "false" ]]; then 34 | chainctl image repo rm $repo || true 35 | else 36 | echo "DRY RUN: chainctl image repo rm $repo || true" 37 | fi 38 | done 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | monopod/monopod 2 | generated/ 3 | .idea 4 | 5 | # Ignore generated credentials from google-github-actions/auth 6 | gha-creds-*.json 7 | 8 | .terraform* 9 | !.terraform.lock.hcl 10 | terraform.tfstate* 11 | plan.out* 12 | main_override.tf 13 | 14 | # Files added by running `apko build` directly 15 | sbom-*.json 16 | sbom-*.cdx 17 | *.tar 18 | 19 | # macOS 20 | .DS_Store 21 | 22 | imagetest-logs/ 23 | -------------------------------------------------------------------------------- /.yam.yaml: -------------------------------------------------------------------------------- 1 | gap: 2 | - '.' 3 | 4 | sort: 5 | - ".contents.packages" 6 | 7 | indent: 2 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chainguard Images 2 | 3 | ### Learn more about Chainguard Images 4 | 5 | https://edu.chainguard.dev/chainguard/chainguard-images/ 6 | 7 | ### See available images 8 | 9 | https://images.chainguard.dev 10 | 11 | ### Log in to view the full catalog 12 | 13 | https://console.chainguard.dev 14 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | To report a security issue, please email 6 | [security@chainguard.dev](mailto:security@chainguard.dev) 7 | with a description of the issue, the steps you took to create the issue, 8 | affected versions, and, if known, mitigations for the issue. 9 | 10 | All support will be made on the best effort base, so please indicate the "urgency level" of the vulnerability as Critical, High, Medium or Low. 11 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/chainguard-images/images 2 | 3 | go 1.22.1 4 | toolchain go1.22.5 5 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chainguard-images/images/f6d25c31463ea902cc57522b553fba13dd15aa24/go.sum -------------------------------------------------------------------------------- /images/TEMPLATE/README.md: -------------------------------------------------------------------------------- 1 | # Chainguard Images Template 2 | 3 | This is a template README.md for new images. 4 | 5 | 1. Include a brief description of the image here, and instructions about how to use it. 6 | 1. Run `monopod readme`, which will update the top section of this file and the root README.md file. 7 | 1. Run `make tfgen`, which will update the generated root module config. 8 | 1. Update your new `config/template.apko.yaml` file to specify packages you want the image to include, and any other necessary image config. 9 | 10 | If you need to support version streams, you can leave `packages` empty in `latest.apko.yaml`, and instead add packages to the images using the `extra_packages` TF variable in `config/main.tf`. 11 | -------------------------------------------------------------------------------- /images/TEMPLATE/config/main.tf.tpl: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "The additional packages to install" 3 | type = list(string) 4 | default = [] 5 | } 6 | 7 | module "accts" { 8 | source = "../../../tflib/accts" 9 | uid = {{ .UserUid }} 10 | gid = {{ .GroupGid }} 11 | run-as = {{ .RunAs }} 12 | } 13 | 14 | output "config" { 15 | value = jsonencode({ 16 | contents = { 17 | packages = concat([ 18 | // TODO: Add any other packages here that are *always* needed. 19 | ], var.extra_packages) 20 | } 21 | // 22 | accounts = module.accts.block 23 | entrypoint = { 24 | command = "{{ .Entrypoint }}" 25 | } 26 | // TODO: Add paths, envs, etc., where necessary. 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /images/TEMPLATE/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | -------------------------------------------------------------------------------- /images/TEMPLATE/main.tf.tpl: -------------------------------------------------------------------------------- 1 | variable "target_repository" { 2 | description = "The docker repo into which the image and attestations should be published." 3 | } 4 | 5 | module "versions" { 6 | package = "{{ .ModuleName }}" 7 | source = "../../tflib/versions" 8 | } 9 | 10 | module "config" { 11 | for_each = module.versions.versions 12 | source = "./config" 13 | extra_packages = [each.key] 14 | } 15 | 16 | module "versioned" { 17 | for_each = module.versions.versions 18 | source = "../../tflib/publisher" 19 | name = basename(path.module) 20 | target_repository = var.target_repository 21 | config = module.config[each.key].config 22 | build-dev = {{ .DevVariant }} 23 | main_package = each.value.main 24 | update-repo = each.value.is_latest 25 | } 26 | 27 | module "test-versioned" { 28 | for_each = module.versions.versions 29 | source = "./tests" 30 | digest = module.versioned[each.key].image_ref 31 | } 32 | 33 | module "tagger" { 34 | source = "../../tflib/tagger" 35 | depends_on = [module.test-versioned] 36 | tags = merge([for v in module.versioned : v.latest_tag_map]...) 37 | } 38 | -------------------------------------------------------------------------------- /images/TEMPLATE/metadata.yaml.tpl: -------------------------------------------------------------------------------- 1 | name: {{ .ModuleName }} 2 | image: cgr.dev/chainguard/{{ .ModuleName }} 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: TODO 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/wolfi-dev/os 9 | keywords: [] 10 | -------------------------------------------------------------------------------- /images/apko/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "Additional packages to install." 3 | type = list(string) 4 | default = ["apko"] 5 | } 6 | 7 | output "config" { 8 | value = jsonencode({ 9 | contents = { 10 | packages = concat(var.extra_packages, [ 11 | "alpine-keys", 12 | "wolfi-keys", 13 | ]) 14 | } 15 | // TODO: Does this need accounts? 16 | paths = [{ 17 | path : "/work", 18 | type : "directory", 19 | permissions = 511 // 0o777 (HCL explicitly does not support octal literals) 20 | }] 21 | entrypoint = { 22 | command = "/usr/bin/apko" 23 | } 24 | work-dir = "/work" 25 | cmd = "--help" 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /images/apko/examples/wolfi-base.yaml: -------------------------------------------------------------------------------- 1 | contents: 2 | packages: 3 | - wolfi-base 4 | 5 | cmd: /bin/sh -l 6 | 7 | # optional environment configuration 8 | environment: 9 | PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 10 | -------------------------------------------------------------------------------- /images/apko/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/apko/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.config.config 18 | main_package = "apko" 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | resource "oci_tag" "latest" { 27 | depends_on = [module.test-latest] 28 | digest_ref = module.latest.image_ref 29 | tag = "latest" 30 | } 31 | -------------------------------------------------------------------------------- /images/apko/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: apko 2 | image: cgr.dev/chainguard/apko 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Container image for running [apko](https://github.com/chainguard-dev/apko) container builds. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/chainguard-dev/apko 9 | keywords: 10 | - application 11 | -------------------------------------------------------------------------------- /images/apko/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | imagetest = { source = "chainguard-dev/imagetest" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "imagetest_inventory" "inventory" {} 12 | 13 | resource "imagetest_harness_docker" "docker" { 14 | name = "docker" 15 | inventory = data.imagetest_inventory.inventory 16 | 17 | envs = { 18 | IMAGE_NAME : var.digest 19 | } 20 | } 21 | 22 | resource "imagetest_feature" "test" { 23 | name = "test" 24 | harness = imagetest_harness_docker.docker 25 | 26 | steps = [{ 27 | name = "basic test" 28 | cmd = "docker run --rm $IMAGE_NAME version" 29 | }] 30 | } 31 | -------------------------------------------------------------------------------- /images/aspnet-runtime/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/aspnet-runtime/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | 16 | name = basename(path.module) 17 | 18 | target_repository = var.target_repository 19 | config = module.config.config 20 | build-dev = true 21 | } 22 | 23 | module "test-latest" { 24 | source = "./tests" 25 | digest = module.latest.image_ref 26 | } 27 | 28 | resource "oci_tag" "latest" { 29 | depends_on = [module.test-latest] 30 | digest_ref = module.latest.image_ref 31 | tag = "latest" 32 | } 33 | 34 | resource "oci_tag" "latest-dev" { 35 | depends_on = [module.test-latest] 36 | digest_ref = module.latest.dev_ref 37 | tag = "latest-dev" 38 | } 39 | -------------------------------------------------------------------------------- /images/aspnet-runtime/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: aspnet-runtime 2 | image: cgr.dev/chainguard/aspnet-runtime 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Container image with the latest ASP.NET runtime. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/dotnet/core 9 | keywords: 10 | - base 11 | - featured 12 | -------------------------------------------------------------------------------- /images/aspnet-runtime/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | imagetest = { source = "chainguard-dev/imagetest" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "imagetest_inventory" "inventory" {} 12 | 13 | resource "imagetest_harness_docker" "docker" { 14 | name = "docker" 15 | inventory = data.imagetest_inventory.inventory 16 | 17 | envs = { 18 | IMAGE_NAME : var.digest 19 | } 20 | } 21 | 22 | resource "imagetest_feature" "test" { 23 | name = "docker-test" 24 | harness = imagetest_harness_docker.docker 25 | 26 | steps = [ 27 | { 28 | name = "basic test" 29 | cmd = "docker run --rm $IMAGE_NAME --info" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /images/bash/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "Additional packages to install." 3 | type = list(string) 4 | default = [] 5 | } 6 | 7 | module "accts" { 8 | source = "../../../tflib/accts" 9 | run-as = 0 10 | } 11 | 12 | output "config" { 13 | value = jsonencode({ 14 | contents = { 15 | packages = concat([ 16 | "bash", 17 | "busybox", 18 | "curl", 19 | ], var.extra_packages) 20 | } 21 | accounts = module.accts.block 22 | entrypoint = { 23 | command = "/bin/bash -c" 24 | } 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /images/bash/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/bash/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | 16 | name = basename(path.module) 17 | 18 | target_repository = var.target_repository 19 | config = module.config.config 20 | } 21 | 22 | module "test-latest" { 23 | source = "./tests" 24 | digest = module.latest.image_ref 25 | } 26 | 27 | resource "oci_tag" "latest" { 28 | depends_on = [module.test-latest] 29 | digest_ref = module.latest.image_ref 30 | tag = "latest" 31 | } 32 | -------------------------------------------------------------------------------- /images/bash/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: bash 2 | image: cgr.dev/chainguard/bash 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Container image with only Bash and libc. Suitable for running any small scripts or binaries that need Bash instead of the BusyBox shell. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.gnu.org/software/bash/ 9 | keywords: 10 | - application 11 | aliases: 12 | - bash:latest 13 | -------------------------------------------------------------------------------- /images/bash/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | imagetest = { source = "chainguard-dev/imagetest" } 5 | } 6 | } 7 | 8 | variable "digest" { 9 | description = "The image digest to run tests over." 10 | } 11 | 12 | data "imagetest_inventory" "this" {} 13 | 14 | resource "imagetest_harness_docker" "this" { 15 | name = "bash" 16 | inventory = data.imagetest_inventory.this 17 | 18 | envs = { 19 | "IMAGE_NAME" : var.digest 20 | } 21 | } 22 | 23 | resource "imagetest_feature" "docker" { 24 | name = "Test bash" 25 | harness = imagetest_harness_docker.this 26 | 27 | steps = [ 28 | { 29 | name = "run a bash function" 30 | cmd = </dev/null 8 | 9 | # The image runs as nonroot by default. 10 | docker run --rm --entrypoint '' "$image" whoami | grep "^nonroot$" 11 | 12 | # The image contains many common utilities (some in /usr/bin and some in /bin) 13 | for cmd in awk basename cat chmod chown cp cut date dirname du echo egrep expr find grep head id ln ls mkdir mktemp mv printf pwd rm rmdir sed sh sort tail tar tee test touch tr uname uniq wc xargs; do 14 | docker run --rm "$image" which "$cmd" || { echo "$cmd not in PATH"; exit 1; } 15 | done 16 | 17 | # The image can be used as a base image. 18 | cat </dev/null 9 | 10 | # Test dive analysis on a static image 11 | docker pull cgr.dev/chainguard/static 12 | docker save cgr.dev/chainguard/static >static.tar 13 | 14 | docker run --rm -u 0:0 -v "$PWD":/work --workdir=/work "$image" --source docker-archive static.tar -j out.json 15 | cat out.json | grep "efficiencyScore" 16 | 17 | -------------------------------------------------------------------------------- /images/docker-dind/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/docker-dind/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: docker-dind 2 | image: cgr.dev/chainguard/docker-dind 3 | endoflife: "A secure and lightweight Docker-in-Docker (dind) image for containerized development and CI/CD." 4 | console_summary: "Run Docker within containers efficiently with this secure and optimized dind image." 5 | short_description: "Chainguard image for Docker in Docker (DinD), allowing you to run Docker within a container." 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/docker-library/docker 9 | keywords: 10 | - application 11 | aliases: 12 | - library/docker:latest 13 | tier: APPLICATION 14 | public: true 15 | -------------------------------------------------------------------------------- /images/dotnet/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/dotnet/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "test-latest" { 12 | source = "./tests" 13 | test_repository = var.test_repository 14 | 15 | digests = { 16 | sdk = module.sdk.image_ref 17 | runtime = module.runtime.image_ref 18 | } 19 | } 20 | 21 | resource "oci_tag" "latest" { 22 | depends_on = [module.test-latest] 23 | for_each = { 24 | "runtime" : module.runtime.image_ref, 25 | "sdk" : module.sdk.image_ref, 26 | } 27 | digest_ref = each.value 28 | tag = "latest" 29 | } 30 | 31 | resource "oci_tag" "latest-dev" { 32 | depends_on = [module.test-latest] 33 | for_each = { 34 | "runtime" : module.runtime.dev_ref, 35 | "sdk" : module.sdk.dev_ref, 36 | } 37 | digest_ref = each.value 38 | tag = "latest-dev" 39 | } 40 | -------------------------------------------------------------------------------- /images/dotnet/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: dotnet 2 | image: cgr.dev/chainguard/dotnet 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal container image for .NET and the .NET Tools. 6 | compatibility_notes: 7 | readme_file: README.md 8 | upstream_url: https://dot.net/core 9 | keywords: 10 | - base 11 | aliases: 12 | - mcr.microsoft.com/dotnet/runtime:latest 13 | - mcr.microsoft.com/dotnet/sdk:latest 14 | - mcr.microsoft.com/dotnet/runtime:8.0 15 | - mcr.microsoft.com/dotnet/sdk:8.0 16 | - mcr.microsoft.com/dotnet/runtime:9.0 17 | - mcr.microsoft.com/dotnet/sdk:9.0 18 | tier: BASE 19 | -------------------------------------------------------------------------------- /images/dotnet/runtime.tf: -------------------------------------------------------------------------------- 1 | module "runtime-config" { source = "./configs/runtime" } 2 | 3 | module "runtime" { 4 | source = "../../tflib/publisher" 5 | name = basename(path.module) 6 | target_repository = "${var.target_repository}-runtime" 7 | config = module.runtime-config.config 8 | build-dev = true 9 | } 10 | -------------------------------------------------------------------------------- /images/dotnet/sdk.tf: -------------------------------------------------------------------------------- 1 | module "sdk-config" { source = "./configs/sdk" } 2 | 3 | module "sdk" { 4 | source = "../../tflib/publisher" 5 | name = basename(path.module) 6 | target_repository = "${var.target_repository}-sdk" 7 | config = module.sdk-config.config 8 | build-dev = true 9 | } 10 | -------------------------------------------------------------------------------- /images/dotnet/tests/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | chmod 777 -R /data 6 | cp -r /tests/* /data 7 | 8 | apk add icu tzdata openssl 9 | 10 | UNAME=$(uname -m) 11 | if [ "$UNAME" == "x86_64" ]; then 12 | UNAME="linux-x64" 13 | else 14 | UNAME="linux-arm64" 15 | fi 16 | 17 | # need this for dotnet 6 to figure out standalone release target 18 | printf "$UNAME" > /tmp/arch -------------------------------------------------------------------------------- /images/dotnet/tests/src/tzdata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | class Program 4 | { 5 | static void Main() 6 | { 7 | try 8 | { 9 | // Try to find the Eastern Standard Time time zone 10 | var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); 11 | Console.WriteLine($"Time Zone found: {timeZone.DisplayName}"); 12 | } 13 | catch (Exception ex) 14 | { 15 | Console.WriteLine("Timezone error: " + ex.Message); 16 | Environment.Exit(1); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /images/gcc-glibc/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "Additional packages to install." 3 | type = list(string) 4 | default = ["build-base"] 5 | } 6 | 7 | output "config" { 8 | value = jsonencode({ 9 | contents = { 10 | packages = concat(["busybox"], var.extra_packages) 11 | } 12 | paths = [{ 13 | path = "/work" 14 | type = "directory" 15 | permissions = 511 // 0o777 (HCL explicitly does not support octal literals) 16 | }] 17 | work-dir = "/work" 18 | entrypoint = { 19 | command = "/usr/bin/gcc" 20 | } 21 | cmd = "--help" 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /images/gcc-glibc/examples/hello/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("Hello World!\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /images/gcc-glibc/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/gcc-glibc/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | 16 | name = basename(path.module) 17 | 18 | target_repository = var.target_repository 19 | config = module.config.config 20 | build-dev = true 21 | } 22 | 23 | module "test-latest" { 24 | source = "./tests" 25 | digest = module.latest.image_ref 26 | } 27 | 28 | resource "oci_tag" "latest" { 29 | depends_on = [module.test-latest] 30 | digest_ref = module.latest.image_ref 31 | tag = "latest" 32 | } 33 | 34 | resource "oci_tag" "latest-dev" { 35 | depends_on = [module.test-latest] 36 | digest_ref = module.latest.dev_ref 37 | tag = "latest-dev" 38 | } 39 | -------------------------------------------------------------------------------- /images/gcc-glibc/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: gcc-glibc 2 | image: cgr.dev/chainguard/gcc-glibc 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal GCC (GNU Compiler Collection) image for building C applications compatible with glibc. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://wolfi.dev 9 | keywords: 10 | - application 11 | - base 12 | aliases: 13 | - gcc:latest 14 | -------------------------------------------------------------------------------- /images/gcc-glibc/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "oci_exec_test" "version" { 12 | digest = var.digest 13 | script = "docker run --rm $IMAGE_NAME --version" 14 | } 15 | -------------------------------------------------------------------------------- /images/git/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "Extra packages to install." 3 | type = list(string) 4 | default = [] 5 | } 6 | 7 | variable "extra_repositories" { 8 | description = "Extra repositories to add." 9 | type = list(string) 10 | default = [] 11 | } 12 | 13 | variable "root" { 14 | description = "Whether to run as root." 15 | type = bool 16 | default = false 17 | } 18 | 19 | module "accts" { 20 | source = "../../../tflib/accts" 21 | run-as = var.root ? 0 : 65532 22 | name = "git" 23 | } 24 | 25 | output "config" { 26 | value = jsonencode({ 27 | contents = { 28 | repositories = var.extra_repositories 29 | packages = concat([ 30 | "git", 31 | "git-lfs", 32 | "openssh-client", 33 | ], var.extra_packages) 34 | } 35 | accounts = module.accts.block 36 | entrypoint = { 37 | command = "/usr/bin/git" 38 | } 39 | work-dir = "/home/git" 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /images/git/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/git/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | apko = { 4 | source = "chainguard-dev/apko" 5 | } 6 | } 7 | } 8 | 9 | locals { 10 | accounts = toset(["nonroot", "root"]) 11 | } 12 | 13 | variable "target_repository" { 14 | description = "The docker repo into which the image and attestations should be published." 15 | } 16 | 17 | module "tagger" { 18 | source = "../../tflib/tagger" 19 | 20 | depends_on = [ 21 | module.test-latest-wolfi, 22 | module.test-latest-wolfi-dev, 23 | ] 24 | 25 | tags = merge( 26 | { "latest" = module.latest-wolfi["nonroot"].image_ref }, 27 | { "latest-dev" = module.latest-wolfi["nonroot"].dev_ref }, 28 | { "latest-root" = module.latest-wolfi["root"].image_ref }, 29 | { "latest-root-dev" = module.latest-wolfi["root"].dev_ref }, 30 | 31 | { "latest-glibc" = module.latest-wolfi["nonroot"].image_ref }, 32 | { "latest-glibc-dev" = module.latest-wolfi["nonroot"].dev_ref }, 33 | { "latest-glibc-root" = module.latest-wolfi["root"].image_ref }, 34 | { "latest-glibc-root-dev" = module.latest-wolfi["root"].dev_ref }, 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /images/git/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: git 2 | image: cgr.dev/chainguard/git 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: A minimal Git image. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://git-scm.com/ 9 | keywords: 10 | - application 11 | aliases: 12 | - bitnami/git:latest 13 | - alpine/git:latest 14 | -------------------------------------------------------------------------------- /images/git/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | imagetest = { source = "chainguard-dev/imagetest" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "target_repository" {} 12 | 13 | module "bash_sandbox" { 14 | source = "../../../tflib/imagetest/sandboxes/bash" 15 | target_repository = var.target_repository 16 | } 17 | 18 | module "dind_test" { 19 | source = "../../../tflib/imagetest/tests/docker-in-docker" 20 | 21 | images = { git = var.digest } 22 | 23 | tests = [ 24 | { 25 | name = "smoke" 26 | image = module.bash_sandbox.image_ref 27 | content = [{ source = path.module }] 28 | cmd = "./smoke.sh" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /images/git/tests/smoke.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | image=$(echo "$IMAGES" | jq -r '.git.ref') 6 | 7 | # Test git version 8 | docker run --rm "${image}" --version 9 | 10 | # Test git submodule help 11 | docker run --rm "${image}" submodule -h 12 | 13 | # Test repo cloning 14 | CLONE_URL="https://github.com/chainguard-images/.github.git" 15 | CLONEDIR="$(mktemp -d)" 16 | chmod go+wrx "${CLONEDIR}" 17 | 18 | # Clone and verify 19 | pushd "${CLONEDIR}" 20 | docker run --rm -v "${PWD}":/w -w /w "${image}" clone --depth 1 "${CLONE_URL}" . 21 | popd 22 | 23 | # Verify clone worked 24 | find "${CLONEDIR}/README.md" && echo "Clone test passed." 25 | 26 | # Cleanup 27 | rm -rf "${CLONEDIR}" -------------------------------------------------------------------------------- /images/git/wolfi.tf: -------------------------------------------------------------------------------- 1 | module "wolfi" { 2 | for_each = local.accounts 3 | source = "./config" 4 | root = each.key == "root" 5 | } 6 | 7 | module "latest-wolfi" { 8 | for_each = local.accounts 9 | source = "../../tflib/publisher" 10 | name = basename(path.module) 11 | target_repository = var.target_repository 12 | config = module.wolfi[each.key].config 13 | check-sbom = false # TODO: Not yet conformant: ncurses, libedit, openssh 14 | build-dev = true 15 | extra_packages = [ 16 | "dash-binsh", 17 | // Default git signing tools - See https://github.com/git/git/blob/6a64ac7b014fa2cfa7a69af3c253bcd53a94b428/gpg-interface.c#L93-L124 18 | "gpg", 19 | "gpgsm", 20 | "openssh-keygen", 21 | ] 22 | } 23 | 24 | module "test-latest-wolfi" { 25 | for_each = local.accounts 26 | source = "./tests" 27 | digest = module.latest-wolfi[each.key].image_ref 28 | target_repository = var.target_repository 29 | } 30 | 31 | module "test-latest-wolfi-dev" { 32 | for_each = local.accounts 33 | source = "./tests" 34 | digest = module.latest-wolfi[each.key].dev_ref 35 | target_repository = var.target_repository 36 | } 37 | -------------------------------------------------------------------------------- /images/glibc-dynamic/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "Additional packages to install." 3 | type = list(string) 4 | default = [] 5 | } 6 | 7 | variable "extra_repositories" { 8 | description = "Extra repositories to add." 9 | type = list(string) 10 | default = [] 11 | } 12 | 13 | module "accts" { source = "../../../tflib/accts" } 14 | 15 | output "config" { 16 | value = jsonencode({ 17 | contents = { 18 | repositories = var.extra_repositories 19 | packages = concat(["glibc", "libgcc", "libstdc++"], var.extra_packages) 20 | } 21 | accounts = module.accts.block 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /images/glibc-dynamic/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/glibc-dynamic/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | build-dev = true 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | resource "oci_tag" "latest" { 27 | depends_on = [module.test-latest] 28 | digest_ref = module.latest.image_ref 29 | tag = "latest" 30 | } 31 | 32 | resource "oci_tag" "latest-dev" { 33 | depends_on = [module.test-latest] 34 | digest_ref = module.latest.dev_ref 35 | tag = "latest-dev" 36 | } 37 | -------------------------------------------------------------------------------- /images/glibc-dynamic/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: glibc-dynamic 2 | image: cgr.dev/chainguard/glibc-dynamic 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Base image with just enough to run arbitrary glibc binaries. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://wolfi.dev 9 | keywords: 10 | - base 11 | -------------------------------------------------------------------------------- /images/glibc-dynamic/tests/01-runs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | docker run --rm "${IMAGE_NAME}" /sbin/ldconfig --help 6 | -------------------------------------------------------------------------------- /images/glibc-dynamic/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "oci_exec_test" "version" { 12 | digest = var.digest 13 | script = "${path.module}/01-runs.sh" 14 | } 15 | -------------------------------------------------------------------------------- /images/go/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/go/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: go 2 | image: cgr.dev/chainguard/go 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Container image for building Go applications. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://go.dev/ 9 | keywords: 10 | - base 11 | - featured 12 | public: true 13 | tier: BASE 14 | aliases: 15 | - golang:latest 16 | - golang:alpine 17 | -------------------------------------------------------------------------------- /images/go/tests/hello/.gitignore: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /images/go/tests/hello/go.mod: -------------------------------------------------------------------------------- 1 | module hello 2 | 3 | go 1.17 4 | 5 | require github.com/opencontainers/go-digest v1.0.0 6 | -------------------------------------------------------------------------------- /images/go/tests/hello/go.sum: -------------------------------------------------------------------------------- 1 | github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= 2 | github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 3 | -------------------------------------------------------------------------------- /images/go/tests/hello/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | // nolint: depguard 5 | _ "crypto/sha256" // Recommended by go-digest. 6 | "fmt" 7 | 8 | "github.com/opencontainers/go-digest" 9 | ) 10 | 11 | func main() { 12 | if err := digest.Canonical.Validate("36bc3535e93a712d148f2a2e3674236e1f8a5e3db935ed2e6d0320e369920c2c"); err != nil { 13 | panic(err) 14 | } 15 | fmt.Println("Hello World!") 16 | } 17 | -------------------------------------------------------------------------------- /images/go/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "target_repository" { 12 | } 13 | 14 | variable "image_version" { 15 | } 16 | 17 | module "bash_sandbox" { 18 | source = "../../../tflib/imagetest/sandboxes/bash" 19 | target_repository = var.target_repository 20 | } 21 | 22 | module "dind_test" { 23 | images = { go = var.digest } 24 | name = var.image_version 25 | source = "../../../tflib/imagetest/tests/docker-in-docker" 26 | tests = [ 27 | { 28 | name = "smoke" 29 | image = module.bash_sandbox.image_ref 30 | content = [{ source = path.module }] 31 | cmd = "./smoke.sh" 32 | } 33 | ] 34 | } 35 | 36 | -------------------------------------------------------------------------------- /images/gradle/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "The additional packages to install" 3 | type = list(string) 4 | default = [] 5 | } 6 | 7 | variable "extra_environment" { 8 | description = "Additional apko environment." 9 | type = map(string) 10 | default = {} 11 | } 12 | 13 | module "accts" { 14 | source = "../../../tflib/accts" 15 | uid = 65532 16 | gid = 65532 17 | run-as = 65532 18 | } 19 | 20 | output "config" { 21 | value = jsonencode({ 22 | contents = { 23 | packages = concat([ 24 | ], var.extra_packages) 25 | } 26 | accounts = module.accts.block 27 | entrypoint = { 28 | command = "/usr/bin/gradle" 29 | } 30 | work-dir = "/home/build" 31 | environment = merge({ 32 | JAVA_HOME = "/usr/lib/jvm/default-jvm" 33 | LANG = "en_US.UTF-8" 34 | }, var.extra_environment) 35 | paths = [ 36 | { 37 | path = "/home/build" 38 | type = "directory" 39 | uid = 65532 40 | gid = 65532 41 | permissions = 493 42 | } 43 | ] 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /images/gradle/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/gradle/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { 12 | source = "./config" 13 | extra_packages = [ 14 | "gradle", 15 | "openjdk-24-default-jdk", 16 | "busybox", 17 | "glibc-locale-en" 18 | ] 19 | } 20 | 21 | module "latest" { 22 | source = "../../tflib/publisher" 23 | 24 | name = basename(path.module) 25 | 26 | target_repository = var.target_repository 27 | config = module.config.config 28 | extra_dev_packages = ["binutils"] 29 | } 30 | 31 | module "test-latest" { 32 | source = "./tests" 33 | digest = module.latest.image_ref 34 | java-version = "24" 35 | target_repository = var.target_repository 36 | } 37 | 38 | resource "oci_tag" "latest" { 39 | depends_on = [module.test-latest] 40 | digest_ref = module.latest.image_ref 41 | tag = "latest" 42 | } 43 | -------------------------------------------------------------------------------- /images/gradle/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: gradle 2 | image: cgr.dev/chainguard/gradle 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Chainguard Image with [Gradle](https://gradle.org/), an open source build system for Java, Android, and Kotlin. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/gradle/gradle 9 | keywords: 10 | - application 11 | aliases: 12 | - gradle:latest 13 | -------------------------------------------------------------------------------- /images/gradle/tests/main.tf: -------------------------------------------------------------------------------- 1 | variable "digest" { 2 | description = "The image digest to run tests over." 3 | } 4 | 5 | variable "java-version" { 6 | description = "Java version" 7 | } 8 | 9 | variable "target_repository" {} 10 | 11 | module "bash_sandbox" { 12 | source = "../../../tflib/imagetest/sandboxes/bash" 13 | target_repository = var.target_repository 14 | } 15 | 16 | module "dind_test" { 17 | source = "../../../tflib/imagetest/tests/docker-in-docker" 18 | 19 | images = { gradle = var.digest } 20 | 21 | tests = [ 22 | { 23 | name = "smoke test" 24 | image = module.bash_sandbox.image_ref 25 | content = [{ source = path.module }] 26 | cmd = "./test.sh" 27 | envs = { 28 | JAVA_VERSION = var.java-version 29 | } 30 | } 31 | ] 32 | } 33 | 34 | -------------------------------------------------------------------------------- /images/gradle/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | image=$(echo "$IMAGES" | jq -r '.gradle.ref') 6 | 7 | docker run --rm --entrypoint "" "$image" sh -c "gradle init --type java-application --dsl kotlin --test-framework junit-jupiter --package my.project --project-name my-project --no-split-project --incubating --java-version ${JAVA_VERSION} && gradle build --stacktrace" 8 | -------------------------------------------------------------------------------- /images/grype/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "The additional packages to install (e.g. grype)." 3 | default = ["grype"] 4 | } 5 | 6 | module "accts" { source = "../../../tflib/accts" } 7 | 8 | output "config" { 9 | value = jsonencode({ 10 | contents = { 11 | # From the upstream .ko.yaml 12 | # We need a shell for a lot of redirection/piping to work 13 | packages = concat(["busybox"], var.extra_packages) 14 | } 15 | accounts = module.accts.block 16 | entrypoint = { 17 | command = "/usr/bin/grype" 18 | } 19 | cmd = "help" 20 | paths = [{ 21 | path = "/var/lib/grype" 22 | type = "directory" 23 | uid = module.accts.block.run-as 24 | gid = module.accts.block.run-as 25 | permissions = 511 // 0o777 (HCL explicitly does not support octal literals) 26 | }] 27 | }) 28 | } 29 | 30 | -------------------------------------------------------------------------------- /images/grype/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/grype/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | build-dev = true 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | target_repository = var.target_repository 25 | } 26 | 27 | resource "oci_tag" "latest" { 28 | depends_on = [module.test-latest] 29 | digest_ref = module.latest.image_ref 30 | tag = "latest" 31 | } 32 | 33 | resource "oci_tag" "latest-dev" { 34 | depends_on = [module.test-latest] 35 | digest_ref = module.latest.dev_ref 36 | tag = "latest-dev" 37 | } 38 | 39 | -------------------------------------------------------------------------------- /images/grype/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: grype 2 | image: cgr.dev/chainguard/grype 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: A vulnerability scanner for container images and filesystems 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/anchore/grype 9 | keywords: 10 | - application 11 | aliases: 12 | - anchore/grype:latest 13 | -------------------------------------------------------------------------------- /images/grype/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "target_repository" {} 12 | 13 | module "bash_sandbox" { 14 | source = "../../../tflib/imagetest/sandboxes/bash" 15 | target_repository = var.target_repository 16 | } 17 | 18 | module "dind_test" { 19 | source = "../../../tflib/imagetest/tests/docker-in-docker" 20 | 21 | images = { grype = var.digest } 22 | 23 | tests = [ 24 | { 25 | name = "smoke" 26 | image = module.bash_sandbox.image_ref 27 | content = [{ source = path.module }] 28 | cmd = "./smoke.sh" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /images/haproxy/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/haproxy/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { 12 | source = "./config" 13 | extra_packages = ["haproxy", "haproxy-oci-entrypoint", "dataplaneapi"] 14 | } 15 | 16 | module "latest" { 17 | source = "../../tflib/publisher" 18 | 19 | name = basename(path.module) 20 | 21 | target_repository = var.target_repository 22 | config = module.config.config 23 | 24 | } 25 | 26 | module "test-latest" { 27 | source = "./tests" 28 | digest = module.latest.image_ref 29 | target_repository = var.target_repository 30 | } 31 | 32 | resource "oci_tag" "latest" { 33 | depends_on = [module.test-latest] 34 | digest_ref = module.latest.image_ref 35 | tag = "latest" 36 | } 37 | -------------------------------------------------------------------------------- /images/haproxy/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: haproxy 2 | image: cgr.dev/chainguard/haproxy 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: A minimal [haproxy](https://www.haproxy.org/) base image rebuilt every night from source. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.haproxy.org/ 9 | keywords: 10 | - application 11 | aliases: 12 | - bitnami/haproxy:latest 13 | - haproxy:alpine 14 | - haproxy:latest 15 | -------------------------------------------------------------------------------- /images/haproxy/tests/slim/haproxy.cfg: -------------------------------------------------------------------------------- 1 | global 2 | maxconn 256 3 | 4 | defaults 5 | mode http 6 | timeout connect 5s 7 | timeout client 50s 8 | timeout server 50s 9 | 10 | frontend http_front 11 | bind *:8080 12 | default_backend http_back 13 | 14 | backend http_back 15 | server nginx nginx:8080 check 16 | -------------------------------------------------------------------------------- /images/haproxy/tests/slim/haproxy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: haproxy 5 | labels: 6 | app: haproxy 7 | spec: 8 | containers: 9 | - name: haproxy 10 | image: haproxy:latest 11 | volumeMounts: 12 | - name: haproxy-config-volume 13 | mountPath: /etc/haproxy/haproxy.cfg 14 | subPath: haproxy.cfg 15 | volumes: 16 | - name: haproxy-config-volume 17 | configMap: 18 | name: haproxy-config -------------------------------------------------------------------------------- /images/helm/config/main.tf: -------------------------------------------------------------------------------- 1 | module "accts" { 2 | source = "../../../tflib/accts" 3 | } 4 | 5 | terraform { 6 | required_providers { 7 | apko = { source = "chainguard-dev/apko" } 8 | } 9 | } 10 | 11 | variable "extra_packages" { 12 | default = ["helm", "kubectl-latest"] 13 | description = "The additional packages to install (e.g. helm)." 14 | } 15 | 16 | output "config" { 17 | value = jsonencode({ 18 | "contents" : { 19 | "packages" : var.extra_packages 20 | }, 21 | "entrypoint" : { 22 | "command" : "/usr/bin/helm" 23 | }, 24 | "cmd" : "help", 25 | "accounts" : module.accts.block 26 | }) 27 | } 28 | 29 | -------------------------------------------------------------------------------- /images/helm/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/helm/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | build-dev = true 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | target_repository = var.target_repository 25 | } 26 | 27 | resource "oci_tag" "latest" { 28 | depends_on = [module.test-latest] 29 | digest_ref = module.latest.image_ref 30 | tag = "latest" 31 | } 32 | 33 | resource "oci_tag" "latest-dev" { 34 | depends_on = [module.test-latest] 35 | digest_ref = module.latest.dev_ref 36 | tag = "latest-dev" 37 | } 38 | -------------------------------------------------------------------------------- /images/helm/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: helm 2 | image: cgr.dev/chainguard/helm 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal image with [helm](https://helm.sh) binary. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/helm/helm 9 | keywords: 10 | - application 11 | tier: APPLICATION 12 | aliases: 13 | - alpine/helm:latest 14 | - quay.io/coreos/helm:latest 15 | -------------------------------------------------------------------------------- /images/helm/tests/main.tf: -------------------------------------------------------------------------------- 1 | variable "digest" { 2 | description = "The image digest to run tests over." 3 | } 4 | 5 | variable "target_repository" { 6 | description = "The repository to push transient test images to." 7 | } 8 | 9 | module "bash_sandbox" { 10 | source = "../../../tflib/imagetest/sandboxes/bash" 11 | target_repository = var.target_repository 12 | } 13 | 14 | module "test" { 15 | source = "../../../tflib/imagetest/tests/docker-in-docker" 16 | 17 | images = { helm = var.digest } 18 | 19 | tests = [ 20 | { 21 | name = "helm help test" 22 | image = module.bash_sandbox.image_ref 23 | content = [{ source = path.module }] 24 | cmd = "./test.sh" 25 | } 26 | ] 27 | } 28 | 29 | -------------------------------------------------------------------------------- /images/helm/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o errexit -o nounset -o errtrace -o pipefail -x 3 | 4 | image=$(echo "$IMAGES" | jq -r '.helm.ref') 5 | 6 | docker run --rm "$image" help 7 | -------------------------------------------------------------------------------- /images/hugo/config/main.tf: -------------------------------------------------------------------------------- 1 | module "accts" { 2 | source = "../../../tflib/accts" 3 | } 4 | 5 | terraform { 6 | required_providers { 7 | apko = { source = "chainguard-dev/apko" } 8 | } 9 | } 10 | 11 | variable "extra_packages" { 12 | default = ["hugo"] 13 | description = "The additional packages to install (e.g. hugo)." 14 | } 15 | 16 | output "config" { 17 | value = jsonencode({ 18 | "contents" : { 19 | // TODO: remove the need for using hardcoded local.baseline_packages by plumbing 20 | // these packages through var.extra_packages in all callers of this config module 21 | "packages" : var.extra_packages, 22 | }, 23 | "entrypoint" : { 24 | "command" : "/usr/bin/hugo" 25 | }, 26 | "work-dir" : "/hugo", 27 | "accounts" : module.accts.block, 28 | "paths" : [ 29 | { 30 | "path" : "/hugo", 31 | "type" : "directory", 32 | "uid" : 65532, 33 | "gid" : 65532, 34 | "permissions" : 509 35 | } 36 | ] 37 | }) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /images/hugo/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/hugo/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | build-dev = true 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | resource "oci_tag" "latest" { 27 | depends_on = [module.test-latest] 28 | digest_ref = module.latest.image_ref 29 | tag = "latest" 30 | } 31 | 32 | resource "oci_tag" "latest-dev" { 33 | depends_on = [module.test-latest] 34 | digest_ref = module.latest.dev_ref 35 | tag = "latest-dev" 36 | } 37 | -------------------------------------------------------------------------------- /images/hugo/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: hugo 2 | image: cgr.dev/chainguard/hugo 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: This is a minimal [Hugo](https://gohugo.io/) image. 6 | compatibility_notes: This image only contains `hugo` and supporting libraries. The Hugo process starts in `/hugo` by default so this directory may be initialized with the Hugo site to serve. 7 | readme_file: README.md 8 | upstream_url: https://github.com/gohugoio/hugo/ 9 | keywords: 10 | - base 11 | tier: BASE 12 | aliases: 13 | - klakegg/hugo:latest 14 | -------------------------------------------------------------------------------- /images/jdk/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "run-as" { 2 | description = "The UID used to run the container." 3 | default = 65532 4 | } 5 | 6 | variable "extra_packages" { 7 | description = "The additional packages to install (e.g. openjdk-17)." 8 | default = ["default-jdk"] 9 | } 10 | 11 | variable "environment" { 12 | default = {} 13 | } 14 | 15 | module "accts" { 16 | source = "../../../tflib/accts" 17 | run-as = var.run-as 18 | name = "java" 19 | } 20 | 21 | output "config" { 22 | value = jsonencode({ 23 | contents = { 24 | packages = concat([ 25 | "glibc-locale-en", 26 | "busybox", 27 | "libstdc++", 28 | ], var.extra_packages) 29 | } 30 | accounts = module.accts.block 31 | work-dir = "/home/build" 32 | environment = merge({ 33 | "LANG" : "en_US.UTF-8", 34 | "JAVA_HOME" : "/usr/lib/jvm/default-jvm" 35 | }, var.environment) 36 | paths = [{ 37 | path = "/home/build" 38 | type = "directory" 39 | uid = module.accts.block.run-as 40 | gid = module.accts.block.run-as 41 | permissions = 493 // 0o755 (HCL explicitly does not support octal literals) 42 | }] 43 | }) 44 | } 45 | -------------------------------------------------------------------------------- /images/jdk/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/jdk/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | build-dev = true 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | resource "oci_tag" "latest" { 27 | depends_on = [module.test-latest] 28 | digest_ref = module.latest.image_ref 29 | tag = "latest" 30 | } 31 | 32 | resource "oci_tag" "latest-dev" { 33 | depends_on = [module.test-latest] 34 | digest_ref = module.latest.dev_ref 35 | tag = "latest-dev" 36 | } 37 | -------------------------------------------------------------------------------- /images/jdk/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: jdk 2 | image: cgr.dev/chainguard/jdk 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal Wolfi-based Java JDK image using [OpenJDK](https://openjdk.org/projects/jdk/). Used for compiling Java applications. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/openjdk/jdk 9 | keywords: 10 | - base 11 | - featured 12 | aliases: 13 | - openjdk:latest 14 | -------------------------------------------------------------------------------- /images/jdk/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "java-source-version" { 12 | type = number 13 | description = "The Java source version to use for compilation in this test." 14 | default = 8 15 | } 16 | 17 | variable "java-target-version" { 18 | type = number 19 | description = "The Java target version to use for compilation in this test." 20 | default = 8 21 | } 22 | 23 | data "oci_exec_test" "version" { 24 | digest = var.digest 25 | script = "docker run --entrypoint javac --rm $IMAGE_NAME -version" 26 | } 27 | 28 | module "jre-test" { 29 | source = "../../jre/tests" 30 | digest = var.digest 31 | sdk-image = var.digest 32 | java-source-version = var.java-source-version 33 | java-target-version = var.java-target-version 34 | } 35 | -------------------------------------------------------------------------------- /images/jre/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "run-as" { 2 | description = "The UID used to run the container." 3 | default = 65532 4 | } 5 | 6 | variable "extra_packages" { 7 | description = "The additional packages to install (e.g. openjdk-17-default-jvm)." 8 | default = ["default-jvm"] 9 | } 10 | 11 | variable "environment" { 12 | default = {} 13 | } 14 | 15 | variable "entrypoint-command" { 16 | default = "/usr/bin/java" 17 | } 18 | 19 | module "accts" { 20 | source = "../../../tflib/accts" 21 | run-as = var.run-as 22 | name = "java" 23 | } 24 | 25 | output "config" { 26 | value = jsonencode({ 27 | contents = { 28 | packages = concat([ 29 | "glibc-locale-en", 30 | "libstdc++", 31 | ], var.extra_packages) 32 | } 33 | accounts = module.accts.block 34 | work-dir = "/app" 35 | environment = merge({ 36 | "LANG" : "en_US.UTF-8", 37 | "JAVA_HOME" : "/usr/lib/jvm/default-jvm" 38 | }, var.environment) 39 | entrypoint = { 40 | command = var.entrypoint-command 41 | } 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /images/jre/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/jre/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | build-dev = true 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | resource "oci_tag" "latest" { 27 | depends_on = [module.test-latest] 28 | digest_ref = module.latest.image_ref 29 | tag = "latest" 30 | } 31 | 32 | resource "oci_tag" "latest-dev" { 33 | depends_on = [module.test-latest] 34 | digest_ref = module.latest.dev_ref 35 | tag = "latest-dev" 36 | } 37 | -------------------------------------------------------------------------------- /images/jre/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: jre 2 | image: cgr.dev/chainguard/jre 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimalist Wolfi-based Java JRE image using [OpenJDK](https://openjdk.org/projects/jdk/). Used for running Java applications. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/openjdk/jdk 9 | keywords: 10 | - base 11 | - featured 12 | -------------------------------------------------------------------------------- /images/jre/tests/HelloWorld.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main(String[] args) { 3 | System.out.println("Hello, World!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /images/k3s/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags, module.tagger-static.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/k3s/k3s.tf: -------------------------------------------------------------------------------- 1 | module "config" { 2 | extra_packages = ["k3s", "containerd-shim-runc-v2~1"] 3 | source = "./config" 4 | } 5 | 6 | module "latest" { 7 | build-dev = true 8 | config = module.config.config 9 | extra_dev_packages = ["bash-completion"] 10 | main_package = "k3s" 11 | name = basename(path.module) 12 | source = "../../tflib/publisher" 13 | target_repository = var.target_repository 14 | } 15 | 16 | module "test-latest" { 17 | digest = module.latest.image_ref 18 | source = "./tests" 19 | } 20 | 21 | module "tagger" { 22 | depends_on = [module.test-latest] 23 | source = "../../tflib/tagger" 24 | tags = module.latest.latest_tag_map 25 | } 26 | 27 | -------------------------------------------------------------------------------- /images/k3s/main.tf: -------------------------------------------------------------------------------- 1 | variable "target_repository" { 2 | description = "The docker repo into which the image and attestations should be published." 3 | } 4 | 5 | -------------------------------------------------------------------------------- /images/k3s/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: k3s 2 | image: cgr.dev/chainguard/k3s 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal image of [K3s](https://k3s.io/), a lightweight Kubernetes distribution 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/k3s-io/k3s 9 | keywords: 10 | - application 11 | tier: APPLICATION 12 | aliases: 13 | - rancher/k3s:latest 14 | public: true 15 | -------------------------------------------------------------------------------- /images/k3s/static.tf: -------------------------------------------------------------------------------- 1 | module "config-static" { 2 | extra_packages = ["k3s-static"] 3 | source = "./config" 4 | } 5 | 6 | module "latest-static" { 7 | build-dev = true 8 | config = module.config-static.config 9 | extra_dev_packages = ["bash-completion"] 10 | main_package = "k3s-static" 11 | name = basename(path.module) 12 | source = "../../tflib/publisher" 13 | target_repository = "${var.target_repository}-static" 14 | } 15 | 16 | module "test-latest-static" { 17 | digest = module.latest-static.image_ref 18 | source = "./tests" 19 | } 20 | 21 | module "tagger-static" { 22 | depends_on = [module.test-latest-static] 23 | source = "../../tflib/tagger" 24 | tags = module.latest-static.latest_tag_map 25 | } 26 | 27 | -------------------------------------------------------------------------------- /images/k3s/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "oci_exec_test" "test" { 12 | digest = var.digest 13 | script = "${path.module}/smoke.sh" 14 | } 15 | 16 | -------------------------------------------------------------------------------- /images/k3s/tests/smoke.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | uid="k3s-$FREE_PORT" 6 | TMPDIR=$uid 7 | mkdir -p $TMPDIR 8 | 9 | docker run --name "$uid" -d --rm -it --privileged \ 10 | -p $FREE_PORT:$FREE_PORT \ 11 | -v $(pwd)/$TMPDIR:/etc/rancher/k3s/ \ 12 | $IMAGE_NAME server --https-listen-port $FREE_PORT --write-kubeconfig-mode 0644 13 | 14 | cleanup() { 15 | rm -rf $TMPDIR 16 | docker stop "$uid" -t 1 17 | } 18 | trap cleanup EXIT 19 | 20 | tries=0 21 | while [ $tries -le 20 ]; do 22 | KUBECONFIG=$TMPDIR/k3s.yaml kubectl wait --for=condition=complete job --all -n kube-system --timeout=120s >/dev/null 2>&1 && exit 0 23 | sleep 5 24 | tries=$((tries + 1)) 25 | done 26 | 27 | echo 'Failed to boot k3s' 28 | exit 1 29 | -------------------------------------------------------------------------------- /images/ko/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | default = [] 3 | description = "The additional packages to install" 4 | type = list(string) 5 | } 6 | 7 | module "accts" { 8 | gid = 65532 9 | run-as = 65532 10 | source = "../../../tflib/accts" 11 | uid = 65532 12 | } 13 | 14 | output "config" { 15 | value = jsonencode({ 16 | contents = { 17 | packages = concat(["busybox", "build-base", "go", "git"], var.extra_packages) 18 | } 19 | accounts = module.accts.block 20 | entrypoint = { 21 | command = "/usr/bin/ko" 22 | } 23 | }) 24 | } 25 | 26 | -------------------------------------------------------------------------------- /images/ko/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/ko/main.tf: -------------------------------------------------------------------------------- 1 | variable "target_repository" { 2 | description = "The docker repo into which the image and attestations should be published." 3 | } 4 | 5 | module "versions" { 6 | package = "ko" 7 | source = "../../tflib/versions" 8 | } 9 | 10 | module "config" { 11 | extra_packages = [each.key] 12 | for_each = module.versions.versions 13 | source = "./config" 14 | } 15 | 16 | module "versioned" { 17 | build-dev = true 18 | config = module.config[each.key].config 19 | eol = each.value.eol 20 | for_each = module.versions.versions 21 | main_package = each.value.main 22 | name = basename(path.module) 23 | source = "../../tflib/publisher" 24 | target_repository = var.target_repository 25 | update-repo = each.value.is_latest 26 | } 27 | 28 | module "test-versioned" { 29 | digest = module.versioned[each.key].image_ref 30 | for_each = module.versions.versions 31 | source = "./tests" 32 | } 33 | 34 | module "tagger" { 35 | depends_on = [module.test-versioned] 36 | source = "../../tflib/tagger" 37 | tags = merge([for v in module.versioned : v.latest_tag_map]...) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /images/ko/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: ko 2 | image: cgr.dev/chainguard/ko 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal image to build and deploy Go applications using [ko](https://ko.build/) 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/ko-build/ko 9 | keywords: 10 | - application 11 | public: true 12 | tier: APPLICATION 13 | -------------------------------------------------------------------------------- /images/ko/tests/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | docker run --rm \ 6 | -v "${PWD}/example:/work" \ 7 | --workdir=/work \ 8 | -e KO_DOCKER_REPO=example.com \ 9 | -e CGO_ENABLED=1 \ 10 | "${IMAGE_NAME}" build ./ \ 11 | --push=false \ 12 | --preserve-import-paths \ 13 | --verbose 14 | -------------------------------------------------------------------------------- /images/ko/tests/example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/chainguard-images/images/images/ko/tests/example 2 | 3 | go 1.21 4 | -------------------------------------------------------------------------------- /images/ko/tests/example/main.go: -------------------------------------------------------------------------------- 1 | // Package main is the example from https://pkg.go.dev/cmd/cgo#hdr-Go_references_to_C 2 | 3 | package main 4 | 5 | // typedef int (*intFunc) (); 6 | // 7 | // int 8 | // bridge_int_func(intFunc f) 9 | // { 10 | // return f(); 11 | // } 12 | // 13 | // int fortytwo() 14 | // { 15 | // return 42; 16 | // } 17 | import "C" 18 | import "fmt" 19 | 20 | func main() { 21 | f := C.intFunc(C.fortytwo) 22 | fmt.Println(int(C.bridge_int_func(f))) 23 | // Output: 42 24 | } 25 | -------------------------------------------------------------------------------- /images/ko/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "oci_exec_test" "build" { 12 | digest = var.digest 13 | script = "./build.sh" 14 | working_dir = path.module 15 | } 16 | 17 | -------------------------------------------------------------------------------- /images/kubectl/config/main.tf: -------------------------------------------------------------------------------- 1 | module "accts" { 2 | source = "../../../tflib/accts" 3 | } 4 | 5 | variable "entrypoint" { 6 | default = "/usr/bin/kubectl" 7 | description = "Image entrypoint" 8 | } 9 | 10 | variable "command" { 11 | default = "--help" 12 | description = "Image command" 13 | } 14 | 15 | variable "extra_env_variables" { 16 | default = {} 17 | description = "Additional environment variables to set" 18 | } 19 | 20 | variable "extra_packages" { 21 | default = ["kubectl-default"] 22 | description = "The additional packages to install (e.g. kubectl-default, kubectl-1.28-default)." 23 | } 24 | 25 | variable "extra_paths" { 26 | default = [] 27 | description = "The additional paths to add." 28 | } 29 | 30 | output "config" { 31 | value = jsonencode({ 32 | "contents" : { 33 | "packages" : var.extra_packages 34 | }, 35 | "entrypoint" : { 36 | "command" : var.entrypoint 37 | }, 38 | "cmd" : var.command 39 | "accounts" : module.accts.block, 40 | "environment" : var.extra_env_variables 41 | "paths" : var.extra_paths 42 | }) 43 | } 44 | 45 | -------------------------------------------------------------------------------- /images/kubectl/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/kubectl/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | build-dev = true 19 | extra_dev_packages = ["kustomize", "bash-completion"] 20 | } 21 | 22 | module "test-latest" { 23 | source = "./tests" 24 | digest = module.latest.image_ref 25 | } 26 | 27 | resource "oci_tag" "latest" { 28 | depends_on = [module.test-latest] 29 | digest_ref = module.latest.image_ref 30 | tag = "latest" 31 | } 32 | 33 | resource "oci_tag" "latest-dev" { 34 | depends_on = [module.test-latest] 35 | digest_ref = module.latest.dev_ref 36 | tag = "latest-dev" 37 | } 38 | -------------------------------------------------------------------------------- /images/kubectl/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: kubectl 2 | image: cgr.dev/chainguard/kubectl 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal image with kubectl binary. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://kubernetes.io/docs/reference/kubectl/ 9 | keywords: 10 | - application 11 | aliases: 12 | - bitnami/kubectl:latest 13 | -------------------------------------------------------------------------------- /images/kubectl/tests/test/config: -------------------------------------------------------------------------------- 1 | This file is used as a dummy kubeconfig. We mount the `test/` dir during harness tests, 2 | and later a new kubeconfig is written into this file to perform `kubectl` commands against the cluster. 3 | -------------------------------------------------------------------------------- /images/laravel/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/laravel/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | extra_dev_packages = ["composer", "php-xmlwriter"] 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | module "test-latest-dev" { 27 | source = "./tests" 28 | check-dev = true 29 | digest = module.latest.dev_ref 30 | } 31 | 32 | resource "oci_tag" "latest" { 33 | depends_on = [module.test-latest] 34 | digest_ref = module.latest.image_ref 35 | tag = "latest" 36 | } 37 | 38 | resource "oci_tag" "latest-dev" { 39 | depends_on = [module.test-latest-dev] 40 | digest_ref = module.latest.dev_ref 41 | tag = "latest-dev" 42 | } 43 | -------------------------------------------------------------------------------- /images/laravel/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: laravel 2 | image: cgr.dev/chainguard/laravel 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimalist Wolfi-based Laravel images for developing, building, and running Laravel applications. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.laravel.com/ 9 | keywords: 10 | - base 11 | tier: BASE 12 | -------------------------------------------------------------------------------- /images/laravel/tests/01-fpm-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | CONTAINER_NAME=${CONTAINER_NAME:-"php-fpm-smoketest-${FREE_PORT}"} 6 | 7 | docker run -p "${FREE_PORT}:9000" -d --name $CONTAINER_NAME $IMAGE_NAME 8 | trap "docker logs $CONTAINER_NAME && docker rm -f $CONTAINER_NAME" EXIT 9 | sleep 1 10 | 11 | count=0 12 | max_retries=5 13 | wait_time=1 14 | while (( count < max_retries )) 15 | do 16 | if nc -z localhost ${FREE_PORT}; then 17 | echo "Server is running" 18 | exit 0 19 | else 20 | sleep $wait_time 21 | ((wait_time *= 2)) 22 | ((count++)) 23 | fi 24 | done 25 | -------------------------------------------------------------------------------- /images/laravel/tests/02-shutdown.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | LOGFILE=$(mktemp) 6 | ID=$(docker run --rm -d $IMAGE_NAME) 7 | docker attach $ID 2> $LOGFILE & 8 | sleep 5 9 | docker stop $ID 10 | 11 | grep "exiting, bye-bye!" $LOGFILE 12 | -------------------------------------------------------------------------------- /images/laravel/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "check-dev" { 12 | default = false 13 | description = "Whether to check for dev extensions" 14 | } 15 | 16 | data "oci_exec_test" "version" { 17 | digest = var.digest 18 | script = "docker run --entrypoint php --rm $IMAGE_NAME --version" 19 | } 20 | 21 | data "oci_exec_test" "fpm-server" { 22 | digest = var.digest 23 | script = "${path.module}/01-fpm-server.sh" 24 | } 25 | 26 | data "oci_exec_test" "fpm-shutdown" { 27 | digest = var.digest 28 | script = "${path.module}/02-shutdown.sh" 29 | } 30 | 31 | data "oci_exec_test" "laravel-extensions" { 32 | digest = var.digest 33 | script = "docker run --rm --entrypoint php $IMAGE_NAME -m | grep fileinfo" 34 | } 35 | 36 | data "oci_exec_test" "composer" { 37 | count = var.check-dev ? 1 : 0 38 | digest = var.digest 39 | script = "docker run --entrypoint composer --rm $IMAGE_NAME --version" 40 | } 41 | -------------------------------------------------------------------------------- /images/malcontent/config/main.tf: -------------------------------------------------------------------------------- 1 | module "accts" { 2 | source = "../../../tflib/accts" 3 | } 4 | 5 | terraform { 6 | required_providers { 7 | apko = { source = "chainguard-dev/apko" } 8 | } 9 | } 10 | 11 | variable "extra_packages" { 12 | default = ["malcontent"] 13 | description = "The additional packages to install (e.g. malcontent)." 14 | } 15 | 16 | output "config" { 17 | value = jsonencode({ 18 | "contents" : { 19 | "packages" : var.extra_packages 20 | }, 21 | "entrypoint" : { 22 | "command" : "/usr/bin/mal" 23 | }, 24 | "cmd" : "--help" 25 | "accounts" : module.accts.block 26 | }) 27 | } 28 | 29 | -------------------------------------------------------------------------------- /images/malcontent/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/malcontent/main.tf: -------------------------------------------------------------------------------- 1 | variable "target_repository" { 2 | description = "The docker repo into which the image and attestations should be published." 3 | } 4 | 5 | module "latest-config" { 6 | source = "./config" 7 | } 8 | 9 | module "latest" { 10 | build-dev = true 11 | config = module.latest-config.config 12 | main_package = "malcontent" 13 | name = basename(path.module) 14 | source = "../../tflib/publisher" 15 | target_repository = var.target_repository 16 | } 17 | 18 | module "test-latest" { 19 | digest = module.latest.image_ref 20 | source = "./tests" 21 | } 22 | 23 | module "tagger" { 24 | depends_on = [module.test-latest] 25 | source = "../../tflib/tagger" 26 | tags = module.latest.latest_tag_map 27 | } 28 | 29 | -------------------------------------------------------------------------------- /images/malcontent/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: malcontent 2 | image: cgr.dev/chainguard/malcontent 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Enumerate binary capabilities, including malicious behaviors. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/chainguard-dev/malcontent 9 | keywords: [] 10 | tier: APPLICATION 11 | public: true 12 | -------------------------------------------------------------------------------- /images/malcontent/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | imagetest = { source = "chainguard-dev/imagetest" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "imagetest_inventory" "inventory" { 12 | } 13 | 14 | resource "imagetest_harness_docker" "docker" { 15 | envs = { 16 | IMAGE_NAME = var.digest 17 | } 18 | inventory = data.imagetest_inventory.inventory 19 | name = "docker" 20 | } 21 | 22 | resource "imagetest_feature" "malcontent_analysis" { 23 | harness = imagetest_harness_docker.docker 24 | name = "malcontent-analysis" 25 | steps = [ 26 | { 27 | name = "run malcontent analysis" 28 | cmd = "docker run --rm $IMAGE_NAME --ignore-self=false analyze /usr/bin/mal | tee /dev/stderr | grep -Ei 'RISK|DESCRIPTION|EVIDENCE'" 29 | } 30 | ] 31 | } 32 | 33 | -------------------------------------------------------------------------------- /images/mariadb/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/mariadb/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | 16 | name = basename(path.module) 17 | 18 | target_repository = var.target_repository 19 | config = module.config.config 20 | build-dev = true 21 | } 22 | 23 | module "test-latest" { 24 | source = "./tests" 25 | digest = module.latest.image_ref 26 | } 27 | 28 | resource "oci_tag" "latest" { 29 | depends_on = [module.test-latest] 30 | digest_ref = module.latest.image_ref 31 | tag = "latest" 32 | } 33 | 34 | resource "oci_tag" "latest-dev" { 35 | depends_on = [module.test-latest] 36 | digest_ref = module.latest.dev_ref 37 | tag = "latest-dev" 38 | } 39 | -------------------------------------------------------------------------------- /images/mariadb/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: mariadb 2 | image: cgr.dev/chainguard/mariadb 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: "[MariaDB](https://mariadb.org) is one of the most popular open source relational databases." 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://mariadb.org 9 | keywords: 10 | - application 11 | aliases: 12 | - mariadb:latest 13 | -------------------------------------------------------------------------------- /images/mariadb/tests/02-runs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | # Start up the mariadb container in the background 6 | name=mariadb-${RANDOM} 7 | docker run -d --name $name -e MARIADB_ROOT_PASSWORD=secret "${IMAGE_NAME}" 8 | # Database needs some time to start up 9 | sleep 30 10 | 11 | # Exec into the container and run the mysql command 12 | docker exec $name mariadb -uroot -psecret -e "SHOW status;" | grep Uptime 13 | 14 | docker kill $name 15 | -------------------------------------------------------------------------------- /images/mariadb/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "oci_exec_test" "version" { 12 | digest = var.digest 13 | script = "docker run --rm $IMAGE_NAME --version" 14 | } 15 | 16 | data "oci_exec_test" "runs" { 17 | digest = var.digest 18 | script = "${path.module}/02-runs.sh" 19 | } 20 | -------------------------------------------------------------------------------- /images/maven/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "The additional packages to install" 3 | type = list(string) 4 | default = [] 5 | } 6 | 7 | variable "extra_environment" { 8 | description = "Additional apko environment." 9 | type = map(string) 10 | default = {} 11 | } 12 | 13 | module "accts" { 14 | source = "../../../tflib/accts" 15 | uid = 65532 16 | gid = 65532 17 | run-as = 65532 18 | } 19 | 20 | output "config" { 21 | value = jsonencode({ 22 | contents = { 23 | packages = concat([ 24 | ], var.extra_packages) 25 | } 26 | accounts = module.accts.block 27 | entrypoint = { 28 | command = "/usr/bin/mvn" 29 | } 30 | work-dir = "/home/build" 31 | environment = merge({ 32 | JAVA_HOME = "/usr/lib/jvm/default-jvm" 33 | LANG = "en_US.UTF-8" 34 | }, var.extra_environment) 35 | paths = [ 36 | { 37 | path = "/home/build" 38 | type = "directory" 39 | uid = 65532 40 | gid = 65532 41 | permissions = 493 42 | } 43 | ] 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /images/maven/docs/png/spring_initializr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chainguard-images/images/f6d25c31463ea902cc57522b553fba13dd15aa24/images/maven/docs/png/spring_initializr.png -------------------------------------------------------------------------------- /images/maven/docs/png/spring_whitelabel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chainguard-images/images/f6d25c31463ea902cc57522b553fba13dd15aa24/images/maven/docs/png/spring_whitelabel.png -------------------------------------------------------------------------------- /images/maven/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/maven/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { 12 | source = "./config" 13 | extra_packages = ["maven", "openjdk-23-default-jdk", "busybox", "glibc-locale-en"] 14 | } 15 | 16 | module "maven" { 17 | source = "../../tflib/publisher" 18 | name = basename(path.module) 19 | target_repository = var.target_repository 20 | config = module.config.config 21 | build-dev = true 22 | extra_dev_packages = ["openjdk-23-jmods", "binutils"] 23 | } 24 | 25 | module "test" { 26 | source = "./tests" 27 | digest = module.maven.image_ref 28 | } 29 | 30 | module "tagger" { 31 | source = "../../tflib/tagger" 32 | 33 | depends_on = [module.test] 34 | 35 | tags = { 36 | "latest" : module.maven.image_ref 37 | "latest-dev" : module.maven.dev_ref 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /images/maven/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: maven 2 | image: cgr.dev/chainguard/maven 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal image with the Maven build system. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://maven.apache.org/ 9 | keywords: 10 | - application 11 | aliases: 12 | - maven:latest 13 | -------------------------------------------------------------------------------- /images/melange/config/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | baseline_packages = ["alpine-keys", "bubblewrap", "wolfi-keys"] 3 | } 4 | 5 | terraform { 6 | required_providers { 7 | apko = { source = "chainguard-dev/apko" } 8 | } 9 | } 10 | 11 | variable "extra_packages" { 12 | default = ["melange"] 13 | description = "The additional packages to install" 14 | } 15 | 16 | output "config" { 17 | value = jsonencode({ 18 | "contents" : { 19 | // TODO: remove the need for using hardcoded local.baseline_packages by plumbing 20 | // these packages through var.extra_packages in all callers of this config module 21 | "packages" : distinct(concat(local.baseline_packages, var.extra_packages)) 22 | }, 23 | "entrypoint" : { 24 | "command" : "/usr/bin/melange" 25 | }, 26 | "cmd" : "--help", 27 | "work-dir" : "/work", 28 | "paths" : [ 29 | { 30 | "path" : "/work", 31 | "type" : "directory", 32 | "permissions" : 511 33 | } 34 | ] 35 | }) 36 | } 37 | 38 | -------------------------------------------------------------------------------- /images/melange/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/melange/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { source = "./config" } 12 | 13 | module "melange" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.config.config 18 | build-dev = true 19 | main_package = "melange" 20 | } 21 | 22 | module "test" { 23 | source = "./tests" 24 | digest = module.melange.image_ref 25 | } 26 | 27 | resource "oci_tag" "latest" { 28 | depends_on = [module.test] 29 | digest_ref = module.melange.image_ref 30 | tag = "latest" 31 | } 32 | 33 | resource "oci_tag" "latest-dev" { 34 | depends_on = [module.test] 35 | digest_ref = module.melange.dev_ref 36 | tag = "latest-dev" 37 | } 38 | -------------------------------------------------------------------------------- /images/melange/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: melange 2 | image: cgr.dev/chainguard/melange 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Container image for running [melange](https://github.com/chainguard-dev/melange) workflows to build APK packages. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/chainguard-dev/melange 9 | keywords: 10 | - application 11 | -------------------------------------------------------------------------------- /images/melange/tests/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | docker run --rm --privileged=true -v "${PWD}/images/melange/tests:/work" $IMAGE_NAME build minimal.yaml --arch=$(uname -m) --out-dir /tmp 6 | -------------------------------------------------------------------------------- /images/melange/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "oci_exec_test" "build" { 12 | digest = var.digest 13 | script = "${path.module}/build.sh" 14 | } 15 | -------------------------------------------------------------------------------- /images/melange/tests/minimal.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: minimal 3 | version: 0.0.1 4 | description: a very basic melange example 5 | target-architecture: [x86_64, aarch64] 6 | 7 | environment: 8 | contents: 9 | repositories: 10 | - https://packages.wolfi.dev/os 11 | keyring: 12 | - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub 13 | packages: 14 | - wolfi-base 15 | 16 | pipeline: 17 | - runs: | 18 | mkdir -p "${{targets.destdir}}" 19 | echo "hello" > "${{targets.destdir}}/hello" 20 | -------------------------------------------------------------------------------- /images/min-toolkit-debug/config/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | shared_packages = [ 3 | "bash", 4 | "bind-tools", 5 | "busybox", 6 | "coreutils", 7 | "curl", 8 | "dhcping", 9 | "drill", 10 | "dstat", 11 | "fatrace", 12 | "findutils", 13 | "git", 14 | "gperf", 15 | "iproute2", 16 | "jq", 17 | "ltrace", 18 | "mycli", 19 | "net-tools", 20 | "ngrep", 21 | "nmap", 22 | "openssl", 23 | "py3-pgcli", 24 | "redis", 25 | "socat", 26 | "strace", 27 | "sysstat", 28 | "tcptraceroute", 29 | ] 30 | } 31 | 32 | output "shared_packages" { 33 | description = "The list of shared_packages b/w fips and non-fips image" 34 | value = local.shared_packages 35 | } 36 | 37 | variable "extra_packages" { 38 | default = [] 39 | description = "The additional packages to install." 40 | } 41 | 42 | output "config" { 43 | value = jsonencode({ 44 | "contents" = { 45 | "packages" = concat(var.extra_packages, local.shared_packages) 46 | } 47 | "entrypoint" = { 48 | "command" = "/bin/bash -c" 49 | } 50 | }) 51 | } 52 | 53 | -------------------------------------------------------------------------------- /images/min-toolkit-debug/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/min-toolkit-debug/main.tf: -------------------------------------------------------------------------------- 1 | variable "target_repository" { 2 | description = "The docker repo into which the image and attestations should be published." 3 | } 4 | 5 | module "latest-config" { 6 | extra_packages = [ 7 | "crane", # go toolchain 8 | "grpcurl", # go toolchain 9 | "oras", # go toolchain 10 | "yq" # go toolchain 11 | ] 12 | source = "./config" 13 | } 14 | 15 | module "latest" { 16 | build-dev = true 17 | config = module.latest-config.config 18 | main_package = "" 19 | name = basename(path.module) 20 | source = "../../tflib/publisher" 21 | target_repository = var.target_repository 22 | } 23 | 24 | module "test-latest" { 25 | digest = module.latest.image_ref 26 | source = "./tests" 27 | target_repository = var.target_repository 28 | test_repository = var.test_repository 29 | } 30 | 31 | module "tagger" { 32 | depends_on = [module.test-latest] 33 | source = "../../tflib/tagger" 34 | tags = { "latest" = module.latest.image_ref } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /images/min-toolkit-debug/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: min-toolkit-debug 2 | image: cgr.dev/chainguard/min-toolkit-debug 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Wolfi container image with some debugging utilies included. Suitable for using as a debugging tool. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://wolfi.dev 9 | keywords: 10 | - application 11 | tier: APPLICATION 12 | public: true 13 | -------------------------------------------------------------------------------- /images/min-toolkit-debug/tests/docker-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | source ../libs/libs.sh 6 | 7 | test_entrypoint() { 8 | local image 9 | image="$(get_test_image "min-toolkit-debug")" 10 | docker run --rm --entrypoint "$1" "${image}" "$2" 11 | } 12 | 13 | main() { 14 | test_entrypoint "bash" "--version" 15 | test_entrypoint "bash" "--help" 16 | test_entrypoint "grpcurl" "--version" 17 | test_entrypoint "grpcurl" "--help" 18 | test_entrypoint "oras" "--help" 19 | test_entrypoint "oras" "version" 20 | } 21 | 22 | main "$@" 23 | 24 | 25 | -------------------------------------------------------------------------------- /images/min-toolkit-debug/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | imagetest = { source = "chainguard-dev/imagetest" } 4 | oci = { source = "chainguard-dev/oci" } 5 | } 6 | } 7 | 8 | variable "digest" { 9 | description = "The image digest to run tests over." 10 | } 11 | 12 | variable "target_repository" { 13 | description = "The docker repo into which the image and attestations should be published." 14 | } 15 | 16 | variable "test_repository" { 17 | description = "The docker repo root to use for sourcing test images." 18 | } 19 | 20 | locals { 21 | parsed = provider::oci::parse(var.digest) 22 | } 23 | 24 | module "bash_sandbox" { 25 | source = "../../../tflib/imagetest/sandboxes/bash/" 26 | target_repository = var.target_repository 27 | } 28 | 29 | module "dind_test" { 30 | cwd = path.module 31 | images = { min-toolkit-debug = var.digest } 32 | source = "../../../tflib/imagetest/tests/docker-in-docker" 33 | tests = [ 34 | { 35 | name = "basic functionality" 36 | image = module.bash_sandbox.image_ref 37 | cmd = "./docker-test.sh" 38 | } 39 | ] 40 | } 41 | 42 | -------------------------------------------------------------------------------- /images/mongodb/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/mongodb/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.config.config 18 | build-dev = true 19 | } 20 | 21 | module "test" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | resource "oci_tag" "latest" { 27 | depends_on = [module.test] 28 | digest_ref = module.latest.image_ref 29 | tag = "latest" 30 | } 31 | 32 | resource "oci_tag" "latest-dev" { 33 | depends_on = [module.test] 34 | digest_ref = module.latest.dev_ref 35 | tag = "latest-dev" 36 | } -------------------------------------------------------------------------------- /images/mongodb/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: mongodb 2 | image: cgr.dev/chainguard/mongodb 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: "[MongoDB](https://www.mongodb.com/) is a document-oriented database management system. MongoDB is a popular example of a NoSQL database, and stores data in JSON-like documents." 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/mongodb/mongo 9 | keywords: 10 | - application 11 | - ai 12 | aliases: 13 | - mongo:latest 14 | -------------------------------------------------------------------------------- /images/mongodb/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "fips_enabled" { 12 | description = "Indicates whether this is a FIPS image or not." 13 | default = 0 14 | } 15 | 16 | # Commenting out to diagnose CI 17 | data "oci_exec_test" "check" { 18 | digest = var.digest 19 | script = "${path.module}/check.sh" 20 | env = [ 21 | { 22 | name = "FIPS_ENABLED" 23 | value = var.fips_enabled 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /images/nginx/examples/hello-world/site-content/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Nginx 6 | 7 | 8 |

Hello World from Nginx!

9 | 10 | 11 | -------------------------------------------------------------------------------- /images/nginx/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/nginx/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { 12 | source = "./config" 13 | extra_packages = ["nginx-mainline", "nginx-mainline-package-config"] 14 | } 15 | 16 | module "latest" { 17 | source = "../../tflib/publisher" 18 | name = basename(path.module) 19 | target_repository = var.target_repository 20 | config = module.latest-config.config 21 | build-dev = true 22 | } 23 | 24 | module "test-latest" { 25 | source = "./tests" 26 | digest = module.latest.image_ref 27 | } 28 | 29 | resource "oci_tag" "latest" { 30 | depends_on = [module.test-latest] 31 | digest_ref = module.latest.image_ref 32 | tag = "latest" 33 | } 34 | 35 | resource "oci_tag" "latest-dev" { 36 | depends_on = [module.test-latest] 37 | digest_ref = module.latest.dev_ref 38 | tag = "latest-dev" 39 | } 40 | -------------------------------------------------------------------------------- /images/node/example/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /images/node/example/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | # Based on https://docs.docker.com/language/nodejs/build-images/ 3 | 4 | ARG BUILDER=cgr.dev/chainguard/node:latest-dev 5 | ARG BASE=cgr.dev/chainguard/node:latest 6 | 7 | FROM ${BUILDER} AS builder 8 | WORKDIR /build-stage 9 | COPY package*.json ./ 10 | ENV NODE_ENV=production 11 | 12 | # Make sure the alternative package managers got installed in the -dev image 13 | RUN corepack --version && \ 14 | pnpm --version && \ 15 | yarn --version 16 | 17 | RUN npm ci --omit=dev 18 | # Copy the files you need 19 | COPY . ./ 20 | # npm run build or whatever you need to do to build your app 21 | 22 | FROM ${BASE} 23 | COPY --from=builder /build-stage/ . 24 | ENTRYPOINT [""] 25 | CMD ["dumb-init", "node", "server.js"] 26 | -------------------------------------------------------------------------------- /images/node/example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "keywords": [], 7 | "author": "", 8 | "license": "ISC", 9 | "dependencies": { 10 | "jsonwebtoken": "^9.0.2", 11 | "ronin-mocks": "^0.1.11", 12 | "ronin-server": "^0.1.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /images/node/example/server.js: -------------------------------------------------------------------------------- 1 | const ronin = require('ronin-server') 2 | const mocks = require('ronin-mocks') 3 | 4 | const server = ronin.server() 5 | 6 | server.use('/', mocks.server(server.Router(), false, true)) 7 | server.start() 8 | -------------------------------------------------------------------------------- /images/node/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/node/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: node 2 | image: cgr.dev/chainguard/node 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal container image for running NodeJS apps 6 | compatibility_notes: | 7 | The image specifies a default non-root `node` user (UID 65532), and a working directory at `/app`, owned by that `node` user, and accessible to all users. 8 | readme_file: README.md 9 | upstream_url: https://nodejs.org/ 10 | keywords: 11 | - base 12 | - featured 13 | public: true 14 | tier: BASE 15 | aliases: 16 | - bitnami/node:latest 17 | - node:latest 18 | -------------------------------------------------------------------------------- /images/node/tests/01-dockerfile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | TAG="smoke-test-${FREE_PORT}" 6 | CONTAINER="node-example-${FREE_PORT}" 7 | 8 | function cleanup() { 9 | docker kill ${CONTAINER} 10 | docker rmi -f ${TAG} 11 | } 12 | 13 | trap cleanup EXIT 14 | 15 | docker run --rm "${IMAGE_NAME}" --version 16 | 17 | docker build \ 18 | --build-arg BUILDER=${DEV_IMAGE_NAME} \ 19 | --build-arg BASE=${IMAGE_NAME} \ 20 | --tag ${TAG} --file ./../example/Dockerfile ../example 21 | 22 | docker run --rm -p ${FREE_PORT}:8000 -d --name ${CONTAINER} ${TAG} 23 | curl --retry 3 --retry-all-errors http://localhost:${FREE_PORT}/test | grep payload 24 | -------------------------------------------------------------------------------- /images/node/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "dev-digest" { 12 | description = "The image dev digest to run tests over." 13 | } 14 | 15 | data "oci_exec_test" "dockerfile" { 16 | digest = var.digest 17 | env = [{ 18 | name = "DEV_IMAGE_NAME" 19 | value = var.dev-digest 20 | }] 21 | script = "./01-dockerfile.sh" 22 | working_dir = path.module 23 | } 24 | 25 | -------------------------------------------------------------------------------- /images/openscap/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | default = [] 3 | description = "The additional packages to install" 4 | type = list(string) 5 | } 6 | 7 | module "accts" { 8 | gid = 65532 9 | run-as = 65532 10 | source = "../../../tflib/accts" 11 | uid = 65532 12 | } 13 | 14 | output "config" { 15 | value = jsonencode({ 16 | contents = { 17 | packages = concat([ 18 | "py3-docker", 19 | "docker-cli", 20 | "scap-security-guide", 21 | "chainguard-security-guide", 22 | # oscap-docker hard codes /usr/bin/python3 as the interpreter 23 | "python3", 24 | ], var.extra_packages) 25 | } 26 | // 27 | accounts = module.accts.block 28 | entrypoint = { 29 | command = "/usr/bin/oscap" 30 | } 31 | }) 32 | } 33 | 34 | -------------------------------------------------------------------------------- /images/openscap/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/openscap/main.tf: -------------------------------------------------------------------------------- 1 | variable "target_repository" { 2 | description = "The docker repo into which the image and attestations should be published." 3 | } 4 | 5 | module "versions" { 6 | package = "openscap" 7 | source = "../../tflib/versions" 8 | } 9 | 10 | module "config" { 11 | extra_packages = [each.key] 12 | for_each = module.versions.versions 13 | source = "./config" 14 | } 15 | 16 | module "versioned" { 17 | build-dev = true 18 | config = module.config[each.key].config 19 | eol = each.value.eol 20 | for_each = module.versions.versions 21 | main_package = each.value.main 22 | name = basename(path.module) 23 | source = "../../tflib/publisher" 24 | target_repository = var.target_repository 25 | update-repo = each.value.is_latest 26 | } 27 | 28 | module "test-versioned" { 29 | digest = module.versioned[each.key].image_ref 30 | for_each = module.versions.versions 31 | source = "./tests" 32 | } 33 | 34 | module "tagger" { 35 | depends_on = [module.test-versioned] 36 | source = "../../tflib/tagger" 37 | tags = merge([for v in module.versioned : v.latest_tag_map]...) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /images/openscap/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: openscap 2 | image: cgr.dev/chainguard/openscap 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: "NIST Certified SCAP 1.2 toolkit" 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: "https://github.com/OpenSCAP/openscap" 9 | keywords: [] 10 | public: true 11 | tier: APPLICATION 12 | -------------------------------------------------------------------------------- /images/opentelemetry-collector-contrib/config/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | baseline_packages = ["busybox", "opentelemetry-collector-contrib-compat"] 3 | } 4 | 5 | module "accts" { 6 | source = "../../../tflib/accts" 7 | } 8 | 9 | variable "extra_packages" { 10 | default = [""] 11 | description = "The additional packages to install." 12 | } 13 | 14 | output "config" { 15 | value = jsonencode({ 16 | "contents" : { 17 | "packages" : distinct(concat(local.baseline_packages, var.extra_packages)) 18 | }, 19 | "entrypoint" : { 20 | "command" : "/usr/bin/otelcol-contrib" 21 | }, 22 | "accounts" : module.accts.block, 23 | "environment" : { 24 | "PORT" : "8080" 25 | }, 26 | "paths" : [ 27 | { 28 | "path" : "/conf", 29 | "type" : "directory", 30 | "uid" : 65532, 31 | "gid" : 65532, 32 | "permissions" : 493 33 | } 34 | ] 35 | }) 36 | } 37 | 38 | -------------------------------------------------------------------------------- /images/opentelemetry-collector-contrib/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/opentelemetry-collector-contrib/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: opentelemetry-collector-contrib 2 | image: cgr.dev/chainguard/opentelemetry-collector-contrib 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal image with [opentelemetry-collector-contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib). 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/open-telemetry/opentelemetry-collector-contrib 9 | keywords: 10 | - application 11 | aliases: 12 | - otel/opentelemetry-collector-contrib:latest 13 | tier: APPLICATION 14 | public: true -------------------------------------------------------------------------------- /images/php/config/fpm/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | baseline_packages = ["ca-certificates", "curl"] 3 | } 4 | 5 | module "accts" { 6 | name = "php" 7 | source = "../../../../tflib/accts" 8 | } 9 | 10 | terraform { 11 | required_providers { 12 | apko = { source = "chainguard-dev/apko" } 13 | } 14 | } 15 | 16 | variable "extra_packages" { 17 | default = ["php", "php-fpm"] 18 | description = "The additional packages to install (e.g. php-fpm)." 19 | } 20 | 21 | output "config" { 22 | value = jsonencode({ 23 | "contents" : { 24 | // TODO: remove the need for using hardcoded local.baseline_packages by plumbing 25 | // these packages through var.extra_packages in all callers of this config module 26 | "packages" : distinct(concat(local.baseline_packages, var.extra_packages)) 27 | }, 28 | "entrypoint" : { 29 | "type" : "service-bundle", 30 | "services" : { 31 | "php-fpm" : "/usr/sbin/php-fpm" 32 | } 33 | }, 34 | "work-dir" : "/app", 35 | "accounts" : module.accts.block, 36 | "paths" : [ 37 | { 38 | "path" : "/app", 39 | "type" : "directory", 40 | "uid" : 65532, 41 | "gid" : 65532, 42 | "permissions" : 511 43 | } 44 | ] 45 | }) 46 | } 47 | 48 | -------------------------------------------------------------------------------- /images/php/config/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | baseline_packages = ["ca-certificates", "curl"] 3 | } 4 | 5 | module "accts" { 6 | name = "php" 7 | source = "../../../tflib/accts" 8 | } 9 | 10 | terraform { 11 | required_providers { 12 | apko = { source = "chainguard-dev/apko" } 13 | } 14 | } 15 | 16 | variable "extra_packages" { 17 | default = ["php"] 18 | description = "The additional packages to install (e.g. php, php-8.1)." 19 | } 20 | 21 | output "config" { 22 | value = jsonencode({ 23 | "contents" : { 24 | // TODO: remove the need for using hardcoded local.baseline_packages by plumbing 25 | // these packages through var.extra_packages in all callers of this config module 26 | "packages" : distinct(concat(local.baseline_packages, var.extra_packages)) 27 | }, 28 | "entrypoint" : { 29 | "command" : "/bin/php" 30 | }, 31 | "work-dir" : "/app", 32 | "accounts" : module.accts.block, 33 | "paths" : [ 34 | { 35 | "path" : "/app", 36 | "type" : "directory", 37 | "uid" : 65532, 38 | "gid" : 65532, 39 | "permissions" : 511 40 | } 41 | ] 42 | }) 43 | } 44 | 45 | -------------------------------------------------------------------------------- /images/php/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.fpm-tagger.imagetags, module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/php/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: php 2 | image: cgr.dev/chainguard/php 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimalist Wolfi-based PHP images for building and running PHP applications. Includes both `dev` and `fpm` variants. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.php.net/ 9 | keywords: 10 | - base 11 | - featured 12 | tier: BASE 13 | aliases: 14 | - php:latest 15 | -------------------------------------------------------------------------------- /images/php/tests/01-fpm-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | apk add wait-for-it 6 | 7 | NAME="php-fpm-smoketest-$(shuf -i 0-128 -n 1)" 8 | 9 | docker run -d --name "${NAME}" "${IMAGE_NAME}" 10 | trap "docker logs ${NAME} && docker rm -f ${NAME}" EXIT 11 | sleep 1 12 | 13 | IP="$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${NAME})" 14 | wait-for-it $IP:9000 --timeout=60 15 | -------------------------------------------------------------------------------- /images/php/tests/02-shutdown.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | LOGFILE=$(mktemp) 6 | ID=$(docker run --rm -d $IMAGE_NAME) 7 | docker attach $ID 2> $LOGFILE & 8 | sleep 5 9 | docker stop $ID 10 | 11 | grep "exiting, bye-bye!" $LOGFILE -------------------------------------------------------------------------------- /images/postgres/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/postgres/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: postgres 2 | image: cgr.dev/chainguard/postgres 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal image for PostgreSQL, an advanced object-relational database management system. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.postgresql.org/ 9 | keywords: 10 | - application 11 | - ai 12 | - featured 13 | tier: APPLICATION 14 | aliases: 15 | - postgres:latest 16 | -------------------------------------------------------------------------------- /images/python/config/main.tf: -------------------------------------------------------------------------------- 1 | module "accts" { 2 | source = "../../../tflib/accts" 3 | } 4 | 5 | terraform { 6 | required_providers { 7 | apko = { source = "chainguard-dev/apko" } 8 | } 9 | } 10 | 11 | variable "extra_packages" { 12 | default = ["python-3"] 13 | description = "The additional packages to install (e.g. python-3.11)." 14 | } 15 | 16 | output "config" { 17 | value = jsonencode({ 18 | "contents" : { 19 | "packages" : var.extra_packages 20 | }, 21 | "entrypoint" : { 22 | "command" : "/usr/bin/python" 23 | }, 24 | "accounts" : module.accts.block 25 | }) 26 | } 27 | 28 | -------------------------------------------------------------------------------- /images/python/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/python/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | extra_dev_packages = [ 19 | "build-base", 20 | "py3-pip", 21 | "python3-dev", 22 | "uv" 23 | ] 24 | } 25 | 26 | module "test-latest" { 27 | source = "./tests" 28 | digest = module.latest.image_ref 29 | } 30 | 31 | module "test-latest-dev" { 32 | source = "./tests" 33 | check-dev = true # Check for PIP in dev variants. 34 | digest = module.latest.dev_ref 35 | } 36 | 37 | resource "oci_tag" "latest" { 38 | depends_on = [module.test-latest] 39 | digest_ref = module.latest.image_ref 40 | tag = "latest" 41 | } 42 | 43 | resource "oci_tag" "latest-dev" { 44 | depends_on = [module.test-latest-dev] 45 | digest_ref = module.latest.dev_ref 46 | tag = "latest-dev" 47 | } 48 | -------------------------------------------------------------------------------- /images/python/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: python 2 | image: cgr.dev/chainguard/python 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal Python image based on Wolfi. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.python.org/ 9 | keywords: 10 | - base 11 | - featured 12 | aliases: 13 | - bitnami/python:latest 14 | - python:latest 15 | - python:slim 16 | - python:alpine 17 | -------------------------------------------------------------------------------- /images/python/tests/02-check-pip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | docker run --rm --entrypoint /usr/bin/pip "${IMAGE_NAME}" --version 6 | -------------------------------------------------------------------------------- /images/python/tests/03-check-numpy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | docker run -u root --entrypoint sh --rm "${IMAGE_NAME}" -c "pip install numpy; python -c 'import numpy; print(numpy.__version__)'" 6 | -------------------------------------------------------------------------------- /images/python/tests/04-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | NEW_IMAGE_TAG="app-${RANDOM}" 6 | 7 | # Using registry.local:5000 as the FROM in `docker build` fails with 8 | # current versions of docker that use containerd under the hood. 9 | # Pre-pulling it uses docker's heuristics for allowing insecure registries. 10 | docker pull ${IMAGE_NAME} 11 | 12 | docker build \ 13 | --build-arg=IMAGE_NAME="${IMAGE_NAME}" \ 14 | --tag "${NEW_IMAGE_TAG}" . 15 | 16 | id=$(docker run --detach --publish "${FREE_PORT}:5000" ${NEW_IMAGE_TAG}) 17 | trap "docker kill ${id}" EXIT 18 | 19 | for i in {1..5} 20 | do 21 | if curl http://0.0.0.0:${FREE_PORT} | grep 'Hello, World!'; then 22 | exit 0 23 | fi 24 | sleep 1 25 | done 26 | 27 | exit 1 28 | -------------------------------------------------------------------------------- /images/python/tests/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG IMAGE_NAME 2 | 3 | FROM ${IMAGE_NAME} 4 | 5 | WORKDIR /app 6 | 7 | COPY . . 8 | 9 | USER root 10 | 11 | RUN pip install -r requirements.txt 12 | 13 | ENTRYPOINT ["python", "-m", "flask", "--app", "/app/hello.py", "run", "--host", "0.0.0.0"] 14 | -------------------------------------------------------------------------------- /images/python/tests/hello.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from flask import Flask 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route("/") 8 | def hello(): 9 | return "Hello, World!" 10 | -------------------------------------------------------------------------------- /images/python/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "warn_on_failure" { 12 | description = "Whether to fail or warn if the test fails. Used only for EOL images." 13 | default = false 14 | } 15 | 16 | variable "check-dev" { 17 | default = false 18 | description = "Whether to check for dev extensions" 19 | } 20 | 21 | data "oci_exec_test" "version" { 22 | digest = var.digest 23 | script = "docker run --rm $IMAGE_NAME --version" 24 | } 25 | 26 | data "oci_exec_test" "check-pip" { 27 | count = var.check-dev ? 1 : 0 28 | digest = var.digest 29 | script = "${path.module}/02-check-pip.sh" 30 | } 31 | 32 | data "oci_exec_test" "check-numpy" { 33 | count = var.check-dev ? 1 : 0 34 | digest = var.digest 35 | script = "${path.module}/03-check-numpy.sh" 36 | } 37 | 38 | data "oci_exec_test" "check-build" { 39 | count = var.check-dev ? 1 : 0 40 | digest = var.digest 41 | script = "./04-build.sh" 42 | working_dir = path.module 43 | } 44 | -------------------------------------------------------------------------------- /images/python/tests/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | -------------------------------------------------------------------------------- /images/pytorch/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/pytorch/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: pytorch 2 | image: cgr.dev/chainguard/pytorch 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: | 6 | A minimal, [wolfi](https://github.com/wolfi-dev)-based image for pytorch, a Python package that provides two high-level features: Tensor computation with strong GPU acceleration and Deep neural networks built on a tape-based autograd system. 7 | compatibility_notes: "" 8 | readme_file: README.md 9 | upstream_url: https://www.pytorch.org/ 10 | keywords: 11 | - ai 12 | - base 13 | - ai-gpu 14 | - featured 15 | public: true 16 | aliases: 17 | - pytorch/pytorch:latest 18 | -------------------------------------------------------------------------------- /images/pytorch/model_builder.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | class TinyModel(torch.nn.Module): 4 | 5 | def __init__(self): 6 | super(TinyModel, self).__init__() 7 | 8 | self.linear1 = torch.nn.Linear(100, 200) 9 | self.activation = torch.nn.ReLU() 10 | self.linear2 = torch.nn.Linear(200, 10) 11 | self.softmax = torch.nn.Softmax() 12 | 13 | def forward(self, x): 14 | x = self.linear1(x) 15 | x = self.activation(x) 16 | x = self.linear2(x) 17 | x = self.softmax(x) 18 | return x 19 | 20 | tinymodel = TinyModel() 21 | 22 | print('The model:') 23 | print(tinymodel) 24 | 25 | print('\n\nJust one layer:') 26 | print(tinymodel.linear2) 27 | 28 | print('\n\nModel params:') 29 | for param in tinymodel.parameters(): 30 | print(param) 31 | 32 | print('\n\nLayer params:') 33 | for param in tinymodel.linear2.parameters(): 34 | print(param) 35 | -------------------------------------------------------------------------------- /images/pytorch/tests/check-pytorch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 4 | # Tests pytorch with its helm chart and runs sample scripts to 5 | # confirm its functionality 6 | # 7 | # This helm installation is intendended to run on devices with only cpu; 8 | # to test features utilizing GPU, please refer TESTING.md 9 | 10 | set -o errexit -o nounset -o errtrace -o pipefail -x 11 | 12 | my_d=$(cd "${0%/*}" && pwd) 13 | exit_code=1 14 | 15 | run_scripts() { 16 | pod_name=$(kubectl get pods -n pytorch -l "app.kubernetes.io/instance=pytorch" -o custom-columns=:metadata.name --no-headers | head -n 1) 17 | kubectl cp "${my_d}/quickstart.py" "$pod_name":/tmp/pytorch.py -n pytorch 18 | kubectl exec "$pod_name" -n pytorch -- python /tmp/pytorch.py 19 | exit_code=$? 20 | if [ $exit_code -eq 0 ]; then 21 | printf "Test ran successfully" 22 | return 0 23 | fi 24 | echo "FAILED: Unable to run test scripts" 25 | exit 1 26 | } 27 | 28 | run_scripts 29 | -------------------------------------------------------------------------------- /images/redis/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/redis/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { 12 | source = "./configs" 13 | 14 | extra_repositories = ["https://packages.cgr.dev/extras"] 15 | extra_keyring = ["https://packages.cgr.dev/extras/chainguard-extras.rsa.pub"] 16 | } 17 | 18 | module "latest" { 19 | source = "../../tflib/publisher" 20 | name = basename(path.module) 21 | target_repository = var.target_repository 22 | config = module.latest-config.config 23 | build-dev = true 24 | } 25 | 26 | module "test-latest" { 27 | source = "./tests" 28 | digest = module.latest.image_ref 29 | } 30 | 31 | resource "oci_tag" "latest" { 32 | depends_on = [module.test-latest] 33 | digest_ref = module.latest.image_ref 34 | tag = "latest" 35 | } 36 | 37 | resource "oci_tag" "latest-dev" { 38 | depends_on = [module.test-latest] 39 | digest_ref = module.latest.dev_ref 40 | tag = "latest-dev" 41 | } 42 | -------------------------------------------------------------------------------- /images/redis/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: redis 2 | image: cgr.dev/chainguard/redis 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Chainguard image for [Redis](https://github.com/redis/redis), an in-memory database that persists on disk. Redis is a key-value store, supporting an array of different values, including Strings, Lists, Sets, Sorted Sets, Hashes, Streams, HyperLogLogs, and Bitmaps. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/redis/redis 9 | keywords: 10 | - application 11 | tier: APPLICATION 12 | aliases: 13 | - redis:latest 14 | -------------------------------------------------------------------------------- /images/redis/tests/02-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | # to prevent duplicate container name issues when we run similar tests for both versions within the configs/ folder. 6 | CONTAINER_NAME=${CONTAINER_NAME:-"redis-smoketest-$(date +%s)-${RANDOM}"} 7 | 8 | # Run two containers on the same network (just use host for simplicity) 9 | # The server should start up and listen, and the client will run ping 10 | 11 | docker run -d -p ${FREE_PORT}:6379 --name $CONTAINER_NAME $IMAGE_NAME 12 | 13 | trap "docker logs $CONTAINER_NAME && docker rm -f $CONTAINER_NAME && rm ${CONTAINER_NAME}_${FREE_PORT}.txt" EXIT 14 | 15 | sleep 15 16 | 17 | # Send commands to Redis via nc 18 | ( echo "SET mykey myvalue"; echo "GET mykey"; echo "QUIT" ) | nc localhost ${FREE_PORT} > ${CONTAINER_NAME}_${FREE_PORT}.txt 19 | 20 | # Check if the command passed 21 | grep -q "myvalue" ${CONTAINER_NAME}_${FREE_PORT}.txt 22 | -------------------------------------------------------------------------------- /images/redis/tests/03-server-activedefrag.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | # to prevent duplicate container name issues when we run similar tests for both versions within the configs/ folder. 6 | CONTAINER_NAME=${CONTAINER_NAME:-"redis-defragtest-$(date +%s)-$(uuidgen)"} 7 | 8 | # Turn on activedefrag to ensure redis is being built with jemalloc 9 | 10 | docker run -d --name $CONTAINER_NAME $IMAGE_NAME 11 | 12 | trap "docker logs $CONTAINER_NAME && docker rm -f $CONTAINER_NAME" EXIT 13 | 14 | sleep 15 15 | 16 | docker exec -i $CONTAINER_NAME redis-cli config set activedefrag yes | grep OK 17 | 18 | # Check if the setting took 19 | docker exec -i $CONTAINER_NAME redis-cli config get activedefrag | grep "yes" 20 | -------------------------------------------------------------------------------- /images/redis/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | variable "test_activedefrag" { 12 | default = true 13 | } 14 | 15 | data "oci_exec_test" "version" { 16 | digest = var.digest 17 | script = "docker run --rm $IMAGE_NAME --version" 18 | } 19 | 20 | data "oci_exec_test" "server" { 21 | digest = var.digest 22 | script = "${path.module}/02-server.sh" 23 | } 24 | 25 | data "oci_exec_test" "activedefrag" { 26 | count = var.test_activedefrag ? 1 : 0 27 | 28 | digest = var.digest 29 | script = "${path.module}/03-server-activedefrag.sh" 30 | } 31 | -------------------------------------------------------------------------------- /images/ruby/config/main.tf: -------------------------------------------------------------------------------- 1 | module "accts" { 2 | source = "../../../tflib/accts" 3 | } 4 | 5 | terraform { 6 | required_providers { 7 | apko = { source = "chainguard-dev/apko" } 8 | } 9 | } 10 | 11 | variable "extra_packages" { 12 | default = [] 13 | description = "The additional packages to install (e.g. ruby, ruby-3.2)." 14 | } 15 | 16 | output "config" { 17 | value = jsonencode({ 18 | "contents" : { 19 | "packages" : var.extra_packages 20 | }, 21 | "entrypoint" : { 22 | "command" : "/usr/bin/ruby" 23 | }, 24 | "cmd" : "--version", 25 | "work-dir" : "/work", 26 | "accounts" : module.accts.block, 27 | "paths" : [ 28 | { 29 | "path" : "/work", 30 | "type" : "directory", 31 | "permissions" : 511 32 | } 33 | ] 34 | }) 35 | } 36 | 37 | -------------------------------------------------------------------------------- /images/ruby/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/ruby/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | locals { 12 | version = "3.4" 13 | } 14 | 15 | module "latest-config" { 16 | source = "./config" 17 | extra_packages = ["ruby-${local.version}"] 18 | } 19 | 20 | module "latest" { 21 | source = "../../tflib/publisher" 22 | name = basename(path.module) 23 | target_repository = var.target_repository 24 | config = module.latest-config.config 25 | extra_dev_packages = [ 26 | "build-base", 27 | "ruby-${local.version}-dev", 28 | "ruby${local.version}-bundler", 29 | ] 30 | } 31 | 32 | module "test-latest" { 33 | source = "./tests" 34 | digest = module.latest.image_ref 35 | } 36 | 37 | resource "oci_tag" "latest" { 38 | depends_on = [module.test-latest] 39 | digest_ref = module.latest.image_ref 40 | tag = "latest" 41 | } 42 | 43 | resource "oci_tag" "latest-dev" { 44 | depends_on = [module.test-latest] 45 | digest_ref = module.latest.dev_ref 46 | tag = "latest-dev" 47 | } 48 | -------------------------------------------------------------------------------- /images/ruby/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: ruby 2 | image: cgr.dev/chainguard/ruby 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimal Ruby base image. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.ruby-lang.org 9 | keywords: 10 | - base 11 | - featured 12 | aliases: 13 | - ruby:latest 14 | -------------------------------------------------------------------------------- /images/ruby/tests/02-hello-world.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail 4 | 5 | cat > hello-world.rb <0.6' 8 | require 'chronic' 9 | 10 | puts "Hello World. It is " + Chronic.parse('today').to_s 11 | EOF 12 | 13 | TMP=$(mktemp -d) 14 | 15 | # Make this writeable by the nonroot container user 16 | chmod 777 "${TMP}" 17 | 18 | # Install the gem 19 | docker run --rm -v "${TMP}:/home/nonroot" -v $(pwd)/hello-world.rb:/src/hello-world.rb \ 20 | --entrypoint "gem" "${IMAGE_NAME}" install --user-install chronic 21 | 22 | # Run the container 23 | docker run --rm -v "${TMP}:/home/nonroot" -v $(pwd)/hello-world.rb:/src/hello-world.rb \ 24 | --entrypoint "ruby" "${IMAGE_NAME}" \ 25 | /src/hello-world.rb \ 26 | | grep "Hello World" 27 | -------------------------------------------------------------------------------- /images/ruby/tests/03-base-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | TMP=$(mktemp -d) 6 | 7 | cat > $TMP/hello-world-dockerfile.rb <0.6' 10 | require 'chronic' 11 | 12 | puts "Hello World. It is " + Chronic.parse('today').to_s 13 | EOF 14 | 15 | # The image can be used as a base image. 16 | cat > $TMP/Dockerfile < hello.rs 6 | RUN rustc -C target-feature=+crt-static hello.rs 7 | 8 | FROM $BASE 9 | 10 | COPY --from=build /work/hello /usr/local/bin/ 11 | CMD ["hello"] 12 | -------------------------------------------------------------------------------- /images/static/tests/examples/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("Hello!\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /images/static/tests/examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("Hello!") 7 | } 8 | -------------------------------------------------------------------------------- /images/static/tests/main.tf: -------------------------------------------------------------------------------- 1 | variable "digest" { 2 | description = "The image digest to run tests over." 3 | } 4 | 5 | variable "target_repository" { 6 | description = "The repository to push transient test images to." 7 | } 8 | 9 | module "bash_sandbox" { 10 | source = "../../../tflib/imagetest/sandboxes/bash" 11 | target_repository = var.target_repository 12 | } 13 | 14 | module "test" { 15 | source = "../../../tflib/imagetest/tests/docker-in-docker" 16 | 17 | images = { static = var.digest } 18 | 19 | tests = [ 20 | { 21 | name = "multi dockerfile build test" 22 | image = module.bash_sandbox.image_ref 23 | content = [{ source = path.module }] 24 | cmd = "./test.sh" 25 | } 26 | ] 27 | } 28 | 29 | -------------------------------------------------------------------------------- /images/static/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | image=$(echo "$IMAGES" | jq -r '.static.ref') 6 | 7 | # Pre-pulling it uses docker's heuristics for allowing insecure registries. 8 | docker pull "${image}" 9 | 10 | for lang in c golang rust; do 11 | docker build --build-arg BASE="${image}" --tag smoke-test-${lang} --file examples/Dockerfile.${lang} examples 12 | docker run --rm smoke-test-${lang} 13 | done 14 | -------------------------------------------------------------------------------- /images/static/wolfi.tf: -------------------------------------------------------------------------------- 1 | module "wolfi" { 2 | source = "../../tflib/publisher" 3 | 4 | name = basename(path.module) 5 | 6 | target_repository = var.target_repository 7 | config = file("${path.module}/configs/wolfi.apko.yaml") 8 | check-sbom = false # TODO(jason): Temporarily disabled. 9 | } 10 | 11 | module "test-wolfi" { 12 | source = "./tests" 13 | digest = module.wolfi.image_ref 14 | target_repository = var.target_repository 15 | } 16 | -------------------------------------------------------------------------------- /images/stunnel/config/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | baseline_packages = ["stunnel"] 3 | } 4 | 5 | module "accts" { 6 | source = "../../../tflib/accts" 7 | } 8 | 9 | terraform { 10 | required_providers { 11 | apko = { source = "chainguard-dev/apko" } 12 | } 13 | } 14 | 15 | variable "extra_packages" { 16 | default = ["stunnel"] 17 | description = "The additional packages to install (e.g. stunnel)." 18 | } 19 | 20 | output "config" { 21 | value = jsonencode({ 22 | "contents" : { 23 | // TODO: remove the need for using hardcoded local.baseline_packages by plumbing 24 | // these packages through var.extra_packages in all callers of this config module 25 | "packages" : distinct(concat(local.baseline_packages, var.extra_packages)) 26 | }, 27 | "entrypoint" : { 28 | "command" : "/usr/bin/stunnel" 29 | }, 30 | "cmd" : "-help", 31 | "accounts" : module.accts.block 32 | }) 33 | } 34 | 35 | -------------------------------------------------------------------------------- /images/stunnel/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/stunnel/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | extra_dev_packages = ["curl"] 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | target_repository = var.target_repository 25 | } 26 | 27 | resource "oci_tag" "latest" { 28 | depends_on = [module.test-latest] 29 | digest_ref = module.latest.image_ref 30 | tag = "latest" 31 | } 32 | 33 | resource "oci_tag" "latest-dev" { 34 | depends_on = [module.test-latest] 35 | digest_ref = module.latest.dev_ref 36 | tag = "latest-dev" 37 | } 38 | -------------------------------------------------------------------------------- /images/stunnel/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: stunnel 2 | image: cgr.dev/chainguard/stunnel 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: This image contains the CLI for the [stunnel](https://www.stunnel.org/) networking tool 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.stunnel.org/ 9 | keywords: 10 | - application 11 | -------------------------------------------------------------------------------- /images/stunnel/tests/main.tf: -------------------------------------------------------------------------------- 1 | variable "digest" { 2 | description = "The image digest to run tests over." 3 | } 4 | 5 | variable "target_repository" { 6 | description = "The repository to push transient test images to." 7 | } 8 | 9 | module "bash_sandbox" { 10 | source = "../../../tflib/imagetest/sandboxes/bash" 11 | target_repository = var.target_repository 12 | } 13 | 14 | module "test" { 15 | source = "../../../tflib/imagetest/tests/docker-in-docker" 16 | 17 | images = { stunnel = var.digest } 18 | 19 | tests = [ 20 | { 21 | name = "stunnel help test" 22 | image = module.bash_sandbox.image_ref 23 | content = [{ source = path.module }] 24 | cmd = "./test.sh" 25 | } 26 | ] 27 | } 28 | 29 | -------------------------------------------------------------------------------- /images/stunnel/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | image=$(echo "$IMAGES" | jq -r '.stunnel.ref') 6 | 7 | docker run --rm "${image}" -help 8 | 9 | -------------------------------------------------------------------------------- /images/tomcat/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge(module.tagger.imagetags) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/tomcat/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: tomcat 2 | image: cgr.dev/chainguard/tomcat 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: "[Tomcat](https://tomcat.apache.org/) is a free and open-source implementation of the Jakarta Servlet, Jakarta Expression Language, and WebSocket technologies." 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/apache/tomcat 9 | keywords: 10 | - base 11 | aliases: 12 | - tomcat:latest 13 | -------------------------------------------------------------------------------- /images/valkey/configs/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | baseline_packages = ["busybox"] 3 | } 4 | 5 | module "accts" { 6 | name = "valkey" 7 | source = "../../../tflib/accts" 8 | } 9 | 10 | terraform { 11 | required_providers { 12 | apko = { source = "chainguard-dev/apko" } 13 | } 14 | } 15 | 16 | variable "extra_packages" { 17 | default = ["valkey", "valkey-cli"] 18 | description = "The additional packages to install" 19 | } 20 | 21 | output "config" { 22 | value = jsonencode({ 23 | "contents" : { 24 | // TODO: remove the need for using hardcoded local.baseline_packages by plumbing 25 | // these packages through var.extra_packages in all callers of this config module 26 | "packages" : distinct(concat(local.baseline_packages, var.extra_packages)) 27 | }, 28 | "entrypoint" : { 29 | "command" : "/usr/bin/valkey-server" 30 | }, 31 | "work-dir" : "/data", 32 | "accounts" : module.accts.block, 33 | "paths" : [ 34 | { 35 | "path" : "/data", 36 | "type" : "directory", 37 | "uid" : 65532, 38 | "gid" : 65532, 39 | "permissions" : 493 40 | } 41 | ] 42 | }) 43 | } 44 | 45 | -------------------------------------------------------------------------------- /images/valkey/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/valkey/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./configs" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | build-dev = true 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | resource "oci_tag" "latest" { 27 | depends_on = [module.test-latest] 28 | digest_ref = module.latest.image_ref 29 | tag = "latest" 30 | } 31 | 32 | resource "oci_tag" "latest-dev" { 33 | depends_on = [module.test-latest] 34 | digest_ref = module.latest.dev_ref 35 | tag = "latest-dev" 36 | } 37 | -------------------------------------------------------------------------------- /images/valkey/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: valkey 2 | image: cgr.dev/chainguard/valkey 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimalist Wolfi-based [Valkey](https://github.com/valkey-io/valkey) image. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/valkey-io/valkey 9 | keywords: 10 | - application 11 | tier: APPLICATION 12 | aliases: 13 | - valkey/valkey:latest 14 | -------------------------------------------------------------------------------- /images/valkey/tests/02-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | # to prevent duplicate container name issues when we run similar tests for both versions within the configs/ folder. 6 | CONTAINER_NAME=${CONTAINER_NAME:-"valkey-smoketest-$(date +%s)-${RANDOM}"} 7 | 8 | # Run two containers on the same network (just use host for simplicity) 9 | # The server should start up and listen, and the client will run ping 10 | 11 | docker run -d -p ${FREE_PORT}:6379 --name $CONTAINER_NAME $IMAGE_NAME 12 | 13 | trap "docker logs $CONTAINER_NAME && docker rm -f $CONTAINER_NAME && rm ${CONTAINER_NAME}_${FREE_PORT}.txt" EXIT 14 | 15 | sleep 15 16 | 17 | # Send commands to Valkey via nc 18 | ( echo "SET mykey myvalue"; echo "GET mykey"; echo "QUIT" ) | nc localhost ${FREE_PORT} > ${CONTAINER_NAME}_${FREE_PORT}.txt 19 | 20 | # Check if the command passed 21 | grep -q "myvalue" ${CONTAINER_NAME}_${FREE_PORT}.txt 22 | 23 | # Now use the valkey client to set a counter 24 | docker exec $CONTAINER_NAME valkey-cli SET key1 1 25 | 26 | # Increment the counter 27 | docker exec $CONTAINER_NAME valkey-cli INCR key1 28 | 29 | # Read and verify that it's now 2 30 | docker exec $CONTAINER_NAME valkey-cli get key1 | grep 2 31 | -------------------------------------------------------------------------------- /images/valkey/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "oci_exec_test" "version" { 12 | digest = var.digest 13 | script = "docker run --rm $IMAGE_NAME --version" 14 | } 15 | 16 | data "oci_exec_test" "server" { 17 | digest = var.digest 18 | script = "${path.module}/02-server.sh" 19 | } 20 | -------------------------------------------------------------------------------- /images/wait-for-it/config/main.tf: -------------------------------------------------------------------------------- 1 | module "accts" { 2 | source = "../../../tflib/accts" 3 | } 4 | 5 | terraform { 6 | required_providers { 7 | apko = { source = "chainguard-dev/apko" } 8 | } 9 | } 10 | 11 | variable "extra_packages" { 12 | default = ["wait-for-it"] 13 | description = "The additional packages to install (e.g. wait-for-it)." 14 | } 15 | 16 | output "config" { 17 | value = jsonencode({ 18 | "contents" : { 19 | "packages" : var.extra_packages 20 | }, 21 | "entrypoint" : { 22 | "command" : "/usr/bin/wait-for-it" 23 | }, 24 | "accounts" : module.accts.block 25 | }) 26 | } 27 | 28 | -------------------------------------------------------------------------------- /images/wait-for-it/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/wait-for-it/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "latest-config" { source = "./config" } 12 | 13 | module "latest" { 14 | source = "../../tflib/publisher" 15 | name = basename(path.module) 16 | target_repository = var.target_repository 17 | config = module.latest-config.config 18 | main_package = "wait-for-it" 19 | } 20 | 21 | module "test-latest" { 22 | source = "./tests" 23 | digest = module.latest.image_ref 24 | } 25 | 26 | resource "oci_tag" "latest" { 27 | depends_on = [module.test-latest] 28 | digest_ref = module.latest.image_ref 29 | tag = "latest" 30 | } 31 | -------------------------------------------------------------------------------- /images/wait-for-it/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: wait-for-it 2 | image: cgr.dev/chainguard/wait-for-it 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Container image for testing whether a service is listening on an address/port combination. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://github.com/vishnubob/wait-for-it 9 | keywords: 10 | - application 11 | aliases: 12 | - willwill/wait-for-it:latest 13 | -------------------------------------------------------------------------------- /images/wolfi-base/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "extra_packages" { 2 | description = "Additional packages to install." 3 | type = list(string) 4 | default = ["wolfi-base"] 5 | } 6 | 7 | module "accts" { 8 | source = "../../../tflib/accts" 9 | run-as = 0 10 | } 11 | 12 | output "config" { 13 | value = jsonencode({ 14 | contents = { 15 | packages = var.extra_packages 16 | } 17 | accounts = module.accts.block 18 | cmd = "/bin/sh -l" 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /images/wolfi-base/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/wolfi-base/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "target_repository" { 8 | description = "The docker repo into which the image and attestations should be published." 9 | } 10 | 11 | module "config" { 12 | source = "./config" 13 | } 14 | 15 | module "latest" { 16 | source = "../../tflib/publisher" 17 | 18 | name = basename(path.module) 19 | 20 | target_repository = var.target_repository 21 | config = module.config.config 22 | } 23 | 24 | module "test-latest" { 25 | source = "./tests" 26 | digest = module.latest.image_ref 27 | } 28 | 29 | resource "oci_tag" "latest" { 30 | digest_ref = module.latest.image_ref 31 | tag = "latest" 32 | depends_on = [module.test-latest] 33 | } 34 | -------------------------------------------------------------------------------- /images/wolfi-base/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: wolfi-base 2 | image: cgr.dev/chainguard/wolfi-base 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Base image for the [Wolfi Linux Distribution](https://wolfi.dev). 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://wolfi.dev 9 | keywords: [] 10 | tier: BASE 11 | -------------------------------------------------------------------------------- /images/wolfi-base/tests/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | oci = { source = "chainguard-dev/oci" } 4 | } 5 | } 6 | 7 | variable "digest" { 8 | description = "The image digest to run tests over." 9 | } 10 | 11 | data "oci_exec_test" "runs" { 12 | digest = var.digest 13 | script = "${path.module}/runs.sh" 14 | } 15 | -------------------------------------------------------------------------------- /images/wolfi-base/tests/runs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | # Running with and without a command doesn't error 6 | docker run --rm $IMAGE_NAME 7 | docker run --rm $IMAGE_NAME apk --version | grep "apk-tools .*" 8 | 9 | # The image runs as root by default. 10 | docker run --rm --entrypoint '' $IMAGE_NAME whoami | grep "^root$" 11 | 12 | # The image contains busybox. 13 | docker run --rm $IMAGE_NAME busybox | grep "^BusyBox .* multi-call binary." 14 | 15 | # The image can be used as a base image. 16 | cat < /usr/local/bin/hello && \ 29 | echo 'apk --version' >> /usr/local/bin/hello && \ 30 | chmod +x /usr/local/bin/hello 31 | ENTRYPOINT ["hello"] 32 | EOF 33 | docker run --rm version-entrypoint | grep "^apk-tools " 34 | -------------------------------------------------------------------------------- /images/wordpress/generated.tf: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT - this file is autogenerated by tfgen 2 | 3 | variable "test_repository" { 4 | description = "The docker repo root to use for sourcing test images." 5 | } 6 | 7 | output "summary" { 8 | value = { 9 | "tags" = merge({}) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /images/wordpress/metadata.yaml: -------------------------------------------------------------------------------- 1 | name: wordpress 2 | image: cgr.dev/chainguard/wordpress 3 | endoflife: "" 4 | console_summary: "" 5 | short_description: Minimalist Wolfi-based WordPress images. 6 | compatibility_notes: "" 7 | readme_file: README.md 8 | upstream_url: https://www.wordpress.org/ 9 | keywords: 10 | - application 11 | - base 12 | tier: APPLICATION 13 | aliases: 14 | - wordpress:latest 15 | public: true 16 | -------------------------------------------------------------------------------- /images/wordpress/tests/main.tf: -------------------------------------------------------------------------------- 1 | variable "digest" { 2 | description = "The image digest to run tests over." 3 | } 4 | 5 | variable "target_repository" { 6 | } 7 | 8 | module "bash_sandbox" { 9 | source = "../../../tflib/imagetest/sandboxes/bash" 10 | target_repository = var.target_repository 11 | } 12 | 13 | module "dind_test" { 14 | images = { wordpress = var.digest } 15 | source = "../../../tflib/imagetest/tests/docker-in-docker" 16 | tests = [ 17 | { 18 | name = "smoke" 19 | image = module.bash_sandbox.image_ref 20 | content = [{ source = path.module }] 21 | cmd = "./test.sh" 22 | } 23 | ] 24 | } 25 | 26 | -------------------------------------------------------------------------------- /images/wordpress/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit -o nounset -o errtrace -o pipefail -x 4 | 5 | image=$(echo "$IMAGES" | jq -r '.wordpress.ref') 6 | 7 | container_id=$(docker run --detach --rm "$image") 8 | 9 | max_attempts=15 10 | attempt=1 11 | delay=30 12 | 13 | while [ $attempt -le $max_attempts ]; do 14 | if docker logs "$container_id" 2>&1 | grep -q "ready to handle connections"; then 15 | echo "WordPress is ready!" 16 | break 17 | fi 18 | 19 | echo "Attempt $attempt failed. Retrying in $delay seconds..." 20 | sleep $delay 21 | attempt=$((attempt + 1)) 22 | 23 | if [ $attempt -gt $max_attempts ]; then 24 | echo "Failed after $max_attempts attempts" 25 | exit 1 26 | fi 27 | done 28 | -------------------------------------------------------------------------------- /policies/01-is-signed.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.sigstore.dev/v1beta1 2 | kind: ClusterImagePolicy 3 | metadata: 4 | name: is-signed 5 | spec: 6 | images: 7 | - glob: cgr.dev/chainguard/* 8 | authorities: 9 | - name: keyless-authority 10 | keyless: 11 | url: https://fulcio.sigstore.dev 12 | identities: 13 | - issuer: https://token.actions.githubusercontent.com 14 | subject: https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main 15 | ctlog: 16 | url: https://rekor.sigstore.dev 17 | -------------------------------------------------------------------------------- /policies/03-has-sbom-attestation.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.sigstore.dev/v1beta1 2 | kind: ClusterImagePolicy 3 | metadata: 4 | name: has-sbom-attestation 5 | spec: 6 | images: 7 | - glob: cgr.dev/chainguard/* 8 | authorities: 9 | - name: keyless-authority 10 | keyless: 11 | url: https://fulcio.sigstore.dev 12 | identities: 13 | - issuer: https://token.actions.githubusercontent.com 14 | subject: https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main 15 | ctlog: 16 | url: https://rekor.sigstore.dev 17 | attestations: 18 | - name: must-have-sbom-attestation 19 | predicateType: "https://spdx.dev/Document" 20 | policy: 21 | type: cue 22 | data: | 23 | predicateType: "https://spdx.dev/Document" 24 | -------------------------------------------------------------------------------- /policies/README.md: -------------------------------------------------------------------------------- 1 | This folder contains 2 | [`ClusterImagePolicy`](https://docs.sigstore.dev/policy-controller/overview/) 3 | resources which should apply to all Chainguard Images. 4 | 5 | You can run these policies over a list of image references with: 6 | 7 | ```shell 8 | export TF_VAR_image_refs='["foo", "bar", "baz"]' 9 | 10 | terraform init 11 | terraform apply 12 | ``` 13 | -------------------------------------------------------------------------------- /policies/main.tf: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 Chainguard, Inc. 3 | SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | terraform { 7 | required_providers { 8 | cosign = { 9 | source = "chainguard-dev/cosign" 10 | } 11 | } 12 | } 13 | 14 | variable "image_refs" { 15 | type = list(string) 16 | description = "The image references to verify against our policies." 17 | } 18 | 19 | data "cosign_verify" "is-signed" { 20 | for_each = toset(var.image_refs) 21 | image = each.key 22 | policy = file("${path.module}/01-is-signed.yaml") 23 | } 24 | 25 | data "cosign_verify" "has-sbom-att" { 26 | for_each = toset(var.image_refs) 27 | image = each.key 28 | policy = file("${path.module}/03-has-sbom-attestation.yaml") 29 | } 30 | 31 | data "cosign_verify" "has-slsa-att" { 32 | for_each = toset(var.image_refs) 33 | image = each.key 34 | policy = file("${path.module}/04-has-slsa-attestation.yaml") 35 | } 36 | -------------------------------------------------------------------------------- /reinstated-images.txt: -------------------------------------------------------------------------------- 1 | # Each line should be in the form $repo:$tag@$digest 2 | # Note: If tag already exists, it will NOT be retagged and must be first deleted by adding to withdrawn-images.txt 3 | # Example - add "test1" tag to curl repo pointing to sha257:8bf944...: 4 | # cgr.dev/chainguard/curl:test1@sha256:8bf944b98bdef5ab6b4ef4bd6992d6a5ad5c008b51c119a78ffc385273a36eec 5 | # 6 | -------------------------------------------------------------------------------- /tflib/accts/main.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | description = "The user / group name to create." 3 | default = "nonroot" 4 | } 5 | 6 | variable "uid" { 7 | description = "The UID to give the name." 8 | default = 65532 9 | } 10 | 11 | variable "gid" { 12 | description = "The GID to give the name." 13 | default = 65532 14 | } 15 | 16 | variable "run-as" { 17 | description = "The UID to run as." 18 | default = 65532 19 | } 20 | 21 | output "block" { 22 | value = { 23 | groups = [{ 24 | groupname = var.name 25 | gid = var.gid 26 | }] 27 | users = [{ 28 | username = var.name 29 | uid = var.uid 30 | gid = var.gid 31 | }] 32 | run-as = var.run-as 33 | } 34 | } 35 | 36 | output "name" { 37 | value = var.name 38 | } 39 | 40 | output "uid" { 41 | value = var.uid 42 | } 43 | 44 | output "gid" { 45 | value = var.gid 46 | } 47 | 48 | output "run-as" { 49 | value = var.run-as 50 | } 51 | -------------------------------------------------------------------------------- /tflib/helm-cleanup/main.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | type = string 3 | description = "Name of the helm release to cleanup" 4 | 5 | } 6 | variable "namespace" { 7 | default = "default" 8 | type = string 9 | description = "Namespace of the helm release to cleanup" 10 | } 11 | 12 | resource "null_resource" "cleanup" { 13 | provisioner "local-exec" { 14 | command = <|Runs| B[Docker Container] 19 | A -->|Uses| C[NVIDIA Tesla T4 GPU] 20 | A -->|SSH Access| D[Ephemeral Local Key] 21 | E[imagetest_client] -->|Connects via SSH| B 22 | E -->|Uses| D 23 | ``` 24 | -------------------------------------------------------------------------------- /tflib/imagetest/harnesses/pterraform/gpu/tests/integration.tftest.hcl: -------------------------------------------------------------------------------- 1 | variables { 2 | project = "img-test-infra-f2ea" 3 | region = "us-central1" 4 | zone = "us-central1-a" 5 | } 6 | 7 | run "execute" { 8 | # Empty means just run the module with defaults 9 | 10 | assert { 11 | condition = output.connection.docker.host != "" 12 | error_message = "Expected connection.docker.host to be set" 13 | } 14 | 15 | assert { 16 | condition = startswith(output.connection.docker.host, "ssh://") 17 | error_message = "Expected connection.docker.host to start with ssh://" 18 | } 19 | } 20 | 21 | run "verify" { 22 | module { 23 | source = "./tests/verify" 24 | } 25 | 26 | variables { 27 | instance_name = run.execute.instance_name 28 | container_id = run.execute.connection.docker.cid 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tflib/imagetest/harnesses/pterraform/gpu/tests/verify/main.tf: -------------------------------------------------------------------------------- 1 | variable "project" {} 2 | 3 | variable "region" {} 4 | 5 | variable "zone" {} 6 | 7 | variable "instance_name" { type = string } 8 | 9 | variable "container_id" { type = string } 10 | 11 | resource "terraform_data" "check-gpu" { 12 | provisioner "local-exec" { 13 | command = <