🔑 Key points
- Deploy the JWT Pizza Service container image to ECR.
AWS Elastic Container Registry (ECR) is an Open Container Initiative (OCI)-compliant container registry. You can store up to 500 MB of container images in a private repository without charge under the AWS Free Tier. Using ECR is a convenient and secure way to upload your jwt-pizza-service container images and then deploy them using AWS Elastic Container Service (ECS). Here is the long-term architecture that we are working towards:
Using ECR is similar to what you did with Docker Hub in a previous instruction topic. The steps are to create a repository and then push an image to that repository.
Important
Make sure you are using the us-east-1 AWS region for all your work in this course.
In order to use ECS, you must first create an ECR repository that will hold the jwt-pizza-service container images. Complete the following steps:
-
Open the AWS Management Console and navigate to the Amazon ECR service.
-
Click Create repository and verify that Private is selected for the visibility settings.
-
Give the repository the name
jwt-pizza-service. -
Click Create.
This results in a newly created repository where you can store your jwt-pizza-service Docker images.
With your ECR repository created, you are ready to automate the building and uploading of a Docker container image for the JWT Pizza Service. Your CI pipeline will trigger the image creation whenever a change is pushed to the jwt-pizza-service codebase. The majority of this work involves giving your CI workflow the rights to push a Docker image into ECR. This includes setting up a trust policy between AWS and GitHub, as well as defining which AWS services GitHub can interact with.
In order for the jwt-pizza-service CI workflow to make requests over the OIDC-authorized connection, you must alter the previously configured github-ci IAM role so that the jwt-pizza-service GitHub repository is also part of the trust relationship.
- Open the AWS IAM service console.
- Choose Roles.
- Select the
github-cirole that you created when you set upjwt-pizzato deploy to S3. - Select the Trust relationships tab.
- Click Edit trust policy.
- Replace the
token.actions.githubusercontent.com:subvalue with the following array. This allows both of your source repositories to make an OIDC connection. ReplaceYOURGITHUBACCOUNTHEREwith your actual GitHub username."token.actions.githubusercontent.com:sub": [ "repo:YOURGITHUBACCOUNTHERE/jwt-pizza:ref:refs/heads/main", "repo:YOURGITHUBACCOUNTHERE/jwt-pizza-service:ref:refs/heads/main" ],
- Click the Update policy button.
Next, you need to enhance the github-ci role permissions so that it can push to ECR and initiate the deployment to ECS.
-
Open the AWS IAM service console.
-
Choose Roles.
-
Select the
github-cirole. -
Select the Permissions tab.
-
Click on the
jwt-pizza-ci-deploymentpolicy. -
Select the JSON tab and click Edit.
-
Add the following statements to the
Statementarray to allow the use of ECR and ECS. Make sure you replaceYOURACCOUNTIDHEREwith your actual AWS account ID.{ "Sid": "AuthenticateWithECR", "Effect": "Allow", "Action": "ecr:GetAuthorizationToken", "Resource": "*" }, { "Sid": "PushToECR", "Effect": "Allow", "Action": [ "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability", "ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload" ], "Resource": "arn:aws:ecr:us-east-1:YOURACCOUNTIDHERE:repository/jwt-pizza-service" }, { "Sid": "DeployContainer", "Effect": "Allow", "Action": [ "ecs:UpdateService" ], "Resource": "arn:aws:ecs:us-east-1:YOURACCOUNTIDHERE:service/jwt-pizza-service/jwt-pizza-service" }, { "Sid": "PassRolesInTaskDefinition", "Effect": "Allow", "Action": [ "iam:PassRole" ], "Resource": [ "arn:aws:iam::YOURACCOUNTIDHERE:role/jwt-pizza-ecs" ] } -
Click Next.
-
Click Save.
Before you can modify the CI workflow for the JWT Pizza Service, you need to add the following secrets to your fork of the jwt-pizza-service repository in GitHub (Settings > Secrets and variables > Actions).
| Secret | Description | Example |
|---|---|---|
| AWS_ACCOUNT | Your AWS account number | 123456789 |
| CI_IAM_ROLE | The IAM role with rights to deploy your application | github-ci |
Previously, the workflow stopped after the tests were finished and the coverage badge was updated. Now you will modify the build job of the workflow to create the distribution files used to build the Docker container.
-
Create a distribution folder that will become the Docker context. This copies all source code files and the Dockerfile. It also uses
sedto replace the temporary database credentials used during testing with the environment secrets needed for production.- name: Create dist run: | mkdir dist cp Dockerfile dist cp -r src/* dist cp *.json dist sed -i "s/root/${{ secrets.DB_USERNAME }}/g" dist/config.js sed -i "s/tempdbpassword/${{ secrets.DB_PASSWORD }}/g" dist/config.js sed -i "s/127.0.0.1/${{ secrets.DB_HOSTNAME }}/g" dist/config.js
-
Create a CI pipeline artifact from the resulting distribution build.
- name: Update distribution artifact uses: actions/upload-artifact@v4 with: name: package path: dist/
Next, add a deploy job that builds the container and pushes it to ECR.
-
Create a new GitHub Actions job underneath the
buildjob and name itdeploy. Give it permissions to access the CI pipeline token so that it can authenticate with OIDC. Add the version ID created in the build step to the job environment.deploy: runs-on: ubuntu-latest permissions: id-token: write needs: build env: version: ${{needs.build.outputs.version}}
-
As the first step, download the distribution artifact created by the previous job.
steps: - name: Download distribution artifact uses: actions/download-artifact@v4 with: name: package
-
Authenticate to AWS using OIDC. This is the same authentication step used with the frontend deployment. OIDC allows us to authenticate without storing long-lived AWS credentials in GitHub.
- name: Create OIDC token to AWS uses: aws-actions/configure-aws-credentials@v4 with: audience: sts.amazonaws.com aws-region: us-east-1 role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT }}:role/${{ secrets.CI_IAM_ROLE }}
-
Log in to Amazon ECR. We need to provide credentials to Docker so that it can push container images into the registry. This action retrieves a temporary password from ECR using the OIDC credentials obtained in the previous step.
- name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2
-
Set up Docker build and emulation. We need to build an ARM64 platform package to run on AWS Graviton processors. In order to do that on standard Linux runners, we need to emulate an ARM-based environment.
- name: Set up machine emulation uses: docker/setup-qemu-action@v3 - name: Set up Docker build uses: docker/setup-buildx-action@v3
-
Build and push the Docker container. We use the
--pushparameter to automatically push the container image to ECR once it finishes building. We also define an output variable that contains the name of the image that was pushed for future reference.- name: Build and push container image id: build-image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: 'jwt-pizza-service' run: | docker build --platform=linux/arm64 -t $ECR_REGISTRY/$ECR_REPOSITORY --push . echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:latest" >> $GITHUB_OUTPUT
You should now be able to commit and push the modified workflow script to GitHub. This will trigger the container image build and push it to ECR. Once the workflow completes, navigate to the ECR repository in the AWS console to see your image in the dashboard.
When you push a container image to ECR with a tag that already exists (like latest), ECR untags the previous image and leaves it in the repository as an "untagged" image. To clean these up and avoid exceeding the 500 MB free tier, you can create a Lifecycle policy that removes images without a tag after 1 day. You can also set up a rule that only keeps the last N images.
Deploy a container image of your JWT Pizza Service to ECR. This includes the following steps:
- Create the ECR repository.
- Modify the
github-ciIAM role andjwt-pizza-ci-deploymentpolicy so that your CI pipeline can upload to ECR. - Modify the CI pipeline workflow to build the container and push it to ECR.
- Execute the pipeline and verify the newly created image in the ECR console.
{"id":"5d8c6ed6-ec21-4ade-b51d-bcb37983a4c0", "title":"ECR upload", "type":"file-submission", "gradingCriteria":"AWS ECR showing an uploaded docker image" }
Submit a screenshot of your AWS ECR dashboard displaying your uploaded docker image.




