DevOps新手咨询:如何用CloudFormation推送Docker镜像至ECR
Hey there! As someone who’s been through this exact setup when starting out with DevOps, let’s break down what’s going on here and the best path forward for you.
First off: CloudFormation isn’t designed to handle image building and pushing—it’s an infrastructure-as-code tool meant to provision and manage AWS resources like your ECR repository, batch processing jobs, or compute instances. Trying to shoehorn build/push logic into CloudFormation (even via Init) is going to be clunky and not the most efficient use of the tool.
The Better Approach: Use GitLab CI/CD for Build & Push
Since you already have a GitLab repo with your Dockerfile, GitLab’s built-in CI/CD pipeline is the perfect tool to handle building your image and pushing it to ECR. Here’s a straightforward setup you can copy into a .gitlab-ci.yml file in your repo root:
stages: - build-and-push # Job to build Docker image and push to ECR build-ecr-image: stage: build-and-push image: docker:latest services: - docker:dind # Docker-in-Docker to run build commands variables: AWS_DEFAULT_REGION: "us-east-1" # Update to your region ECR_REPO_URI: "123456789012.dkr.ecr.us-east-1.amazonaws.com/your-repo-name" # Replace with your ECR URI before_script: # Install AWS CLI since the base Docker image doesn't have it - apk add --no-cache aws-cli # Authenticate Docker to your ECR repo - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REPO_URI script: # Build image, tag with Git commit SHA (great for versioning) - docker build -t $ECR_REPO_URI:$CI_COMMIT_SHA . # Push the tagged image to ECR - docker push $ECR_REPO_URI:$CI_COMMIT_SHA # Optional: Tag as "latest" if you want a rolling latest version - docker tag $ECR_REPO_URI:$CI_COMMIT_SHA $ECR_REPO_URI:latest - docker push $ECR_REPO_URI:latest
Setup Steps for This Pipeline:
- Go to your GitLab project’s Settings > CI/CD > Variables
- Add two variables:
AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEY(use an IAM user with permissions to push/pull from ECR—at minimum,AmazonEC2ContainerRegistryFullAccessor a custom policy withecr:GetAuthorizationToken,ecr:BatchCheckLayerAvailability,ecr:GetDownloadUrlForLayer,ecr:BatchGetImage,ecr:InitiateLayerUpload,ecr:UploadLayerPart,ecr:CompleteLayerUpload,ecr:PutImage) - Update the
AWS_DEFAULT_REGIONandECR_REPO_URIvariables in the YAML to match your AWS setup
What About CloudFormation Then?
CloudFormation should handle the infrastructure pieces you need for your batch processing:
- Creating the ECR repository (if it doesn’t exist yet)
- Provisioning batch job definitions, compute environments, or queues
- Any other AWS resources tied to your workflow
You can even have CloudFormation output the ECR repo URI, then reference that in your GitLab CI variables if you want to keep things tied together.
If You Really Need to Use CloudFormation Init (Not Recommended)
If for some reason you have to run the build/push via CloudFormation (e.g., a one-time build instead of ongoing CI), you could use UserData (with cfn-init) on an EC2 instance to run the build commands. But this is inefficient—you’d be spinning up an instance just to run a build, which is overkill compared to using GitLab’s ephemeral CI runners.
Here’s a quick example of what that might look like in CloudFormation:
Resources: ECRBuildInstance: Type: AWS::EC2::Instance Properties: ImageId: ami-0c55b159cbfafe1f0 # Amazon Linux 2 AMI InstanceType: t2.micro IamInstanceProfile: !Ref ECRBuildInstanceProfile # Needs ECR permissions UserData: Fn::Base64: !Sub | #!/bin/bash yum update -y yum install -y docker git aws-cli service docker start usermod -aG docker ec2-user # Clone your GitLab repo (use a personal access token for auth) git clone https://your-gitlab-token@gitlab.com/your-username/your-repo.git /tmp/build-repo cd /tmp/build-repo # Authenticate to ECR aws ecr get-login-password --region ${AWS::Region} | docker login --username AWS --password-stdin ${ECRRepoUri} # Build and push docker build -t ${ECRRepoUri}:latest . docker push ${ECRRepoUri}:latest # Optional: Terminate the instance after build shutdown -h now
Again, this is a workaround—not the standard approach. Stick with GitLab CI for your build/push workflow, and let CloudFormation manage your infrastructure.
内容的提问来源于stack exchange,提问作者Vikas Rathore

