Build and Push a Docker image to AWS ECR with Pulumi : Part 1
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 🤙