From a4157f71ebee7c067b9b8066dd44d878e7e8fa44 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Wed, 20 Mar 2024 15:58:43 -0400 Subject: [PATCH 01/19] Add Hadolint validation --- .github/workflows/dev-build.yml | 16 ++++++++++++++++ .github/workflows/prod-build.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index a0c114e..ba1ad71 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -43,6 +43,22 @@ jobs: with: filters: ".github/tags.yml" token: "" + dockerfile-lint: + runs-on: ubuntu-latest + name: dockerfile-lint + needs: [dockerfile-changes] + if: needs.dockerfile-changes.outputs.docker-images != '[]' + strategy: + fail-fast: false + matrix: + tags: ["${{ fromJson(needs.dockerfile-changes.outputs.docker-images) }}"] + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Hadolint + uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: containers/${{ matrix.tags }}/Dockerfile dockerfile-build: runs-on: ubuntu-latest name: dockerfile-build diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index 7635da0..e61d0b5 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -41,6 +41,22 @@ jobs: with: filters: ".github/tags.yml" token: "" + dockerfile-lint: + runs-on: ubuntu-latest + name: dockerfile-lint + needs: [dockerfile-changes] + if: needs.dockerfile-changes.outputs.docker-images != '[]' + strategy: + fail-fast: false + matrix: + tags: ["${{ fromJson(needs.dockerfile-changes.outputs.docker-images) }}"] + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Hadolint + uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: containers/${{ matrix.tags }}/Dockerfile dockerfile-build: runs-on: ubuntu-latest name: dockerfile-build From cbe4bfd1628a87b0f769a47dda76af9946089498 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Wed, 20 Mar 2024 16:00:44 -0400 Subject: [PATCH 02/19] Add meaningless change to testapp:0.0.1 --- containers/testapp/0.0.1/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/containers/testapp/0.0.1/Dockerfile b/containers/testapp/0.0.1/Dockerfile index 8a8cb74..356b5f1 100644 --- a/containers/testapp/0.0.1/Dockerfile +++ b/containers/testapp/0.0.1/Dockerfile @@ -14,4 +14,4 @@ COPY . /app ENV NAME World # Run app.py when the container launches -CMD ["python", "app.py"] +CMD ["python", "app.py"] \ No newline at end of file From 3b4b18be9d5a8f5d49d1d3a185e713429625c480 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Wed, 20 Mar 2024 16:04:06 -0400 Subject: [PATCH 03/19] change verbosity to true for hadolint in dev-build --- .github/workflows/dev-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index ba1ad71..0d4d204 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -59,6 +59,7 @@ jobs: uses: hadolint/hadolint-action@v3.1.0 with: dockerfile: containers/${{ matrix.tags }}/Dockerfile + verbose: true dockerfile-build: runs-on: ubuntu-latest name: dockerfile-build From 0a543bc19a53183a4c1d0a915e1387b7fd1108a0 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Wed, 20 Mar 2024 16:12:25 -0400 Subject: [PATCH 04/19] Add container that will fail --- containers/lintfail/latest/Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 containers/lintfail/latest/Dockerfile diff --git a/containers/lintfail/latest/Dockerfile b/containers/lintfail/latest/Dockerfile new file mode 100644 index 0000000..0796866 --- /dev/null +++ b/containers/lintfail/latest/Dockerfile @@ -0,0 +1,6 @@ +FROM ubuntu:latest +RUN apt-get update +RUN apt-get install -y curl +RUN apt-get update && apt-get install -y curl +RUN echo "hello world" | grep "world" | wc -l +CMD ["echo", "Hello, world!"] From 1c10dcdd7d91a1ac90fab8bfa5792d6fefe6fa3c Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Fri, 22 Mar 2024 13:19:55 -0400 Subject: [PATCH 05/19] update github actions with image validation steps, and moved Hadolint task to a different job --- .github/jsonschema/docker_image.json | 89 ++++++++++++++++++++++++++++ .github/validate_docker.py | 28 +++++++++ .github/workflows/dev-build.yml | 41 +++++++------ .github/workflows/prod-build.yml | 42 ++++++------- 4 files changed, 158 insertions(+), 42 deletions(-) create mode 100644 .github/jsonschema/docker_image.json create mode 100644 .github/validate_docker.py diff --git a/.github/jsonschema/docker_image.json b/.github/jsonschema/docker_image.json new file mode 100644 index 0000000..a274fed --- /dev/null +++ b/.github/jsonschema/docker_image.json @@ -0,0 +1,89 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "Docker", + "description": "Validate output of docker inspect ", + "type": "object", + "properties": { + "Architecture": { + "type": "string", + "pattern": "amd64" + }, + "Os": { + "type": "string", + "pattern": "linux" + }, + "Config": { + "type":"object", + "properties": { + "Labels": { + "oneOf":[{ + "type":"object", + "oneOf": [ + { + "type":"object", + "properties": { + "org.opencontainers.image.created": { + "type": "string", + "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(?:T([01][0-9]|2[0-3])(:[0-5][0-9])(:[0-5][0-9])(?:\\.[0-9]+)?Z?)?$" + }, + "org.opencontainers.image.authors": {"type": "string"}, + "org.opencontainers.image.url": { + "type": "string", + "pattern":"^(?:http://|https://|www\\.).*" + }, + "org.opencontainers.image.documentation": {"type": "string"}, + "org.opencontainers.image.source": {"type": "string"}, + "org.opencontainers.image.version": {"type": "string"}, + "org.opencontainers.image.revision": {"type": "string"}, + "org.opencontainers.image.vendor": {"type": "string"}, + "org.opencontainers.image.licenses": {"type": "string"}, + "org.opencontainers.image.ref.name": {"type": "string"}, + "org.opencontainers.image.title": {"type": "string"}, + "org.opencontainers.image.description":{"type": "string"}, + "org.opencontainers.image.base.digest":{"type": "string"}, + "org.opencontainers.image.base.name": {"type": "string"} + }, + "required": [ + "org.opencontainers.image.created", + "org.opencontainers.image.authors", + "org.opencontainers.image.url", + "org.opencontainers.image.documentation", + "org.opencontainers.image.source", + "org.opencontainers.image.version", + "org.opencontainers.image.revision", + "org.opencontainers.image.vendor", + "org.opencontainers.image.licenses", + "org.opencontainers.image.ref.name", + "org.opencontainers.image.title", + "org.opencontainers.image.description", + "org.opencontainers.image.base.digest", + "org.opencontainers.image.base.name" + ], + "patternProperties": { + "^org\\.opencontainers\\.image(?!\\.created$|\\.authors$|\\.url$|\\.documentation$|\\.source$|\\.version$|\\.revision$|\\.vendor$|\\.licenses$|\\.ref\\.name$|\\.title$|\\.description$|\\.base\\.digest$|\\.base\\.name$).*": { + "not": {} + } + }, + "additionalProperties": true + }, + { + "type":"object", + "patternProperties": { + "^org\\.opencontainers\\.image.*": { + "not": {} + } + }, + "additionalProperties": true + } + ] + }, + { "type":"null" } + ]} + }, + "required":[], + "additionalProperties": true + } + }, + "required":["Architecture","Os","Config"], + "additionalProperties": true +} \ No newline at end of file diff --git a/.github/validate_docker.py b/.github/validate_docker.py new file mode 100644 index 0000000..700a839 --- /dev/null +++ b/.github/validate_docker.py @@ -0,0 +1,28 @@ +import docker, sys +import json, jsonschema + +def validate_image_labels(image_name,schema): #, expected_labels): + """ + This function checks if a Docker image has the specified structure. + + Args: + image_name: Name of the Docker image to inspect. + schema: Schema to validate against. + + Returns: + True if the image attributes match the json schema, False otherwise. + """ + client = docker.from_env() + try: + image = client.images.get(image_name) + except docker.errors.ImageNotFound: + print(f"Error: Image '{image_name}' not found.") + return False + + jsonschema.validators.validate(instance=image.attrs,schema=schema) + +if __name__ == "__main__": + image_name = sys.argv[1] + with open(sys.argv[2]) as fh: + schema = json.load(fh) + validate_image_labels(image_name,schema) \ No newline at end of file diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index 0d4d204..0eeb4d4 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -43,9 +43,9 @@ jobs: with: filters: ".github/tags.yml" token: "" - dockerfile-lint: + dockerfile-validate-build: runs-on: ubuntu-latest - name: dockerfile-lint + name: dockerfile-build needs: [dockerfile-changes] if: needs.dockerfile-changes.outputs.docker-images != '[]' strategy: @@ -60,18 +60,16 @@ jobs: with: dockerfile: containers/${{ matrix.tags }}/Dockerfile verbose: true - dockerfile-build: - runs-on: ubuntu-latest - name: dockerfile-build - needs: [dockerfile-changes] - if: needs.dockerfile-changes.outputs.docker-images != '[]' - strategy: - fail-fast: false - matrix: - tags: ["${{ fromJson(needs.dockerfile-changes.outputs.docker-images) }}"] - steps: - - name: Checkout - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + with: + python-version: "3.11" + - name: Get docker repo name + id: docker_repo_name + run: echo name=$( dirname "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT + - name: Get docker version + id: docker_repo_version + run: echo version=$( basename "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx @@ -82,12 +80,6 @@ jobs: registry: mskcc.jfrog.io username: ${{ secrets.MSK_JFROG_USERNAME }} password: ${{ secrets.MSK_JFROG_TOKEN }} - - name: Get docker repo name - id: docker_repo_name - run: echo name=$( dirname "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT - - name: Get docker version - id: docker_repo_version - run: echo version=$( basename "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT - name: Build Docker uses: docker/build-push-action@v5 with: @@ -95,10 +87,17 @@ jobs: file: containers/${{ matrix.tags }}/Dockerfile load: true tags: ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + - name: Install pip + run: python -m pip install --upgrade pip + - name: Install python docker package + run : pip install docker + - name: Validate docker + run: | + python .github/validate_docker.py ${image_name} .github/jsonschema/docker_image.json - name: Test image run: | docker run --rm ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} - - name: Export to Docker + - name: Push build to registry uses: docker/build-push-action@v5 with: context: containers/${{ matrix.tags }}/ diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index e61d0b5..212a485 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -41,9 +41,9 @@ jobs: with: filters: ".github/tags.yml" token: "" - dockerfile-lint: + dockerfile-validate-build: runs-on: ubuntu-latest - name: dockerfile-lint + name: dockerfile-build needs: [dockerfile-changes] if: needs.dockerfile-changes.outputs.docker-images != '[]' strategy: @@ -57,18 +57,17 @@ jobs: uses: hadolint/hadolint-action@v3.1.0 with: dockerfile: containers/${{ matrix.tags }}/Dockerfile - dockerfile-build: - runs-on: ubuntu-latest - name: dockerfile-build - needs: [dockerfile-changes] - if: needs.dockerfile-changes.outputs.docker-images != '[]' - strategy: - fail-fast: false - matrix: - tags: ["${{ fromJson(needs.dockerfile-changes.outputs.docker-images) }}"] - steps: - - name: Checkout - uses: actions/checkout@v4 + verbose: true + - name: Set up Python + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + with: + python-version: "3.11" + - name: Get docker repo name + id: docker_repo_name + run: echo name=$( dirname "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT + - name: Get docker version + id: docker_repo_version + run: echo version=$( basename "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx @@ -79,12 +78,6 @@ jobs: registry: mskcc.jfrog.io username: ${{ secrets.MSK_JFROG_USERNAME }} password: ${{ secrets.MSK_JFROG_TOKEN }} - - name: Get docker repo name - id: docker_repo_name - run: echo name=$( dirname "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT - - name: Get docker version - id: docker_repo_version - run: echo version=$( basename "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT - name: Build Docker uses: docker/build-push-action@v5 with: @@ -92,10 +85,17 @@ jobs: file: containers/${{ matrix.tags }}/Dockerfile load: true tags: ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + - name: Install pip + run: python -m pip install --upgrade pip + - name: Install python docker package + run : pip install docker + - name: Validate docker + run: | + python .github/validate_docker.py ${image_name} .github/jsonschema/docker_image.json - name: Test image run: | docker run --rm ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} - - name: Export to Docker + - name: Push build to registry uses: docker/build-push-action@v5 with: context: containers/${{ matrix.tags }}/ From c82c67119fe10b6a85a692ff4f57cf75e1973866 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Fri, 22 Mar 2024 14:26:52 -0400 Subject: [PATCH 06/19] fix validate_docker.cmd --- .github/workflows/dev-build.yml | 2 +- .github/workflows/prod-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index 0eeb4d4..8ec0a7c 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -93,7 +93,7 @@ jobs: run : pip install docker - name: Validate docker run: | - python .github/validate_docker.py ${image_name} .github/jsonschema/docker_image.json + python .github/validate_docker.py ${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json - name: Test image run: | docker run --rm ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index 212a485..db133ec 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -91,7 +91,7 @@ jobs: run : pip install docker - name: Validate docker run: | - python .github/validate_docker.py ${image_name} .github/jsonschema/docker_image.json + python .github/validate_docker.py ${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json - name: Test image run: | docker run --rm ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} From e5da0fc125fed0a0cb9f94a42d6d97bd0787e1f2 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Mon, 25 Mar 2024 10:58:42 -0400 Subject: [PATCH 07/19] update docker image schema based on feedback from team --- .github/jsonschema/docker_image.json | 100 ++++++++++----------------- 1 file changed, 37 insertions(+), 63 deletions(-) diff --git a/.github/jsonschema/docker_image.json b/.github/jsonschema/docker_image.json index a274fed..bcc9bd9 100644 --- a/.github/jsonschema/docker_image.json +++ b/.github/jsonschema/docker_image.json @@ -16,71 +16,45 @@ "type":"object", "properties": { "Labels": { - "oneOf":[{ - "type":"object", - "oneOf": [ - { - "type":"object", - "properties": { - "org.opencontainers.image.created": { - "type": "string", - "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(?:T([01][0-9]|2[0-3])(:[0-5][0-9])(:[0-5][0-9])(?:\\.[0-9]+)?Z?)?$" - }, - "org.opencontainers.image.authors": {"type": "string"}, - "org.opencontainers.image.url": { - "type": "string", - "pattern":"^(?:http://|https://|www\\.).*" - }, - "org.opencontainers.image.documentation": {"type": "string"}, - "org.opencontainers.image.source": {"type": "string"}, - "org.opencontainers.image.version": {"type": "string"}, - "org.opencontainers.image.revision": {"type": "string"}, - "org.opencontainers.image.vendor": {"type": "string"}, - "org.opencontainers.image.licenses": {"type": "string"}, - "org.opencontainers.image.ref.name": {"type": "string"}, - "org.opencontainers.image.title": {"type": "string"}, - "org.opencontainers.image.description":{"type": "string"}, - "org.opencontainers.image.base.digest":{"type": "string"}, - "org.opencontainers.image.base.name": {"type": "string"} - }, - "required": [ - "org.opencontainers.image.created", - "org.opencontainers.image.authors", - "org.opencontainers.image.url", - "org.opencontainers.image.documentation", - "org.opencontainers.image.source", - "org.opencontainers.image.version", - "org.opencontainers.image.revision", - "org.opencontainers.image.vendor", - "org.opencontainers.image.licenses", - "org.opencontainers.image.ref.name", - "org.opencontainers.image.title", - "org.opencontainers.image.description", - "org.opencontainers.image.base.digest", - "org.opencontainers.image.base.name" - ], - "patternProperties": { - "^org\\.opencontainers\\.image(?!\\.created$|\\.authors$|\\.url$|\\.documentation$|\\.source$|\\.version$|\\.revision$|\\.vendor$|\\.licenses$|\\.ref\\.name$|\\.title$|\\.description$|\\.base\\.digest$|\\.base\\.name$).*": { - "not": {} - } - }, - "additionalProperties": true - }, - { - "type":"object", - "patternProperties": { - "^org\\.opencontainers\\.image.*": { - "not": {} - } - }, - "additionalProperties": true - } - ] + "type":"object", + "patternProperties": { + "^org\\.opencontainers\\.image(?!\\.created\\.?|\\.authors\\.?|\\.url\\.?|\\.documentation\\.?|\\.source\\.?|\\.version\\.?|\\.revision\\.?|\\.vendor\\.?|\\.licenses\\.?|\\.ref\\.name\\.?|\\.title\\.?|\\.description\\.?|\\.base\\.digest\\.?|\\.base\\.name\\.?).*": { + "not": {} + }, + "org\\.opencontainers\\.image\\.created(\\..*)?": { + "type": "string", + "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(?:T([01][0-9]|2[0-3])(:[0-5][0-9])(:[0-5][0-9])(?:\\.[0-9]+)?Z?)?$" + }, + "org\\.opencontainers\\.image\\.authors(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.url(\\..*)?": { + "type": "string", + "pattern":"^(?:http://|https://|www\\.).*" + }, + "org\\.opencontainers\\.image\\.documentation(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.source(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.version(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.revision(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.vendor(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.licenses(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.ref\\.name(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.title(\\..*)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.description(\\..*)?":{"type": "string"}, + "org\\.opencontainers\\.image\\.base\\.digest(\\..*)?":{"type": "string"}, + "org\\.opencontainers\\.image\\.base\\.name(\\..*)?": {"type": "string"} }, - { "type":"null" } - ]} + "required": [ + "org.opencontainers.image.url", + "org.opencontainers.image.created", + "org.opencontainers.image.authors", + "org.opencontainers.image.source", + "org.opencontainers.image.version", + "org.opencontainers.image.title", + "org.opencontainers.image.description" + ], + "additionalProperties": true + } }, - "required":[], + "required":["Labels"], "additionalProperties": true } }, From d0af070a4b2176488151b16a5eac15d53da2a8d6 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 4 Apr 2024 10:40:03 -0400 Subject: [PATCH 08/19] fix regex patterns in jsonschema, also remove requiredlabels --- .github/jsonschema/docker_image.json | 31 ++++++++++------------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/.github/jsonschema/docker_image.json b/.github/jsonschema/docker_image.json index bcc9bd9..4d870ac 100644 --- a/.github/jsonschema/docker_image.json +++ b/.github/jsonschema/docker_image.json @@ -30,27 +30,18 @@ "type": "string", "pattern":"^(?:http://|https://|www\\.).*" }, - "org\\.opencontainers\\.image\\.documentation(\\..*)?": {"type": "string"}, - "org\\.opencontainers\\.image\\.source(\\..*)?": {"type": "string"}, - "org\\.opencontainers\\.image\\.version(\\..*)?": {"type": "string"}, - "org\\.opencontainers\\.image\\.revision(\\..*)?": {"type": "string"}, - "org\\.opencontainers\\.image\\.vendor(\\..*)?": {"type": "string"}, - "org\\.opencontainers\\.image\\.licenses(\\..*)?": {"type": "string"}, - "org\\.opencontainers\\.image\\.ref\\.name(\\..*)?": {"type": "string"}, - "org\\.opencontainers\\.image\\.title(\\..*)?": {"type": "string"}, - "org\\.opencontainers\\.image\\.description(\\..*)?":{"type": "string"}, - "org\\.opencontainers\\.image\\.base\\.digest(\\..*)?":{"type": "string"}, - "org\\.opencontainers\\.image\\.base\\.name(\\..*)?": {"type": "string"} + "org\\.opencontainers\\.image\\.documentation(\\..+)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.source(\\..+)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.version(\\..+)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.revision(\\..+)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.vendor(\\..+)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.licenses(\\..+)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.ref\\.name(\\..+)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.title(\\..+)?": {"type": "string"}, + "org\\.opencontainers\\.image\\.description(\\..+)?":{"type": "string"}, + "org\\.opencontainers\\.image\\.base\\.digest(\\..+)?":{"type": "string"}, + "org\\.opencontainers\\.image\\.base\\.name(\\..+)?": {"type": "string"} }, - "required": [ - "org.opencontainers.image.url", - "org.opencontainers.image.created", - "org.opencontainers.image.authors", - "org.opencontainers.image.source", - "org.opencontainers.image.version", - "org.opencontainers.image.title", - "org.opencontainers.image.description" - ], "additionalProperties": true } }, From a6757e9da724be2ab96e8247cd82cc39ff7e5f9c Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 4 Apr 2024 10:40:23 -0400 Subject: [PATCH 09/19] update docker validation script --- .github/validate_docker.py | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/.github/validate_docker.py b/.github/validate_docker.py index 700a839..e60d2be 100644 --- a/.github/validate_docker.py +++ b/.github/validate_docker.py @@ -1,7 +1,8 @@ import docker, sys import json, jsonschema +import re -def validate_image_labels(image_name,schema): #, expected_labels): +def validate_image_labels(image_name,schema,required_annot): #, expected_labels): """ This function checks if a Docker image has the specified structure. @@ -13,16 +14,39 @@ def validate_image_labels(image_name,schema): #, expected_labels): True if the image attributes match the json schema, False otherwise. """ client = docker.from_env() - try: - image = client.images.get(image_name) - except docker.errors.ImageNotFound: - print(f"Error: Image '{image_name}' not found.") - return False + # if fail, raises docker.errors.ImageNotFound + image = client.images.get(image_name) + #try: + # image = client.images.get(image_name) + #except docker.errors.ImageNotFound: + # print(f"Error: Image '{image_name}' not found.") + # return False jsonschema.validators.validate(instance=image.attrs,schema=schema) + #print(json.dumps(image.attrs["Config"]["Labels"], indent=4)) + missing_label = [] + for i in required_annot: + if not any([re.search(i,j) for j in image.attrs["Config"]["Labels"]]): + missing_label += [i] + + if len(missing_label) > 0: + print(f"Missing labels in image:\n{"\n".join(missing_label)}") + raise Exception("Failed due to missing labels") + +#jsonschema doesn't seem like it can easily require patterned properties +required_annot = [ + r"^org\.opencontainers\.image\.url(\..+)?", + r"^org\.opencontainers\.image\.created(\..+)?", + r"^org\.opencontainers\.image\.authors(\..+)?", + r"^org\.opencontainers\.image\.source(\..+)?", + r"^org\.opencontainers\.image\.version(\..+)?", + r"^org\.opencontainers\.image\.title(\..+)?", + r"^org\.opencontainers\.image\.description(\..+)?" +] + if __name__ == "__main__": image_name = sys.argv[1] with open(sys.argv[2]) as fh: schema = json.load(fh) - validate_image_labels(image_name,schema) \ No newline at end of file + validate_image_labels(image_name,schema,required_annot) \ No newline at end of file From bb6141926483de0c4cd4e08c56d50dc1158d0982 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 4 Apr 2024 10:50:05 -0400 Subject: [PATCH 10/19] upgrade python version --- .github/workflows/dev-build.yml | 2 +- .github/workflows/prod-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index 8ec0a7c..bf76222 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -63,7 +63,7 @@ jobs: - name: Set up Python uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: - python-version: "3.11" + python-version: "3.12" - name: Get docker repo name id: docker_repo_name run: echo name=$( dirname "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index db133ec..0f84bc5 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -61,7 +61,7 @@ jobs: - name: Set up Python uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: - python-version: "3.11" + python-version: "3.12" - name: Get docker repo name id: docker_repo_name run: echo name=$( dirname "${{ matrix.tags }}" ) >> $GITHUB_OUTPUT From 50f373dc36b2a970b995469b168138d06bd77c6f Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 4 Apr 2024 10:53:09 -0400 Subject: [PATCH 11/19] fix docker image name for label validation step --- .github/workflows/dev-build.yml | 2 +- .github/workflows/prod-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index bf76222..e59173c 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -93,7 +93,7 @@ jobs: run : pip install docker - name: Validate docker run: | - python .github/validate_docker.py ${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json + python .github/validate_docker.py ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json - name: Test image run: | docker run --rm ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index 0f84bc5..c401220 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -91,7 +91,7 @@ jobs: run : pip install docker - name: Validate docker run: | - python .github/validate_docker.py ${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json + python .github/validate_docker.py ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json - name: Test image run: | docker run --rm ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} From 363690224c90820a3c617a52e9a27e14c8178195 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 4 Apr 2024 10:55:51 -0400 Subject: [PATCH 12/19] install jsonschema in python --- .github/workflows/dev-build.yml | 2 +- .github/workflows/prod-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index e59173c..dd20a90 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -90,7 +90,7 @@ jobs: - name: Install pip run: python -m pip install --upgrade pip - name: Install python docker package - run : pip install docker + run : pip install docker jsonschema - name: Validate docker run: | python .github/validate_docker.py ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index c401220..699569f 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -88,7 +88,7 @@ jobs: - name: Install pip run: python -m pip install --upgrade pip - name: Install python docker package - run : pip install docker + run : pip install docker jsonschema - name: Validate docker run: | python .github/validate_docker.py ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json From 08e0ae713bebbf48bd2b01d36ed889bf561141ea Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 4 Apr 2024 11:01:57 -0400 Subject: [PATCH 13/19] update labels in testapp:0.0.1 --- containers/testapp/0.0.1/Dockerfile | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/containers/testapp/0.0.1/Dockerfile b/containers/testapp/0.0.1/Dockerfile index 356b5f1..d1748c8 100644 --- a/containers/testapp/0.0.1/Dockerfile +++ b/containers/testapp/0.0.1/Dockerfile @@ -1,5 +1,18 @@ FROM python:3.9-slim +# Labels +LABEL org.opencontainers.image.vendor="MSKCC-OMICS-WORKFLOWS" +LABEL org.opencontainers.image.authors="Anne Marie Noronha (noronhaa@mskcc.org)" + +LABEL org.opencontainers.image.created="2020-12-16T15:55:35Z" \ + org.opencontainers.image.version="0.0.1" \ + org.opencontainers.image.licenses="test-license" \ + org.opencontainers.image.source="https://github.com/mskcc-omics-workflows/containers/containers/testapp/" \ + org.opencontainers.image.url="https://github.com/mskcc-omics-workflows/containers/" \ + org.opencontainers.image.title="My test app" + + + # Set the working directory in the container WORKDIR /app From 880bfccfe3d2c8ef4c6fbd9b1164278c6ecbe6ed Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 4 Apr 2024 11:03:57 -0400 Subject: [PATCH 14/19] add org.opencontainers.image.description label in testapp:0.0.1 --- containers/testapp/0.0.1/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/containers/testapp/0.0.1/Dockerfile b/containers/testapp/0.0.1/Dockerfile index d1748c8..c01d531 100644 --- a/containers/testapp/0.0.1/Dockerfile +++ b/containers/testapp/0.0.1/Dockerfile @@ -9,7 +9,8 @@ LABEL org.opencontainers.image.created="2020-12-16T15:55:35Z" \ org.opencontainers.image.licenses="test-license" \ org.opencontainers.image.source="https://github.com/mskcc-omics-workflows/containers/containers/testapp/" \ org.opencontainers.image.url="https://github.com/mskcc-omics-workflows/containers/" \ - org.opencontainers.image.title="My test app" + org.opencontainers.image.title="My test app" \ + org.opencontainers.image.description="My test app description" From 68adaf04bf7bf4c44375ccd3ce2718f5492543e4 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 4 Apr 2024 11:08:07 -0400 Subject: [PATCH 15/19] update README --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index 6e73325..a29052a 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,43 @@ Mono-repository for custom docker containers used in nextflow modules For further information on how to contribute or use images in this repository, visit our [Gitbook documentation](https://mskcc-omics-workflows.gitbook.io/omics-wf/GMaCKqX0TmAhUOoZmuc6/image-management) + +## Naming conventions + +Each Dockerfile should be saved within a specific folder structure: + +``` +containers///Dockerfile +``` + +Any custom scripts or resource files that are included in the image or required for building the image should be contained in the same folder as the Dockerfile. When you open a pull request for the container, an image will be automatically created and be labeled `$REGISTRY/:version` + +The version of the image should correspond to the version of the software it contains. If the image has multiple independent software packages, the image version should start at 0.1.0 and increment in accordance with [Semantic Versioning](https://semver.org/#semantic-versioning-200). + +## Image repository + +Development images are stored at `mskcc.jfrog.io/omicswf-docker-dev-local/mskcc-omics-workflows`. When a pull request is created against the `develop` branch, and the image passes basic checks, the image is automatically built and pushed to this location. + +Productions images are stored at `mskcc.jfrog.io/omicswf-docker-prod-local/mskcc-omics-workflows`. When a pull request is created against the `master` branch, and the image passes basic checks, the image is automatically built and pushed to this location. + +When contributing an image you should first open a pull request to `develop`. The `develop` branch will be merged regularly into `master`. + +## Image Requirements + +Requirements are based on [OCI image-spec annotations](https://github.com/opencontainers/image-spec/blob/main/annotations.md). The image must have the following labels: +``` +org.opencontainers.image.url +org.opencontainers.image.created +org.opencontainers.image.authors +org.opencontainers.image.source +org.opencontainers.image.version +org.opencontainers.image.title +org.opencontainers.image.description +``` +You can optionally use any of the above properties with an extension related to a specific software in the image, and you can use multiple of them as well. For example, if you want to label versions for both the Java version and the abra version: +``` +LABEL \ + org.opencontainers.image.version.java=${JAVA_VERSION} \ + org.opencontainers.image.version.abra2=${ABRA2_VERSION} +``` +It is also acceptable to use no extension. \ No newline at end of file From 269075e9a703b04b998491ba2d8b559ec71300d8 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 18 Apr 2024 09:54:01 -0400 Subject: [PATCH 16/19] remove lintfail container --- containers/lintfail/latest/Dockerfile | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 containers/lintfail/latest/Dockerfile diff --git a/containers/lintfail/latest/Dockerfile b/containers/lintfail/latest/Dockerfile deleted file mode 100644 index 0796866..0000000 --- a/containers/lintfail/latest/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM ubuntu:latest -RUN apt-get update -RUN apt-get install -y curl -RUN apt-get update && apt-get install -y curl -RUN echo "hello world" | grep "world" | wc -l -CMD ["echo", "Hello, world!"] From 6ce46fb9992b28944408bbfcf07876ba87669551 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 18 Apr 2024 10:03:03 -0400 Subject: [PATCH 17/19] add confirm-pass step --- .github/workflows/dev-build.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index dd20a90..edc34a7 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -103,4 +103,21 @@ jobs: context: containers/${{ matrix.tags }}/ file: containers/${{ matrix.tags }}/Dockerfile tags: ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} - push: true \ No newline at end of file + push: true + confirm-pass: + runs-on: ubuntu-latest + needs: [ dockerfile-changes, dockerfile-validate-build ] + if: always() + steps: + - name: All tests ok + if: ${{ success() || !contains(needs.*.result, 'failure') }} + run: exit 0 + - name: One or more tests failed + if: ${{ contains(needs.*.result, 'failure') }} + run: exit 1 + + - name: debug-print + if: always() + run: | + echo "toJSON(needs) = ${{ toJSON(needs) }}" + echo "toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}" \ No newline at end of file From 99e15b49700c178e51db86a6245a888d76556079 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 18 Apr 2024 10:07:51 -0400 Subject: [PATCH 18/19] add confirm-pass step to prod github workflow as well --- .github/workflows/prod-build.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index 699569f..d0974d4 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -101,4 +101,21 @@ jobs: context: containers/${{ matrix.tags }}/ file: containers/${{ matrix.tags }}/Dockerfile tags: ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} - push: true \ No newline at end of file + push: true + confirm-pass: + runs-on: ubuntu-latest + needs: [ dockerfile-changes, dockerfile-validate-build ] + if: always() + steps: + - name: All tests ok + if: ${{ success() || !contains(needs.*.result, 'failure') }} + run: exit 0 + - name: One or more tests failed + if: ${{ contains(needs.*.result, 'failure') }} + run: exit 1 + + - name: debug-print + if: always() + run: | + echo "toJSON(needs) = ${{ toJSON(needs) }}" + echo "toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}" \ No newline at end of file From e40056fb3c97120cef9989f00748a10b5f905949 Mon Sep 17 00:00:00 2001 From: Anne Marie Noronha Date: Thu, 18 Apr 2024 10:24:03 -0400 Subject: [PATCH 19/19] Add docker build push to ghcr.io --- .github/workflows/dev-build.yml | 14 ++++++++------ .github/workflows/prod-build.yml | 26 ++++++++++++++++++-------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index edc34a7..8e6a99e 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -10,7 +10,9 @@ concurrency: cancel-in-progress: true env: - REGISTRY: mskcc.jfrog.io/omicswf-docker-dev-local/mskcc-omics-workflows + JFROG_REGISTRY: mskcc.jfrog.io + JFROG_CONTAINER_REPO: mskcc.jfrog.io/omicswf-docker-prod-local/mskcc-omics-workflows + GHCR_CONTAINER_REPO: ghcr.io/mskcc-omics-workflows/ jobs: dockerfile-changes: @@ -80,29 +82,29 @@ jobs: registry: mskcc.jfrog.io username: ${{ secrets.MSK_JFROG_USERNAME }} password: ${{ secrets.MSK_JFROG_TOKEN }} - - name: Build Docker + - name: Build Docker Jfrog uses: docker/build-push-action@v5 with: context: containers/${{ matrix.tags }}/ file: containers/${{ matrix.tags }}/Dockerfile load: true - tags: ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + tags: ${{ env.JFROG_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} - name: Install pip run: python -m pip install --upgrade pip - name: Install python docker package run : pip install docker jsonschema - name: Validate docker run: | - python .github/validate_docker.py ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json + python .github/validate_docker.py ${{ env.JFROG_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json - name: Test image run: | - docker run --rm ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + docker run --rm ${{ env.JFROG_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} - name: Push build to registry uses: docker/build-push-action@v5 with: context: containers/${{ matrix.tags }}/ file: containers/${{ matrix.tags }}/Dockerfile - tags: ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + tags: ${{ env.JFROG_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} push: true confirm-pass: runs-on: ubuntu-latest diff --git a/.github/workflows/prod-build.yml b/.github/workflows/prod-build.yml index d0974d4..4095b5b 100644 --- a/.github/workflows/prod-build.yml +++ b/.github/workflows/prod-build.yml @@ -8,7 +8,9 @@ concurrency: cancel-in-progress: true env: - REGISTRY: mskcc.jfrog.io/omicswf-docker-prod-local/mskcc-omics-workflows + JFROG_REGISTRY: mskcc.jfrog.io + JFROG_CONTAINER_REPO: mskcc.jfrog.io/omicswf-docker-prod-local/mskcc-omics-workflows + GHCR_CONTAINER_REPO: ghcr.io/mskcc-omics-workflows/ jobs: dockerfile-changes: @@ -75,32 +77,40 @@ jobs: - name: Login to Docker Hub uses: docker/login-action@v3 with: - registry: mskcc.jfrog.io + registry: env.JFROG_REGISTRY username: ${{ secrets.MSK_JFROG_USERNAME }} password: ${{ secrets.MSK_JFROG_TOKEN }} - - name: Build Docker + - name: Build Docker Jfrog uses: docker/build-push-action@v5 with: context: containers/${{ matrix.tags }}/ file: containers/${{ matrix.tags }}/Dockerfile load: true - tags: ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + tags: ${{ env.JFROG_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} - name: Install pip run: python -m pip install --upgrade pip - name: Install python docker package run : pip install docker jsonschema - name: Validate docker run: | - python .github/validate_docker.py ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json + python .github/validate_docker.py ${{ env.JFROG_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} .github/jsonschema/docker_image.json - name: Test image run: | - docker run --rm ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} - - name: Push build to registry + docker run --rm ${{ env.JFROG_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + - name: Push build to Jfrog repo uses: docker/build-push-action@v5 with: context: containers/${{ matrix.tags }}/ file: containers/${{ matrix.tags }}/Dockerfile - tags: ${{ env.REGISTRY }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + tags: ${{ env.JFROG_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} + push: true + - name: Build and push Docker to GHCR + uses: docker/build-push-action@v5 + with: + context: containers/${{ matrix.tags }}/ + file: containers/${{ matrix.tags }}/Dockerfile + load: true + tags: ${{ env.GHCR_CONTAINER_REPO }}/${{ steps.docker_repo_name.outputs.name}}:${{steps.docker_repo_version.outputs.version}} push: true confirm-pass: runs-on: ubuntu-latest