{"id":27064653,"url":"https://github.com/wesley-dean/publish_container","last_synced_at":"2025-04-05T17:18:21.242Z","repository":{"id":282913759,"uuid":"949041577","full_name":"wesley-dean/publish_container","owner":"wesley-dean","description":"This project is a GitHub Action that builds Docker-compatible images on various platforms, adds OCI metadata tags to the images, attests to the images, and then publishes the images to various registries.","archived":false,"fork":false,"pushed_at":"2025-04-04T18:48:28.000Z","size":87,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T23:08:18.954Z","etag":null,"topics":["actions","docker","docker-image","dockerhub","dockerhub-image","ecr","ghcr","ghcr-image","harbor","harbor-image","quay","quay-image","quayio","workflow-reusable"],"latest_commit_sha":null,"homepage":"https://GitHub.com/wesley-dean/publish_container","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wesley-dean.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-15T14:43:49.000Z","updated_at":"2025-03-31T19:11:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"442abb10-6052-46f2-b60f-38bd1f439a1a","html_url":"https://github.com/wesley-dean/publish_container","commit_stats":null,"previous_names":["wesley-dean/publish_container"],"tags_count":11,"template":false,"template_full_name":"wesley-dean/template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fpublish_container","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fpublish_container/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fpublish_container/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesley-dean%2Fpublish_container/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wesley-dean","download_url":"https://codeload.github.com/wesley-dean/publish_container/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247369953,"owners_count":20927928,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actions","docker","docker-image","dockerhub","dockerhub-image","ecr","ghcr","ghcr-image","harbor","harbor-image","quay","quay-image","quayio","workflow-reusable"],"created_at":"2025-04-05T17:18:20.848Z","updated_at":"2025-04-05T17:18:21.236Z","avatar_url":"https://github.com/wesley-dean.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Publish Image to Various Registries\n\n[![Dependabot Updates](https://github.com/wesley-dean/publish_container/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/wesley-dean/publish_container/actions/workflows/dependabot/dependabot-updates)\n[![MegaLinter](https://github.com/wesley-dean/publish_container/actions/workflows/megalinter.yml/badge.svg)](https://github.com/wesley-dean/publish_container/actions/workflows/megalinter.yml)\n[![Scorecard supply-chain security](https://github.com/wesley-dean/publish_container/actions/workflows/scorecard.yml/badge.svg)](https://github.com/wesley-dean/publish_container/actions/workflows/scorecard.yml)\n\n## Description\n\nThis project is a GitHub Action that builds a Docker-compatible image on\nvarious platforms, tags the image, and then publishes a Docker image to various\nregistries. The action can be triggered by a push to a branch, a pull request,\na release, a schedule, or a manual trigger.\n\nThe images are tagged with SBOM attestations and OCI metadata.\n\nThe goal is to make it easy to build and publish images to various registries\nwithout a lot of configuration.  When the project started, it was just to\nbuild for DockerHub with an image name based on the user's DockerHub username\nand the name of the repository.  The project then grew to support the GitHub\nContainer Registry (GHCR).  Labels and tags were added, followed by multiple\nplatforms (e.g., AMD64 and various ARM platforms that Single-Board Computers\n(SBCs) like Raspberry Pis and such).\n\nThe project then grew to support more registries, including Quay, Harbor, ECR,\nand custom registries.\n\nThe first use case was to build and publish images that could be used to run\ncontainers that would run on a laptop, shortly followed by images that could\nrun on a Raspberry Pi.\n\n### Features\n\n#### Image Labels\n\nThe action will add OCI metadata to the image, including the following:\n\n- title\n- description\n- url\n- source\n- version\n- created\n- revision\n- license\n\n#### Image Descriptions\n\nThe action will also update the description of the image on DockerHub, Quay,\nand Harbor using the README.md file in the repository.\n\n#### Image Attestations\n\nThe action will also generate Software Bill of Materials (SBOM) files in\nSPDX format and use them to generate attestations for each image that\nis built.\n\n#### Composite Action Components\n\nThe action is a composite action that uses several other actions to build and\npublish images. The action uses the following actions:\n\n- [docker/build-push-action](https://github.com/docker/build-push-action)\n- [docker/login-action](https://github.com/docker/login-action)\n- [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action)\n- [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action)\n- [docker/metadata-action](https://github.com/docker/metadata-action)\n- [docker/build-push-action](https://github.com/docker/build-push-action)\n- [anchore/sbom-action](https://github.com/anchore/sbom-action)\n- [actions/attest-sbom](https://github.com/actions/attest-sbom)\n- [christian-korneck/update-container-description-action](https://github.com/christian-korneck/update-container-description-action)\n\n#### Image Platforms\n\nBy default, the action builds images for the following platforms:\n\n- linux/amd64\n- linux/arm64\n- linux/arm/v6\n- linux/arm/v7\n\nThe action can be configured to build images for other platforms by setting the\n`platforms` input.  The input should be a comma-separated list of platforms.\n\nThe `arm` images are built using QEMU emulation so that they can run on\nARM-based devices such as the Raspberry Pi.\n\n#### Supported Registries\n\nThe action can be configured to publish images to the following registries:\n\n- DockerHub (docker.io)\n- GitHub Container Registry (ghcr.io)\n- Quay (quay.io)\n- Harbor (goharbor.io)\n- Amazon Elastic Container Registry (ECR)\n- custom registry\n\nThe action can be configured to publish images to other registries by setting\n`_username` and `_token` inputs for the respective registries:\n\n- **DockerHub**: `dockerhub_username` and `dockerhub_token`\n- **GitHub Container Registry**: `ghcr_username` and `ghcr_token`\n- **Quay**: `quay_username` and `quay_token`\n- **Harbor**: `harbor_username` and `harbor_token`\n- **Amazon Elastic Container Registry (ECR)**: `ecr_access_key_id` and `ecr_secret_access_key`\n- **Custom Registry**: `custom_registry_username` and `custom_registry_token`\n\n#### Image Tags\n\nThe action adds various tags to the image, including the following:\n\n- every build\n  - `edge`\n  - `{short sha}`: (short SHA hash of the commit)\n  - `{long sha}` (long SHA hash of the commit)\n- when the action is triggered by a push to a branch\n  - `latest`\n  - `{major}.{minor}.{patch}`\n  - `{major}.{minor}`\n  - `{major}`\n\n## Usage\n\nTo use the action, add the following to your GitHub Actions workflow:\n\n```yaml\n  - name: Publish Image to Various Registries\n    uses: wesdean/publish-image-to-various-registries@v1\n    with:\n      platforms: 'linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7'\n      dockerfile: 'Dockerfile'\n      context: '.'\n      github_ref: ${{ github.ref }}\n      repository_name: ${{ github.repository }}\n\n      # to push to DockerHub, use:\n      dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}\n      dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      # to push to GitHub Container Registry (GHCR), use:\n      ghcr_username: ${{ secrets.GHCR_USERNAME }}\n\n      # to push to Quay, use:\n      quay_username: ${{ secrets.QUAY_USERNAME }}\n      quay_token: ${{ secrets.QUAY_TOKEN }}\n\n      # to push to Harbor, use:\n      harbor_username: ${{ secrets.HARBOR_USERNAME }}\n      harbor_token: ${{ secrets.HARBOR_TOKEN }}\n\n      # to push to Amazon Elastic Container Registry (ECR), use:\n      ecr_access_key_id: ${{ secrets.ECR_ACCESS_KEY_ID }}\n      ecr_secret_access_key: ${{ secrets.ECR_SECRET_ACCESS_KEY }}\n      ecr_region: 'us-east-1'\n\n      # to push to a custom registry, use:\n      custom_registry_username: ${{ secrets.CUSTOM_REGISTRY_USERNAME }}\n      custom_registry_token: ${{ secrets.CUSTOM_REGISTRY_TOKEN }}\n      custom_registry: 'registry.example.com'\n```\n\nAll of the registry-specific inputs are optional.  That said, if none of the\nregistry inputs are set, the action will build the image and tag it, but it\nwill not publish the image.  It'll just eat your billing minutes.  I\nrecommend against that.\n\n### Inputs\n\nThe following inputs are available:\n\n- **basic**\n  - context: The build context for the Docker build. Default: `.`.\n  - dockerfile: The path to the Dockerfile. Default: `Dockerfile`.\n  - platforms: The platforms to build images for. Default: `linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7`.\n  - repository_name: The name of the repository.  Consider using\n    `${{ github.repository }}` to get the repository name.  **REQUIRED**\n  - github_ref: The GitHub ref that triggered the action.  Consider using\n    `${{ github.ref }}` to get the ref that triggered the action. **REQUIRED**\n  - force_release: If `true`, the action will treat any build as a release and\n    tag the image with the appropriate tags.  Default: `false`.\n- **DockerHub**\n  - dockerhub_image: The name of the image on DockerHub. Default:\n    `{ dockerhub username }/{ repository name }`.\n  - dockerhub_username: The username for DockerHub.  Required to use DockerHub.\n  - dockerhub_token: The token for DockerHub.  Required to use DockerHub.\n  - dockerhub_registry: The URL for DockerHub. Default: `docker.io`.\n- **GitHub Container Registry (GHCR)**\n  - ghcr_image: The name of the image on GHCR. Default:\n    `{ ghcr username }/{ repository name }`.\n  - ghcr_username: The username for GHCR.  Required to use GHCR.\n  - ghcr_token: The token for GHCR.  Required to use GHCR.\n  - ghcr_registry: The URL for GHCR. Default: `ghcr.io`.\n- **Quay**\n  - quay_image: The name of the image on Quay. Default:\n    `{ quay username }/{ repository name }`.\n  - quay_username: The username for Quay.  Required to use Quay.\n  - quay_token: The token for Quay.  Required to use Quay.\n  - quay_registry: The URL for Quay. Default: `quay.io`.\n- **Harbor**\n  - harbor_image: The name of the image on Harbor. Default:\n    `{ harbor username }/{ repository name }`.\n  - harbor_username: The username for Harbor.  Required to use Harbor.\n  - harbor_token: The token for Harbor.  Required to use Harbor.\n  - harbor_registry: The registry for Harbor. Default: `goharbor.io`.\n- **Amazon Elastic Container Registry (ECR)**:\n  - ecr_image: The name of the image on ECR. Default: `{ repository name }`.\n  - ecr_access_key_id: The access key ID for ECR.  Required to use ECR.\n  - ecr_secret_access_key: The secret access key for ECR.  Required to use ECR.\n  - ecr_region: The region for ECR.  Default: `us-east-1`.\n  - ecr_registry: The URL to use with ECR.  Default:\n    `{ ecr account id }.dkr.ecr.{ region }.amazonaws.com`.\n- **Custom Registry**\n  - custom_registry_image: The name of the image on the custom registry.\n    Default: `{ repository name }`.\n  - custom_registry_username: The username for the custom registry.\n    Required to use a custom registry.\n  - custom_registry_token: The token for the custom registry.  Required to use\n    a custom registry.\n  - custom_registry: The URL to the custom registry.\n\n### Outputs\n\nThe following outputs are available:\n- **DockerHub**\n  - dockerhub: `true` if the image was published to DockerHub, `false` otherwise.\n  - dockerhub_image: The name of the image on DockerHub.\n- **GitHub Container Registry (GHCR)**\n  - ghcr: `true` if the image was published to GHCR, `false` otherwise.\n  - ghcr_image: The name of the image on GHCR.\n- **Quay**\n  - quay: `true` if the image was published to Quay, `false` otherwise.\n  - quay_image: The name of the image on Quay.\n- **Harbor**\n  - harbor: `true` if the image was published to Harbor, `false` otherwise.\n  - harbor_image: The name of the image on Harbor.\n- **Amazon Elastic Container Registry (ECR)**\n  - ecr: `true` if the image was published to ECR, `false` otherwise.\n  - ecr_image: The name of the image on ECR.\n  - ecr_image_url: The URL of the image on ECR.\n- **Custom Registry**\n  - custom_registry: `true` if the image was published to a custom registry,\n    `false` otherwise.\n  - custom_image: The name of the image on the custom registry.\n\n## Examples\n\n### Build and Publish Image to DockerHub\n\nThis is a minimal example that builds an image and publishes it to DockerHub.\n\nThe action is triggered by a push to the `main` branch or a tag that starts with\n`v` and a version number with a major release level greater than 0 (i.e., it\nwould run for `v1.0.0`, but not for `v0.1.0`).  The action can also be triggered\nmanually.\n\n```yaml\n---\nname: Build an Awesome Image\n\n# yamllint disable-line rule:truthy\non:\n  push:\n    branches:\n      - \"main\"\n    tags:\n      - \"v[1-9][0-9]*.*\"\n  workflow_dispatch:\n\npermissions: read-all\n\njobs:\n  publish_image:\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4.2.2\n        with:\n          depth: 0\n          tags: true\n      - name: Build and Publish Image\n        uses: wesley-dean/publish_container@v1\n        with:\n          # pass the basic data for the build\n          github_ref: ${{ github.ref }}\n          repository_name: ${{ github.repository }}\n\n          # just push to DockerHub and nowhere else\n          dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}\n          dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}\n```\n\n### Build and Publish Image to DockerHub and GHCR\n\nThis example pushes to both DockerHub and GHCR.  The image is given different\nnames on each registry.\n\n```yaml\n---\nname: Build an Awesome Image\n\n# yamllint disable-line rule:truthy\non:\n  push:\n    branches:\n      - \"main\"\n    tags:\n      - \"v[1-9][0-9]*.*\"\n  workflow_dispatch:\n\npermissions: read-all\n\njobs:\n  publish_image:\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4.2.2\n        with:\n          depth: 0\n          tags: true\n      - name: Build and Publish Image\n        uses: wesley-dean/publish_container@v1\n        with:\n\n          # basic inputs\n          github_ref: ${{ github.ref }}\n          repository_name: ${{ github.repository }}\n\n          # DockerHub inputs\n          dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}\n          dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}\n          dockerhub_image: \"myname/awesomeimage\"\n\n          # GHCR inputs\n          ghcr_username: ${{ secrets.GHCR_USERNAME }}\n          ghcr_token: ${{ secrets.GHCR_TOKEN }}\n          ghcr_image: \"my-name/awesome-image\"\n```\n\n## Questions\n\n### Why do we need to provide the repo name?\n\nBecause the action is a composite action, it doesn't have access to the\n`github.repository` context.  The action needs the repository name to build the\nimage name for the various registries.\n\n### Why do we need to provide the ref?\n\nThe action needs the ref to determine the version of the image.  The ref is\nused to determine the version of the image.  The ref is also used to determine\nthe tags for the image.  Like with the repository name, the action doesn't have\naccess to the `github.ref` data.\n\n### What is the context variable?\n\nThe context variable is the path to the build context for the Docker build.\nThe default is the root of the repository (`.`).\n\n### Why do we need to provide the Dockerfile?\n\nThe action needs to know the path to the Dockerfile to build the image.  The\ndefault is `Dockerfile` in the root of the build context (so, `./Dockerfile`).\n\n### Can we build images for other platforms?\n\nYes, the action can build images for other platforms.  The `platforms` input\nis a comma-separated list of platforms.  The default is\n`linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7`.\n\n### Can we publish images to multiple registries?\n\nYes, images can be pushed to multiple registries.  The action can be configured\nto push images to DockerHub, GHCR, Quay, Harbor, ECR, and custom registries.\n\n### Can images on different registries have different names?\n\nYes, images on different registries can have different names.  The action\nsupports setting the image name for each registry.  For example, the image\nname on DockerHub can be `myname/awesomeimage`, while the image name on GHCR\ncan be `my-name/awesome-image`.  This can be done by setting the\n`dockerhub_image` and `ghcr_image` inputs, respectively.\n\n### How are versions handled?\n\nThe action uses the `github_ref` to determine the version of the image.  If the\nref starts with `refs/tags/v[1-9]` (e.g., `v1.0.0`), the action considers this\nrun to be a \"release\" and sets the version to the tag.\n\n#### What about version 0.x.x?\n\nGood eye.  The action won't consider a tag that starts with `v0` to be a\nrelease.  It will still build and push the image, but it'll only tag the image\nwith the `edge` tag plus the short and long hashes.\n\nIf, however, the `force_release` input is set to `true`, the action will treat\nany build -- v0.x.x or otherwise -- as a release and tag the image with the\nappropriate tags.\n\n### What secrets, credentials, tokens, etc. are stored after runs?\n\nNothing.  Nothing is stored.  The action uses the credentials to authenticate\nto DockerHub, GHCR, etc. and when updating image descriptions on DockerHub,\nQuay, and Harbor.  The credentials aren't used for anything else.  When they're\npassed to the action as secrets, they're stored in the GitHub Actions\nenvironment and are not persisted, even in the logs.  It is recommended that\ncredentials be stored in GitHub Secrets, not as plain text or repository\nenvironment variables.\n\nWant to be sure?  Check the code.  It's all there.  Here's a link:\n\n[https://github.com/wesley-dean/publish_container/blob/main/action.yml](https://github.com/wesley-dean/publish_container/blob/main/action.yml)\n\n#### Release tags\n\nImages associated with releases are given the following tags:\n\n- latest\n- edge\n- `{major}.{minor}.{patch}`\n- `{major}.{minor}`\n- `{major}`\n- `{short sha}`\n- `{long sha}`\n\nSo, if the tag is `v1.2.3`, the image will be tagged with the following:\n\n- latest\n- edge\n- v1.2.3\n- v1.2\n- v1\n- abc123\n- abc123def456aaa7890123456789abcdef012345\n\n(the SHA hashes are made up)\n\n#### Non-release tags\n\nImages that are not associated with a release are given the following tags:\n\n- edge\n- `{short sha}`\n- `{long sha}`\n\n### Image descriptions\n\nFor images on DockerHub, Quay, and Harbor, the action updates the description\nof the image using the README.md file in the repository.\n\n### What if I need to override the image's labels?  Customize build parameters?\n\nYeah, no, this action just handles the most basic stuff.  If you need to\ncustomize the build, you'll need to use the underlying actions directly.  If\nyou want to provide a PR to include those variables, I'm open to it.\n\n## License\n\nThis project is licensed under the Creative Commons License 1.0 Universal\nLicense - see the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nContributions are welcome. Please read the [CONTRIBUTING.md](CONTRIBUTING.md)\nfile for details.\n\n### Code of Conduct\n\nPlease read the [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) file for details on\nthe code of conduct.  Long story short, be nice to each other and treat each\nother with respect, compassion, and empathy, especially when you disagree.\n\n## Authors\n\n- Wes Dean\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwesley-dean%2Fpublish_container","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwesley-dean%2Fpublish_container","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwesley-dean%2Fpublish_container/lists"}