Build and Push a Docker image to AWS ECR with Pulumi : Part 1

CJ Hewett
4 min readNov 14, 2021

--

Pulumi’s open source infrastructure as code SDK enables you to create, deploy, and manage infrastructure on any cloud, using your favorite languages.

In this article we’ll:

  • Create a Typescript Pulumi project
  • Create a simple Node.js Docker image
  • log into AWS ECR registry
  • Use Pulumi to build and push to AWS ECR

(We’ll do this all locally, but in Part 2 of this series, we’ll use Azure DevOps Pipelines to handle all of this, to continuously build and push images to AWS ECR)

Here’s a repo of the code:

Create a Typescript Pulumi project

Assuming you have Pulumi installed, create a folder for you new Pulumi project, run the command to create said Pulumi project, and accept the defaults:

$ mkdir pulumi-ecr-example && cd pulumi-ecr-example
$ pulumi new aws-typescript

Open the index.ts file created and replace the default code that creates an S3 bucket with the following:

import * as aws from "@pulumi/aws";
import * as docker from "@pulumi/docker";
import * as pulumi from "@pulumi/pulumi";
// Create a private ECR repository.
const repo = new aws.ecr.Repository("my-repo");
// Get registry info (creds and endpoint)
const imageName = repo.repositoryUrl;
const customImage = "my-image;
const imageVersion = "v1.0.0"; // in Part 2 this will be dynamic
// Build and publish the container image.
const image = new docker.Image(customImage, {
build: "app",
imageName: pulumi.interpolate`${imageName}:${imageVersion}`,
});
// Export the base and specific version image name.
export const baseImageName = image.baseImageName;
export const fullImageName = image.imageName;

Note: In part 2 of this series, we’ll make imageVersion dynamic as part of an Azure Pipeline, so that the version number increments with each pipeline run.

Create a simple Node.js Docker image

Lets create a simple Express app with Node.js and Typescript to build into a Docker image that Pulumi can push to ECR later.

Create a folder called app within your Pulumi project.
Within this folder, run npm init and accept all the defaults.
Install the express library.
Install typescript libraries as dev dependencies.

~/pulumi_ecr_example $ mkdir app && cd app
~/pulumi_ecr_example/app $ npm init
~/p/app $ npm i express
~/p/app $ npm i -D typescript ts-node @types/node @types/express
~/p/app $ tsc --init

Add an output directory to the tsconfig.json file created:
"outDir": "./build"

Add a build command to package.json under scripts :
"build": "tsc --build"

Create an index.ts file in this app folder with the following code:

import express from 'express';// Constants
const PORT 8080;
const HOST = '0.0.0.0';
// App
const app = express();
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}');

Create a Dockerfile in the app folder with the following code:

FROM node:16# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
COPY . ./
RUN npm install
RUN npm run build
# Bundle app source
COPY ./build .
EXPOSE 8080
CMD [ "node", "index.js" ]

Create a .dockerignore file in the app folder to ignore copying files we don’t need (this is mainly only useful when building images locally).

node_modules
npm-debug.log

Feel free to test this image out locally with the following commands and visit localhost:49160 in your browser:

$ docker build . -t node-web-app
$ docker run -p 49160:8080 -d node-web-app

Login to AWS ECR registry

Make sure you have an IAM user with the AmazonEC2ContainerRegistryFullAccess AWS managed policy. Generate some Access Keys for this user and use the code below in your terminal, replacing the access key id and secret key with the ones you just generated.

export AWS_ACCESS_KEY_ID=AKIAXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Replace <region> with an AWS region, I used ap-southeast-2 , and replace aws_account_id with the ID of your AWS account you want to create the ECR repository in.

aws ecr get-login-password \
--region <region> \
| docker login \
--username AWS \
--password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com

This will allow Pulumi to push Docker images to the AWS ECR repository we create.

Use Pulumi to build and push to AWS ECR

Run pulumi up in the Pulumi project directory ( pulumi-ecr-example )to create the AWS ECR repository as well as build and push a Docker image into it.

If this is your first time using Pulumi, the CLI might get you to login first, but other than that, it should create your resources for you.

Run pulumi destroy to remove your AWS ECR repo when you’re done.

Hoped this helped,
Bonza 🤙

--

--

CJ Hewett
CJ Hewett

Written by CJ Hewett

🛹 Skateboarder. 🏂 Snowboarder. 🏄 Websurfer. I write monthly* about Cloud/DevOps/IoT. AWS Certified DevOps Engineer and Terraform Associate

No responses yet