{"id":19586363,"url":"https://github.com/tbobm/gha-dynamic-containers","last_synced_at":"2026-02-26T03:06:16.687Z","repository":{"id":42014049,"uuid":"470547012","full_name":"tbobm/gha-dynamic-containers","owner":"tbobm","description":"Dynamically build containers in a monolithic Github repository and upload them to ghcr.","archived":false,"fork":false,"pushed_at":"2022-04-18T13:23:11.000Z","size":24,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-14T06:45:54.184Z","etag":null,"topics":["actions","ci-cd","cicd","containers","docker","github-actions","microservices","monolithic"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tbobm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-16T11:07:50.000Z","updated_at":"2022-10-25T16:02:09.000Z","dependencies_parsed_at":"2022-08-12T02:20:53.163Z","dependency_job_id":null,"html_url":"https://github.com/tbobm/gha-dynamic-containers","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbobm%2Fgha-dynamic-containers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbobm%2Fgha-dynamic-containers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbobm%2Fgha-dynamic-containers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbobm%2Fgha-dynamic-containers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tbobm","download_url":"https://codeload.github.com/tbobm/gha-dynamic-containers/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247812949,"owners_count":21000403,"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","ci-cd","cicd","containers","docker","github-actions","microservices","monolithic"],"created_at":"2024-11-11T07:59:31.812Z","updated_at":"2025-10-31T09:43:06.110Z","avatar_url":"https://github.com/tbobm.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Github Actions dynamic containers\n\n[![Build Containers](https://github.com/tbobm/gha-dynamic-containers/actions/workflows/main.yaml/badge.svg)](https://github.com/tbobm/gha-dynamic-containers/actions/workflows/main.yaml)  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nDynamically build containers in a monolithic Github repository and upload them\nto [ghcr][ghcr].\n\n[ghcr]: https://github.com/features/packages\n\n## What does this repository do ?\n\nSometimes, repositories are used to centralize multiple service, either\napplications such as microservices or more simply, different application\ncomponents.\n\nThis repository template allows to dynamically build and publish the\ncorresponding Container Images (or \"Docker Image\") to Github's Container\nRegistry.\n\nEverything it configured in a single Github Actions Workflow located in the\n[`./.github/workflows/main.yaml`](./.github/workflows/main.yaml) file.\n\nThis is achieved using the following pattern:\n1. The `matrix` job (`Generate the matrix`) finds every directory containing\na Dockerfile. It then creates a list of `target` by using the\n[`generate_matrix.sh`](./generate_matrix.sh) script and outputs a JSON string\nthat defines the [matrix strategy][gh-matrix] that will be used downstream.\n2. The `check-matrix` (`Validate and display matrix`) job ensure that the\noutput is using the proper JSON format that can be injected in the Github\nActions Workflow\n3. The main course. The `build-containers` job uses the matrix definition\ncreated in the `matrix` job to start N (where N is the number of targets)\nparallel jobs that will build each service and upload it to the ghcr repository\nmatching the current Github Repository. Each image tag is prefixed by a slug\nof the used path to automatically apply a naming convention. The current\nGithub Reference slug is used as the suffix (i.e.: branch, tag)\n\n[gh-matrix]: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix\n\n### Matrix definition\n\n_Note: this can be adapted by modifying the `generate_matrix.sh` script in the\ntop-level directory of the repository._\n\nEach directory containing a `Dockerfile` is used as a `target`.\n\nConsidering that we have 2 targets structured as the following:\n```console\n$ tree demo/\ndemo/\n├── app1\n│   └── Dockerfile\n└── app2\n    └── Dockerfile\n```\n\nWe will end up with a matrix with a structure matching the one below:\n```yaml\ntarget:\n  - src: ./demo/app2\n    name: ./demo/app2/Dockerfile\n  - src: ./demo/app1\n    name: ./demo/app1/Dockerfile\n```\n\nIt is then exposed as an output in a single-line JSON using [`yq`][yq].\n\nPretty printed JSON:\n```json\n{\n  \"target\": [\n    {\n      \"src\": \"./demo/app2\",\n      \"name\": \"./demo/app2/Dockerfile\"\n    },\n    {\n      \"src\": \"./demo/app1\",\n      \"name\": \"./demo/app1/Dockerfile\"\n    }\n  ]\n}\n```\n\nSingle-line JSON:\n```json\n{\"target\":[{\"src\":\"./demo/app2\",\"name\":\"./demo/app2/Dockerfile\"},{\"src\":\"./demo/app1\",\"name\":\"./demo/app1/Dockerfile\"}]}\n```\n\n[yq]: https://mikefarah.gitbook.io/yq/\n\n### Example\n\nThis repository includes a `./demo` directory that acts as a dummy\nimplementation of this Workflow.\n\nOnce rendered, the Github Actions Workflow \"Build Containers\" creates the\nfollowing container images when running against the `main` branch:\n- `ghcr.io/tbobm/gha-dynamic-containers:demo-app1-main`\n- `ghcr.io/tbobm/gha-dynamic-containers:demo-app2-main`\n\n## Matrix injection\n\nGithub Actions Workflow can be dynamically adapted using the `fromJson`\nfunction that will inject the string directly in the Workflow.\n\nThis is configured in the `build-containers` attribute, as shown below:\n```yaml\n  build-containers:\n    runs-on: \"ubuntu-latest\"\n    name: \"Build and push OCIs\"\n    needs:\n      - matrix\n    strategy:\n      matrix: ${{fromJson(needs.matrix.outputs.matrix)}}\n```\n\nUsing the `demo` example, we will end up with 2 `build-containers` jobs:\n- `./demo/app1`\n- `./demo/app2`\n\nBoth of them resulting in a different images based on the OCI tag.\n\nOnce rendered using the dynamic matrix, the Workflow looks like the following:\n```yaml\n  build-containers:\n    runs-on: \"ubuntu-latest\"\n    name: \"Build and push OCIs\"\n    needs:\n      - matrix\n    strategy:\n      matrix:\n        target:\n          - src: ./demo/app2\n            name: ./demo/app2/Dockerfile\n          - src: ./demo/app1\n            name: ./demo/app1/Dockerfile\n```\n\n## How to use this repository template ?\n\nSimply create your new repository using the `Use this template` button\navailable in this repository.\n\nEverything is pretty much bootstrapped to work out of the box thanks to\nthe [github-slug-action][gh-slug-action] that injects the current repository\nname as the registry entry in [ghcr][ghcr].\n\n[gh-slug-action]: https://github.com/marketplace/actions/github-slug-action#overview\n\nFor more information see [Creating a Repository from a Template][gh-template]\nin the Github documentation.\n\n[gh-template]: https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template#creating-a-repository-from-a-template\n\nOnce done, you can create your own directory structure that will be easy\nto use in your existing workflow.\n\n## Sources\n\n- [Dynamic build matrix in GitHub Actions](https://www.cynkra.com/blog/2020-12-23-dynamic-gha/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftbobm%2Fgha-dynamic-containers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftbobm%2Fgha-dynamic-containers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftbobm%2Fgha-dynamic-containers/lists"}