4 min read

AWS EC2 running Docker with ECR images and serving it with Nginx

AWS EC2 running Docker with ECR images and serving it with Nginx
Photo by frank mckenna / Unsplash

Hello everyone, today we will create a simple NodeJS application, create a Docker image from it, store it under ECR and use that image to serve an application with Docker.

Local Development

On my computer I created a simple Node Express application which sends basic json data as a response.

//index.js

const express = require("express");
const app = express();
const port = 3000;

app.get("/", (req, res) => {
 
 res.json({"success": true, "data": "hello world"});
});

app.listen(port, () => {
 console.log("Listening on port 3000");
});

Let’s create a Dockerfile and .dockerignore

# Dockerfile

FROM node:16

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 3000
CMD [ "node", "index.js" ]
# .dockerignore

node_modules
npm-debug.log

.dockerignore prevents your local modules and debug logs from being copied onto your Docker image.

Finally we will build the Docker image. Beware that in order to build the image you need your Docker instance up and running

docker build . -t node-docker-app

When the build is done you can check if the image is there by entering the docker images command

REPOSITORY            TAG        IMAGE ID       CREATED          SIZE
node-docker-app       latest     f79101f16617   33 seconds ago   919MB

First we will test if the image is working just fine by typing

docker run -p 3000:3000 -d node-docker-app

This will start the app and you can confirm it by typing docker ps

CONTAINER ID   IMAGE              COMMAND                  CREATED         STATUS          PORTS                              NAMES
44e119eaaa85   node-docker-app    "docker-entrypoint.s…"   8 minutes ago   Up 8 minutes    0.0.0.0:3000->3000/tcp, 8080/tcp   ding_dong

Now when you visit localhost:3000 in the browser you will see the json response.

Publishing the image to ECR

First you need to navigate to your AWS management console and create a repository on ECR

Click “Create repository” button on ECR screen
Just write your desired repository name and click create repository below

After creating your repository, you need to configure your aws credentials in order to push ECR. You can simply type aws configure and follow the steps or you can edit the files :

  • ~/.aws/credentials on Linux, macOS, or Unix
  • C:\Users\USERNAME\.aws\credentials on Windows[default]
aws_access_key_id = your_access_key_id
aws_secret_access_key = your_secret_access_key

After the configuration we need to retrieve a token and authenticate our Docker client by typing the following command aws ecr get-login-password --region eu-central-1 | docker login --username AWS --password-stdin <image_uri> you can find your image URI just like in the image below.

You will see your URI in the second column of the repositories table

After you see Login Succeeded message you can tag your image with the command docker tag node-docker-app:latest <image_uri>:<tag>. You can name the tag whatever you like but latest is just fine.

Finally to push the image you can use docker push <image_uri>:<tag>

The push refers to repository [12345678.dkr.ecr.eu-central-1.amazonaws.com/node-docker-app]
1b619aaf1ebd: Pushed 
e30ed1581a5e: Pushed 
e74cb2ef12d0: Pushed 
219742f14735: Pushed 
630cfb4ef1b4: Pushed 
baa7d1140933: Pushed 
ac3ca0266e42: Pushed 
ba72cf902ea2: Pushed 
34d4a130d4f6: Pushed 
9dfd4aa4568a: Pushed 
afa8cfa38e8c: Pushed 
7a023423c8b3: Pushed 
f0a234338d2a: Pushed 
latest: digest: sha256:f5d7ed23423424323495d29de2f1effab2cd12313123a91521825b1 size: 3050
You can see the image in the ECR management console

Running the application

First make sure that your server has Docker and aws-cli installed. If not you can navigate to https://docs.docker.com/engine/install/ and follow the instructions.

In order to pull the image we will use the command docker pull egistry/repository[:tag] . You can easily copy the uri from the ECR management dashboard and append it to docker pull

After pulling the image verify it with the command docker images

REPOSITORY            TAG       IMAGE ID         CREATED         SIZE
.../node-docker-app   latest    f7123129f33217   15 hours ago    919MB

Now run the image with the command

docker run -p 3000:3000 -d <image>

This will run the application in port 3000 and we can confirm it with running docker ps

CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                                                 NAMES
9eafd1227fe86  .../node-docker-app   "docker-entrypoint.s…"   5 seconds ago   Up 3 seconds   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp, 8080/tcp   ping_pong

We need reverse proxy server configuration for hosting our application. I use nginx in this example.

# /etc/nginx/sites-available/domain.com

server {
        listen 80;
        listen [::]:80;
        root /var/www/your_domain/html;
        index index.html index.htm index.nginx-debian.html;
        server_name domain.com www.domain.com;
        location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_pass http://127.0.0.1:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
        }
}

Finally when you visit the url from the browser you will see the application running and returning our json.


Follow me on Instagram, Facebook or Twitter if you like to keep posted about tutorials, tips and experiences from my side.

You can support me from Patreon, Github Sponsors, Ko-fi or Buy me a coffee