Challenge 1: Add a Semantic Version Tag Alongside SHA — Possible Solution ==================================================================== - run: | docker build \ -t ghcr.io/myorg/myapp:${{ github.sha }} \ -t ghcr.io/myorg/myapp:v1.4.0 \ . - run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - run: docker push ghcr.io/myorg/myapp:${{ github.sha }} - run: docker push ghcr.io/myorg/myapp:v1.4.0 WHY THIS WORKS -------------- - docker build supports MULTIPLE -t flags in a single invocation — each one applies an ADDITIONAL tag to the exact same built image, rather than building the image twice. This means both ghcr.io/myorg/ myapp:${{ github.sha }} and ghcr.io/myorg/myapp:v1.4.0 point to the IDENTICAL underlying image content — there's no risk of the two tags ever referring to subtly different builds, since they're produced from one single build step. - Both tags then need their OWN separate docker push command — pushing is per-tag, not automatic for every tag a local image happens to have. This directly follows the chapter's own pattern of one docker push per tag, just repeated for the second tag added here. - Keeping the SHA tag (this chapter's own recommended traceability tag) ALONGSIDE the new semantic version tag — rather than replacing it — preserves the exact benefit the chapter describes: the SHA tag lets anyone trace EXACTLY which commit produced this image, while the v1.4.0 tag gives humans a readable, memorable release name to refer to the same image by. This matches the chapter's own guidance that "SHA tags for traceability, semantic version tags for human-readable releases — both have a place." - The docker login step only needs to run once before either push, since authentication with the registry isn't tag-specific — it authenticates the whole session for pushing to that registry, regardless of how many tags get pushed afterward.