Reputation: 105
Pulling, tagging, and then pushing a Docker image we produce in a Github actions flow is causing a new image with a new digest to be pushed, rather than simply tagging the existing image.
First, we build the image using the newish v2 of the Docker build-push action (https://github.com/docker/build-push-action)
jobs:
build-push:
name: Build and push docker image
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to GCR
uses: docker/login-action@v1
with:
registry: gcr.io
username: _json_key
password: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
- id: docker_build
uses: docker/build-push-action@v2
with:
tags: gcr.io/our-project/foo:initial-tag
push: true
target: build
build-args: |
NPM_TOKEN=${{ secrets.NPM_TOKEN }}
Then, in a separate workflow later we pull that image (gcr.io/our-project/foo:initial-tag
) down and add new tags.
jobs:
tag-image:
name: Tag image
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Login to GCR
uses: docker/login-action@v1
with:
registry: gcr.io
username: _json_key
password: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
- run: |
docker pull gcr.io/our-project/foo:initial-tag
docker tag gcr.io/our-project/foo:initial-tag gcr.io/our-project/foo:new-tag
docker push gcr.io/our-project/foo:new-tag
After pushing up new-tag
, I would expect our registry to contain one image digest with the initial-tag
and new-tag
on it. Instead, this creates a new image digest with just new-tag
on it.
Digest: sha256:abc123
Tags: gcr.io/our-project/foo:initial-tag
Digest: sha256:def456
Tags: gcr.io/our-project/foo:new-tag
In addition, if we now pull and add a tag (say latest
) to new-tag
, it will NOT create a new image digest
Digest: sha256:abc123
Tags: gcr.io/our-project/foo:initial-tag
Digest: sha256:def456
Tags: gcr.io/our-project/foo:new-tag, gcr.io/our-project/foo:latest
As a workaround, we have found that pushing the image name without tags correctly assigns the tag to the existing digest.
docker pull gcr.io/our-project/foo:initial-tag
docker tag gcr.io/our-project/foo:initial-tag gcr.io/our-project/foo:new-tag
docker push gcr.io/our-project/foo
Upvotes: 7
Views: 5184
Reputation: 7332
If you inspect a docker image, the image id and the repo digests are not the same thing. If I take an image in multiple repositories and run docker inspect
I see multiple digests:
{
"Id": "sha256:8c2c38aa676e97e57b4c8385bbcdcb240a933fafcc5f6cc508d2a3a005b24cb8",
"RepoTags": [
"docker/desktop-vpnkit-controller:v2.0",
"hubproxy.docker.internal:5000/docker/desktop-vpnkit-controller:v2.0"
],
"RepoDigests": [
"docker/desktop-vpnkit-controller@sha256:b5bcb3a7172ae44d3a1df2e74a1b4d4e10d5562efe1d3c9197b23b383de70a86",
"hubproxy.docker.internal:5000/docker/desktop-vpnkit-controller@sha256:b5bcb3a7172ae44d3a1df2e74a1b4d4e10d5562efe1d3c9197b23b383de70a86"
],
The ID field will be the same, which means the FS layers will be the same. It is not a different image.
Upvotes: 1
Reputation: 33
you can export docker image and push like this. then docker image digest does not change whenever you tag more.
- name: build docker image
uses: docker/build-push-action@v3
with:
context: .
file: 'Dockerfile'
load: true
tags: |
${{ steps.tag-container-image.outputs.TAG_A }}
${{ steps.tag-container-image.outputs.TAG_B }}
${{ steps.tag-container-image.outputs.LATEST }}
- name: push docker image
run: |
docker push ${{ steps.tag-container-image.outputs.TAG_A }}
docker push ${{ steps.tag-container-image.outputs.TAG_B }}
docker push ${{ steps.tag-container-image.outputs.LATEST }}
Upvotes: 1
Reputation: 1659
crane cp
will copy images efficiently and retaining the digest value
https://github.com/google/go-containerregistry/blob/main/cmd/crane/doc/crane_copy.md
Upvotes: 1