Immutable Artifacts & Versioned Releases
Build once, promote the exact same bytes everywhere. Tag by commit SHA, never mutate a published tag, and make every release traceable to a commit.
The most reliable pipelines share one property: the artifact that runs in production is byte-for-byte the one that passed staging. You build once, then promote that immutable artifact through environments — you never rebuild per stage, because a rebuild is a new, untested artifact wearing an old name.
The rules of immutability
- Tag by commit SHA, not
latest.myapp:9f3c1a2means exactly one thing, forever. - Never overwrite a published tag. Turn on ECR tag immutability so a tag can't be silently repointed at different bytes.
- Pin by digest for deploys. A
sha256:...digest is the strongest guarantee — even a tag can't lie about it. - Trace back to source. Stamp the image with the commit and build metadata via OCI labels so any running container answers "where did you come from?".
Promotion, not rebuilding
"Deploying to prod" should mean "tell prod to run image 9f3c1a2, the one staging already blessed" — a pointer change, not a fresh docker build.
Example
# Create an ECR repo that refuses to overwrite tags + scans on push
aws ecr create-repository \
--repository-name myapp \
--image-tag-mutability IMMUTABLE \
--image-scanning-configuration scanOnPush=true
SHA=$(git rev-parse --short HEAD)
REPO=123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp
# Build ONCE, stamped with provenance labels
docker build \
--label org.opencontainers.image.revision=$SHA \
--label org.opencontainers.image.source=https://github.com/acme/myapp \
-t $REPO:$SHA .
docker push $REPO:$SHA
# Deploy by DIGEST — the unspoofable identity
DIGEST=$(aws ecr describe-images --repository-name myapp \
--image-ids imageTag=$SHA --query 'imageDetails[0].imageDigest' --output text)
echo "Promote $REPO@$DIGEST to prod"When to use it
- A team tags every Docker image with the git commit SHA and pushes it to ECR, so every running container is traceable to the exact source commit.
- An ops engineer rolls back a bad production deploy in 3 minutes by updating the ECS task definition to use the previous commit SHA image tag.
- A company bans the 'latest' tag in production ECR policies so all deployments reference an explicit, immutable version.
More examples
Tag image with commit SHA
Builds and pushes a Docker image tagged only with the commit SHA so the tag permanently identifies the source code version.
GIT_SHA=$(git rev-parse --short HEAD)
REPO=123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp
docker build -t $REPO:$GIT_SHA .
docker push $REPO:$GIT_SHA
echo "Immutable image: $REPO:$GIT_SHA"Deny mutable tags in ECR policy
Configures the ECR repository to reject any push that overwrites an existing image tag, enforcing immutability.
aws ecr put-image-tag-mutability \
--repository-name myapp \
--image-tag-mutability IMMUTABLERollback by redeploying previous SHA
Rolls back to a previous known-good release by pointing the ECS service at the immutable image tagged with that commit SHA.
PREV_SHA=abc1234 # SHA of the last known-good commit
REPO=123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp
# Update task definition to previous image and force redeploy
aws ecs update-service \
--cluster prod \
--service myapp \
--task-definition myapp:$PREV_SHA \
--force-new-deployment
Discussion