AWS Project 8: Deploying a Node.js application to AWS using Docker
Task : Deploy a Node.js application to AWS using Docker and ECS
What did I use to build this environment?
- Visual Studio Code platform
- AWS Console
- AWS CLI
- Docker
What was built?
- Docker Image
- ECR
- ECS Cluster
- ECS Task Definition
- ECS Service
Imagine that you’re working for a Software Company that runs their application in a traditional virtual machine based on AWS using EC2 Services.
After a year running this architecture, the technical leadership team decide to explore other options to re-platform this application to more cost-effective solution using Docker Containers on AWS.
However, there is one problem: Their Development Team does not know how to run Docker Containers On AWS, so they engaged you to work on this Proof of Concept(PoC).
Now the task is to help the team to bring up a Node JS Application on AWS using Containers:
IMPLEMENTATION:
The flow of execution:
1. Create a simple web application in Node.js
2. Create a Docker file
3. Build a Docker image
4. Create Registry (ECR) in AWS and upload the app image to it
5. Create ECS Cluster
6. Create a new ECS Task Definition
7. Create a new ECS Service and deploy it
8. Testing the app on public IP , port 8080
In the first part of this guide I will create a simple web application in Node.js, then I will build a Docker image for that application, and lastly I will instantiate a container from that image.
Docker allows you to package an application with its environment and all of its dependencies into a “box”, called a container. Usually, a container consists of an application running in a stripped-to-basics version of a Linux operating system. An image is the blueprint for a container, a container is a running instance of an image.
1. Create a simple web application in Node.js
First, in VS Code I created a new directory where all the files would live. In this directory I created a package.json
file that describes the app and its dependencies:
Create the app folder name : mkdir nodejs-app
create a
package.json
file: cd nodejs-app /touchpackage.json
# package.json file
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "First Last <first.last@example.com>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.2"
}
}
Then, I created a server.js
file that defines the web app using the Express.js framework:
create a
server.js
file: cd nodejs-app /touchserver.js
# server.js file
'use strict';const express = require('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}`);
});
2. Create a Dockerfile
Here, I am building the Docker image using the official Node.js image from Dockerhub (a repository for base images).
- Start our Dockerfile with a
FROM
statement. This is where you specify your base image. - The
RUN
statement will allow us to execute a command for anything you want to do. We created a subdirectory/usr/src/app
that will hold our application code within the docker image. WORKDIR
instruction establishes the subdirectory we created as the working directory for anyRUN
,CMD
,ENTRYPOINT
,COPY
andADD
instructions that follow it in theDockerfile
./usr/src/app
is our working directory.COPY
lets us copy files from a source to a destination. We copied the contents of our node application code (server.js
andpackage.json
) from our current directory to the working directory in our docker image.- The
EXPOSE
instruction informs Docker that the container listens on the specified network ports at runtime. We specified port 3000. - Last but not least, the
CMD
statement specifies the command to start our application. This tells Docker how to run your application. Here we usenode server.js
which is typically how files are run in Node.js.
FROM node:18
# 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 --omit=dev
# Bundle app source
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
.dockerignore file
Create a .dockerignore
file in the same directory as the Dockerfile
with following content:
node_modules
npm-debug.log
This will prevent my local modules and debug logs from being copied onto my Docker image and possibly overwriting modules installed within the image.
3. Build a docker image
cd nodejs-app
ls
Dockerfile package.json server.js
docker build . -t nodejs
The docker image was built. To see previously created images, run:
docker images
4. Create Registry (ECR) in AWS and upload the app image to it
Amazon Elastic Container Registry (ECR) is a fully-managed Docker container registry that makes it easy for developers to store, manage, and deploy Docker container images. Amazon ECR is integrated with Amazon Elastic Container Service (ECS), simplifying your development to production workflow.
The keyword “Elastic” means you can scale the capacity or reduce it as desired.
To create the ECR I used AWC CLI
First create the ECR with this command below:
aws ecr create-repository --repository-name nodejs-app
Then to push my image to the ECR I just created I used to following commands:
1. aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/$ your AWS account ID
# Note: If you receive an error using the AWS CLI, make sure that you have the latest version of the AWS CLI and Docker installed.
# Build your Docker image using the following command. For information on building a Docker file from scratch see the instructions here . You can skip this step if your image is already built:
2. docker build -t nodejs .
# After the build completes, tag your image so you can push the image to this repository:
3. docker tag nodejs:latest public.ecr.aws/$ your AWS account ID/nodejs:latest
# Run the following command to push this image to your newly created AWS repository:
4. docker push public.ecr.aws/$ your AWS account ID/nodejs:latest
You can see the image is pulled on my Amazon Elastic Container Registry
5. Create ECS Cluster
Now its time to deployed the app inside the cluster
6. Create a new ECS Task Definition
From Task Definitions in the ECS dashboard, press on the Create new Task Definition (ECS) button:
name:nodejs
port : 8080
7. Create a new ECS Service and deploy it
On ECS console, Click to Deploy, create new service, Name: nodejs, create a new security group nodejs-sg allow custom TCP port 8080 source anywhere
Name: nodejs-sg | Custom TCP | Port Range: 8080 | Source: Anywhere
8. Testing the app on public IP , port 8080
It’s working !!!
Now A Node.js application is dockerize and running Amazon Web Service (AWS) using Amazon ECR (Elastic Container Registry) and ECS (Elastic container service).