Welcome to the third lesson in our course on Working with Container Registries. In the previous lesson, you created a secure ECR repository with vulnerability scanning and immutable tags enabled. Now you have an empty repository waiting for container images, but how do you actually get your applications into ECR?
This lesson bridges that gap by teaching you the complete workflow for getting locally built Docker images into your ECR repository. We'll start with a simple Flask web application, build it into a Docker image on your local machine, authenticate Docker to work with ECR, tag the image with the proper ECR naming convention, and finally push it to your repository.
By the end of this lesson, we'll execute the full sequence: docker build to create your image locally, aws ecr get-login-password to authenticate, docker tag to prepare the image for ECR, and docker push to upload it. This workflow forms the foundation for all ECR operations, whether you're working manually or setting up automated CI/CD pipelines.
The sample application we'll use is a minimal Flask web server that responds with "Hello from ECR!" when accessed. While simple, this demonstrates the complete process we'll use for any containerized application, from microservices to complex web applications.
Before pushing your first image to ECR, you need to confirm that your repository from the previous lesson exists and gather the specific details required for the push process. The repository URI you created earlier contains your AWS account ID and region, both of which are essential for the tagging and authentication steps.
Run this command to verify your repository exists and note its URI:
The output should show your repository details, including the repositoryUri field that looks like 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-web-app. This URI contains three critical pieces of information: your 12-digit AWS account ID (123456789012), your region (us-east-1), and your repository name (my-web-app). We'll need these components for the authentication and tagging steps.
Your AWS CLI must be configured with credentials that have ECR permissions, specifically ecr:GetAuthorizationToken for authentication, ecr:BatchCheckLayerAvailability and ecr:PutImage for pushing images, and ecr:InitiateLayerUpload and ecr:UploadLayerPart for the actual upload process.
In the CodeSignal environment, Docker, the AWS CLI, and all necessary permissions are pre-configured for you. However, understanding these requirements is important when you work on your own development machine or set up CI/CD pipelines in production environments.
The first step in getting an image to ECR is having an image to push. We'll build a simple Flask web application using the same files from our previous Docker lessons. The application consists of three files, which will already be provided for you in the docker-app directory: a Python application file (app.py), a requirements file for dependencies (requirements.txt), and a Dockerfile that defines how to build the container image.
The Flask application in docker-app/app.py creates a basic web server that listens on port 3000 and responds with a simple message. The requirements.txt file specifies Flask version 2.3.3 as the only dependency, ensuring reproducible builds. The Dockerfile uses Python 3.9 as the base image, installs the requirements, copies the application code, and configures the container to run the Flask application.
Navigate to the directory containing your application files and build the Docker image:
The docker build command reads the Dockerfile in the current directory (indicated by the .) and creates an image tagged as my-web-app. The build process downloads the Python base image, installs Flask, and packages your application code into a complete container image.
After the build completes, verify that your image exists locally:
You should see output showing your newly created image with the my-web-app repository name and latest tag. This local image is now ready to be tagged and pushed to ECR, but first, you need to authenticate Docker to work with your ECR registry.
Before Docker can push images to ECR, it must authenticate with the registry using your AWS credentials. ECR uses a temporary authentication token that expires after 12 hours, so we'll need to re-authenticate periodically when working with ECR over extended periods.
The authentication process involves two steps: getting an authentication token from ECR and using that token to log Docker into your ECR registry. AWS provides a convenient command that combines both steps:
Replace us-east-1 with your actual region and 123456789012 with your actual AWS account ID from the repository URI you noted earlier. The aws ecr get-login-password command generates a temporary password that's valid for 12 hours, and the pipe (|) passes this password directly to the docker login command.
The registry URL in the docker login command follows the pattern <account_id>.dkr.ecr.<region>.amazonaws.com. This is the base URL for all ECR repositories in your account and region. When the authentication succeeds, you'll see a "Login Succeeded" message.
This authentication step is required every time you start a new session or when your token expires. In automated environments like CI/CD pipelines, this authentication step is typically included in deployment scripts to ensure fresh tokens for each build.
Docker images must be tagged with the complete ECR repository URI before they can be pushed to ECR. The tag tells Docker exactly where to push the image and what to call it in the registry. ECR requires a specific naming format that includes your account ID, region, repository name, and image tag.
Tag your local image with the ECR repository URI:
Replace the account ID and region with your actual values from the repository URI. This command creates a new tag for your existing image without duplicating the image data. The format <account_id>.dkr.ecr.<region>.amazonaws.com/<repository_name>:<tag> is required for all ECR images.
The tag portion (:latest in this example) is optional but recommended. If you omit it, Docker assumes :latest. While :latest is convenient for development, production environments typically use specific version tags like :v1.2.3 or :build-456 to ensure predictable deployments.
After tagging, you can verify that both tags exist for the same image:
You should see two entries: your original my-web-app:latest tag and the new ECR-formatted tag. Both point to the same image ID, confirming that tagging doesn't create duplicate images locally.
With your image properly tagged and Docker authenticated to ECR, you can now push the image to your repository. The push process uploads all the image layers to ECR, where they're stored securely and made available for deployment.
Push your tagged image to ECR:
The push command uploads your image layers to ECR. We'll see progress indicators showing each layer being pushed. Docker optimizes this process by only uploading layers that don't already exist in the registry, which speeds up subsequent pushes of related images.
Once the push completes, verify that your image is now stored in ECR:
This command shows all images in your repository. You should see your image with the :latest tag and details like the image digest and push timestamp. The image digest is a unique identifier based on the image content, ensuring integrity and enabling precise image references.
Since you enabled scan-on-push when creating your repository, ECR automatically begins scanning your image for vulnerabilities. You can check the scan status with:
The output includes an imageScanFindingsSummary section that shows the scan status and any vulnerabilities found. Initial scans typically complete within a few minutes. Here is a sample of what the summary looks like once the scan is complete:
The findingSeverityCounts gives you a quick overview of potential security issues found in your image, categorized by severity. This provides valuable security insights about your container images.
Several common issues can prevent successful image pushes to ECR. Understanding these problems and their solutions helps you troubleshoot quickly and maintain smooth workflows.
- Authentication failures: This is the most frequent issue, usually caused by expired tokens or incorrect registry URLs. If you see "authentication required" errors, re-run the
aws ecr get-login-passwordcommand with the correct region and account ID. Remember that authentication tokens expire after 12 hours. - Region mismatches: This occurs when your AWS CLI is configured for a different region than your ECR repository. Ensure that the
--regionparameter in your commands matches the region where you created your repository. You can check your current region withaws configure get region. - Immutable tag conflicts: This happens when you try to push an image with a tag that already exists in a repository configured with immutable tags. ECR will reject the push with an error message. The correct solution is to use a new, unique tag for the updated image. While it is possible to delete the existing image and then push a new one with the same tag, this practice defeats the purpose of immutability and should be avoided, as it breaks the guarantee that a tag always refers to the same image.
- Repository URI formatting errors: These cause push failures when the tag format is incorrect. The URI must exactly match
<account_id>.dkr.ecr.<region>.amazonaws.com/<repository_name>:<tag>. Double-check your account ID, region, and repository name against the output fromaws ecr describe-repositories. - Permission denied errors: These indicate that your AWS credentials lack the necessary ECR permissions. Verify that your IAM user or role has policies that include
ecr:GetAuthorizationToken,ecr:BatchCheckLayerAvailability,ecr:PutImage,ecr:InitiateLayerUpload, andecr:UploadLayerPartpermissions.
Most of these issues stem from configuration problems rather than complex technical failures, making them straightforward to resolve once you understand the root cause.
We've successfully learned the complete workflow for getting Docker images into ECR. Starting with a local Docker image, you authenticated Docker to work with ECR using temporary tokens, tagged your image with the proper ECR naming format, and pushed it to your secure repository. You also verified the upload and confirmed that vulnerability scanning began automatically.
This end-to-end process — build, authenticate, tag, push, verify — forms the foundation for all ECR operations. Whether you're deploying a simple web application or managing complex microservices architectures, these same steps apply. The authentication and tagging steps are particularly important to master since they're required for every push operation.
In the upcoming practice exercises, we'll work through this entire workflow hands-on. We'll push our own images to ECR, experiment with different tags, examine vulnerability scan results, and troubleshoot common errors like authentication failures and tag conflicts. These exercises will reinforce the concepts and give you confidence to use ECR in your own projects and production environments.
