Intro to Docker on AWS

Intro to Docker on AWS

Serverless containers with AWS Fargate. Running a serverless Node.js app on AWS ECS. Learn how to use Docker with key AWS services to deploy and manage container-based applications. Running Docker on AWS provides developers and admins a highly reliable, low-cost way to build, ship, and run distributed applications at any scale.

Intro to Docker on AWS AWS Fargate: Running a serverless Node.js app on AWS ECS.

Project Summary

We're going to containerize a node.js project that renders a simple static site and deploy it to an Amazon ECS Fargate cluster. I will supply all the code at https://github.com/austinloveless/Docker-on-AWS.

Installing Prerequisites

Downloading Docker Desktop.

If you are on a Mac go to https://docs.docker.com/docker-for-mac/install/ or Windows go to https://docs.docker.com/docker-for-windows/install/. Follow the installation instructions and account setup.

Installing node.js

Download node.js here.

Installing the AWS CLI

Follow the instructions here.

Project setup

Now that we have our prerequisites installed we can build our application. This project isn't going to focus on the application code, the point is to get more familiar with Docker and AWS. So you can download the Repo and change directories into the Docker-on-AWS directory.

If you wanted to run the app locally and say screw docker you can run npm install in side the Docker-on-AWS directory. Then run node app.js. To see the site running locally visit http://localhost:80.

Now that we have docker installed and the repo downloaded we can look at the Dockerfile. You can think of it as a list of instructions for docker to execute when building a container or the blueprints for the application.

FROM node:12.4-alpine

RUN mkdir /app
WORKDIR /app

COPY package.json package.json
RUN npm install && mv node_modules /node_modules

COPY . .

LABEL maintainer="Austin Loveless"

CMD node app.js

At the top we are declaring our runtime which is node:12.4-alpine. This is basically our starting point for the application. We're grabbing this base image "FROM" the official docker hub node image.

If you go to the link you can see 12.4-alpine. The "-alpine" is a much smaller base image and is recommended by docker hub "when final image size being as small as possible is desired". Our application is very small so we're going to use an alpine image.

Next in the Dockerfile we're creating an /app directory and setting our working directory within the docker container to run in /app.

After that we're going to "COPY" the package.json file to package.json on the docker container. We then install our dependencies from our node_modules. "COPY" the entire directory and run the command node app.js to start the node app within the docker container.

Using Docker

Now that we've gone over the boring details of a Dockerfile, lets actually build the thing.

So when you installed Docker Desktop it comes with a few tools. Docker Command Line, Docker Compose and Docker Notary command line.

We're going to use the Docker CLI to:

  • Build a docker image

  • Run the container locally

Building an image

The command for building an image is docker build [OPTIONS] PATH | URL | -. You can go to the docs to see all the options.

In the root directory of the application you can run docker build -t docker-on-aws .. This will tag our image as "docker-on-aws".

To verify you successfully created the image you can run docker images. Mine looks like docker-on-aws latest aa68c5e51a8e About a minute ago 82.8MB.

Running a container locally

Now we are going to run our newly created image and see docker in action. Run docker run -p 80:80 docker-on-aws. The -p is defining what port you want your application running on.

You can now visit http://localhost:80.

To see if your container is running via the CLI you can open up another terminal window and run docker container ls. To stop the image you can run docker container stop <CONTAINER ID> . Verify it stopped with docker container ls again or docker ps.

Docker on Amazon ECS

We're going to push the image we just created to Amazon ECR, Elastic Container Registry, create an ECS cluster and download the image from ECR onto the ECS cluster.

Before we can do any of that we need to create an IAM user and setup our AWS CLI.

Configuring the AWS CLI

We're going to build everything with the AWS CLI.

Go to the AWS Console and search for IAM. Then go to "Users" and click the blue button "Add User".

Create a user name like "ECS-User" and select "Programmatic Access".

Click "Next: Permissions" and select "Attach exisiting policies directly" at the top right. Then you should see "AdministratorAccess", we're keeping this simple and giving admin access.

Click "Next: Tags" and then "Next: Review", we're not going to add any tags, and "Create user".

Now you should see a success page and an "Access key ID" and a "Secret access key".

Take note of both the Access Key ID and Secret Access key. We're going to need that to configure the AWS CLI.

Open up a new terminal window and type aws configure and input the keys when prompted. Set your region as us-east-1.

Creating an ECS Cluster

To create an ECS Cluster you can run the command aws ecs create-cluster --cluster-name docker-on-aws.

We can validate that our cluster is created by running aws ecs list-clusters.

.

If you wanted to delete the cluster you can run aws ecs delete-cluster --cluster docker-on-aws

Pushing an Image to Amazon ECR

Now that the CLI is configured we can tag our docker image and upload it to ECR.

First, we need to login to ECR.

Run the command aws ecr get-login --no-include-email. The output should be docker login -u AWS -p followed by a token that is valid for 12 hours. Copy and run that command as well. This will authenticate you with Amazon ECR. If successful you should see "Login Succeeded".

Create an ECR Repository by running aws ecr create-repository --repository-name docker-on-aws/nodejs. That's the cluster name followed by the image name. Take note of the repositoryUri in the output.

We have to tag our image so we can push it up to ECR.

Run the command docker tag docker-on-aws <ACCOUNT ID>.dkr.ecr.us-east-1.amazonaws.com/docker-on-aws/nodejs. Verify you tagged it correctly with docker images.

Now push the image to your ECR repo. Run docker push <ACCOUNT ID>.dkr.ecr.us-east-1.amazonaws.com/docker-on-aws/nodejs. Verify you pushed the image with aws ecr list-images --repository-name docker-on-aws/nodejs.

Uploading a node.js app to ECS

The last few steps involve pushing our node.js app to the ECS cluster. To do that we need to create and run a task definition and a service. Before we can do that we need to create an IAM role to allow us access to ECS.

Creating an ecsTaskExecutionRole with the AWS CLI

I have created a file called task-execution-assume-role.json that we will use to create the ecsTaskExecutionRole from the CLI.

    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "ecs-tasks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

You can run aws iam create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://task-execution-assume-role.json to create the role. Take note of the "Arn" in the output.

Then run aws iam attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy to attach the "AmazonECSTaskExecutionRolePolicy".

Take the "Arn" you copied earlier and paste it into the node-task-definition.json file for the executionRoleArn.

{
    "family": "nodejs-fargate-task",
    "networkMode": "awsvpc",
    "executionRoleArn": "arn:aws:iam::xxxxx:role/ecsTaskExecutionRole",
    "containerDefinitions": [
        {
            "name": "nodejs-app",
            "image": "xxxxx.dkr.ecr.us-east-1.amazonaws.com/docker-on-aws/nodejs:latest",
            "portMappings": [
                {
                    "containerPort": 80,
                    "hostPort": 80,
                    "protocol": "tcp"
                }
            ],
            "essential": true
        }
    ],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "256",
    "memory": "512"
}

Registering an ECS Task Definition

Once your IAM role is created and you updated the node-task-definition.json file with your repositoryUri and executionRoleArn and you can register your task.

Run aws ecs register-task-definition --cli-input-json file://node-task-definition.json

Creating and ECS Service

The final step to this process is creating a service that will run our task on the ECS Cluster.

We need to create a security group with port 80 open and we need a list of public subnets for our network configuration.

To create the security group run aws ec2 create-security-group --group-name ecs-security-group --description "Security Group us-east-1 for ECS". That will output a security group ID. Take note of this ID. You can see information about the security group by running aws ec2 describe-security-groups --group-id <YOUR SG ID>.

It will show that we don't have any IpPermissions so we need to add one to allow port 80 for our node application. Run aws ec2 authorize-security-group-ingress --group-id <YOUR SG ID> --protocol tcp --port 80 --cidr 0.0.0.0/0 to add port 80.

Now we need to get a list of our public subnets and then we can create the ECS Service.

Run aws ec2 describe-subnets in the output you should see "SubnetArn" for all the subnets. At the end of that line you see "subnet-XXXXXX" take note of those subnets. Note: if you are in us-east-1 you should have 6 subnets

Finally we can create our service.

Replace the subnets and security group Id with yours and run aws ecs create-service --cluster docker-on-aws --service-name nodejs-service --task-definition nodejs-fargate-task:1 --desired-count 1 --network-configuration "awsvpcConfiguration={subnets=[ subnet-XXXXXXXXXX, subnet-XXXXXXXXXX, subnet-XXXXXXXXXX, subnet-XXXXXXXXXX, subnet-XXXXXXXXXX, subnet-XXXXXXXXXX],securityGroups=[sg-XXXXXXXXXX],assignPublicIp=ENABLED}" --launch-type "FARGATE".

Running this will create the service nodejs-service and run the task nodejs-fargate-task:1. The :1 is the revision count. When you update the task definition the revision count will go up.

Viewing your nodejs application.

Now that you have everything configured and running it's time to view the application in the browser.

To view the application we need to get the public IP address. Go to the ECS dashboard, in the AWS Console, and click on your cluster.

Then click the "tasks" tab and click your task ID.

From there you should see a network section and the "Public IP".

Paste the IP address in the browser and you can see the node application.

Bam! We have a simple node application running in an Amazon ECS cluster powered by Fargate.

If you don't want to use AWS and just want to learn how to use Docker check out my last blog

Also, I attached some links here for more examples of task definitions you could use for other applications.

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/example_task_definitions.html

https://github.com/aws-samples/aws-containers-task-definitions/blob/master/

Node.js for Beginners - Learn Node.js from Scratch (Step by Step)

Node.js for Beginners - Learn Node.js from Scratch (Step by Step)

Node.js for Beginners - Learn Node.js from Scratch (Step by Step) - Learn the basics of Node.js. This Node.js tutorial will guide you step by step so that you will learn basics and theory of every part. Learn to use Node.js like a professional. You’ll learn: Basic Of Node, Modules, NPM In Node, Event, Email, Uploading File, Advance Of Node.

Node.js for Beginners

Learn Node.js from Scratch (Step by Step)

Welcome to my course "Node.js for Beginners - Learn Node.js from Scratch". This course will guide you step by step so that you will learn basics and theory of every part. This course contain hands on example so that you can understand coding in Node.js better. If you have no previous knowledge or experience in Node.js, you will like that the course begins with Node.js basics. otherwise if you have few experience in programming in Node.js, this course can help you learn some new information . This course contain hands on practical examples without neglecting theory and basics. Learn to use Node.js like a professional. This comprehensive course will allow to work on the real world as an expert!
What you’ll learn:

  • Basic Of Node
  • Modules
  • NPM In Node
  • Event
  • Email
  • Uploading File
  • Advance Of Node

Docker Best Practices for Node Developers

Docker Best Practices for Node Developers

Welcome to the "Docker Best Practices for Node Developers"! With your basic knowledge of Docker and Node.js in hand, Docker Mastery for Node.js is a course for anyone on the Node.js path. This course will help you master them together.

Welcome to the best course on the planet for using Docker with Node.js! With your basic knowledge of Docker and Node.js in hand, Docker Mastery for Node.js is a course for anyone on the Node.js path. This course will help you master them together.

My talk on all the best of Docker for Node.js developers and DevOps dealing with Node apps. From DockerCon 2019. Get the full 9-hour training course with my coupon at http://bit.ly/365ogba

Get the source code for this talk at https://github.com/BretFisher/dockercon19

Some of the many cool things you'll do in this course
  • Build Node.js Images that auto-scan for security vulnerabilities
  • Use Docker's cutting-edge BuildKit with SSH Agents and NPM Caches for better image building
  • Use docker-compose with Visual Studio Code for full Node.js debug support
  • Use BuildKit and Multi-stage Builds to create minimal and flexible Dockerfiles
  • Build custom Node.js images using distro's like CentOS and Alpine
  • Test Docker init, tini, and Node.js as a PID 1 process in containers
  • Create Node.js apps that properly startup and respond to healthchecks
  • Develop ARM based Node.js apps with Docker Desktop, and deploy to AWS A1 Servers
  • Build graceful shutdown code into your apps for zero-downtime deploys
  • Dig into HTTP connections with orchestration, and how Proxies can help
  • Study examples of Docker Swarm and Kubernetes deployments for Node.js
  • Spend time Migrating traditional (legacy) Node.js apps into containers
  • Simplify your microservice solutions with advanced Docker Compose features
What you will learn in this course

You'll start with a quick review about getting set up with Docker, as well as Docker Compose basics. That way we're on the same page for the basics.

Then you'll jump into Node.js Dockerfile basics, that way you'll have a good Dockerfile foundation for new features we'll add throughout the course.

You'll be building on all the different things you learn from each Lecture in the course. Once you have the basics down of Compose, Dockerfile, and Docker Image, then you'll focus on nuances like how Docker and Linux control the Node process and how Docker changes that to make sure you know what options there are for starting up and shutting down Node.js and the right way to do it in different scenarios.

We'll cover advanced, newer features around making the Dockerfile the most efficient and flexible as possible using things like BuildKit and Multi-stage.

Then we'll talk about distributed computing and cloud design to ensure your Node.js apps have 12-factor design in your containers, as well as learning how to migrate old apps into this new way of doing things.

Next we cover Compose and its awesome features to get really efficient local development and test set-up using the Docker Compose command line and Docker Compose YAML file.

With all this knowledge, you'll progress to production concerns and making images production-ready.

Then we'll jump into deploying those containers and running them in production. Whether you use Docker Engine or orchestration with Kubernetes or Swarm, I've got you covered. In addition, we'll cover HTTP connections and reverse proxies for connection handling and routing with multi-container systems.

Lastly, you'll get a final, big assignment where you'll be building and deploying a large, complex solution, including multiple Node.js containers that are doing different things. You'll build Docker images, Dockerfiles, and compose files, and deploy them to a server to test. You'll need to check whether connections failover properly. You'll basically take everything you've learned and apply it in one big project!

How to Build a Node.js Application with Docker

How to Build a Node.js Application with Docker

Interested in Node.js but not sure where to start with Docker? This tutorial will walk you through creating an application image for a static website that uses the Express framework and Bootstrap. You will then build a container using that image, push it to Docker Hub, and use it to build another container, demonstrating how you can recreate and scale your application.

Introduction

This tutorial will walk you through creating an application image for a static website that uses the Express framework and Bootstrap. You will then build a container using that image, push it to Docker Hub, and use it to build another container, demonstrating how you can recreate and scale your application.

Prerequisites

To follow this tutorial, you will need:

  • A sudo user on your server or in your local environment.
  • Docker.
  • Node.js and npm.
  • A Docker Hub account.
Step 1 — Installing Your Application Dependencies

First, create a directory for your project in your non-root user’s home directory:

mkdir node_project

Navigate to this directory:

cd node_project

This will be the root directory of the project.

Next, create a package.json with your project’s dependencies:

nano package.json

Add the following information about the project to the file; be sure to replace the author information with your own name and contact details:

{
  "name": "nodejs-image-demo",
  "version": "1.0.0",
  "description": "nodejs image demo",
  "author": "Sammy the Shark <[email protected]>",
  "license": "MIT",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "nodejs",
    "bootstrap",
    "express"
  ],
  "dependencies": {
    "express": "^4.16.4"
  }
}

Install your project’s dependencies:

npm install

Step 2 — Creating the Application Files

We will create a website that offers users information about sharks.

Open app.js in the main project directory to define the project’s routes:

nano app.js

Add the following content to the file to create the Express application and Router objects, define the base directory, port, and host as variables, set the routes, and mount the router middleware along with the application’s static assets:

var express = require("express");
var app = express();
var router = express.Router();

var path = __dirname + '/views/';

// Constants
const PORT = 8080;
const HOST = '0.0.0.0';

router.use(function (req,res,next) {
  console.log("/" + req.method);
  next();
});

router.get("/",function(req,res){
  res.sendFile(path + "index.html");
});

router.get("/sharks",function(req,res){
  res.sendFile(path + "sharks.html");
});

app.use(express.static(path));
app.use("/", router);

app.listen(8080, function () {
  console.log('Example app listening on port 8080!')
})

Next, let’s add some static content to the application. Create the views directory:

mkdir views

Open index.html:

nano views/index.html

Add the following code to the file, which will import Boostrap and create a jumbotron component with a link to the more detailed sharks.html info page:

<!DOCTYPE html>
<html lang="en">
   <head>
      <title>About Sharks</title>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
      <link href="css/styles.css" rel="stylesheet">
      <link href='https://fonts.googleapis.com/css?family=Merriweather:400,700' rel='stylesheet' type='text/css'>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
   </head>
   <body>
      <nav class="navbar navbar-inverse navbar-static-top">
         <div class="container">
            <div class="navbar-header">
               <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
               <span class="sr-only">Toggle navigation</span>
               <span class="icon-bar"></span>
               <span class="icon-bar"></span>
               <span class="icon-bar"></span>
               </button>
               <a class="navbar-brand" href="#">Everything Sharks</a>
            </div>
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
               <ul class="nav navbar-nav mr-auto">
                  <li class="active"><a href="/">Home</a></li>
                  <li><a href="/sharks">Sharks</a></li>
               </ul>
            </div>
         </div>
      </nav>
      <div class="jumbotron">
         <div class="container">
            <h1>Want to Learn About Sharks?</h1>
            <p>Are you ready to learn about sharks?</p>
            <br>
            <p><a class="btn btn-primary btn-lg" href="/sharks" role="button">Get Shark Info</a></p>
         </div>
      </div>
      <div class="container">
         <div class="row">
            <div class="col-md-6">
               <h3>Not all sharks are alike</h3>
               <p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.</p>
            </div>
            <div class="col-md-6">
               <h3>Sharks are ancient</h3>
               <p>There is evidence to suggest that sharks lived up to 400 million years ago.</p>
            </div>
         </div>
      </div>
   </body>
</html>

Next, open a file called sharks.html:

nano views/sharks.html

Add the following code, which imports Bootstrap and the custom style sheet and offers users detailed information about certain sharks:

<!DOCTYPE html>
<html lang="en">
   <head>
      <title>About Sharks</title>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
      <link href="css/styles.css" rel="stylesheet">
      <link href='https://fonts.googleapis.com/css?family=Merriweather:400,700' rel='stylesheet' type='text/css'>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
   </head>
   <nav class="navbar navbar-inverse navbar-static-top">
      <div class="container">
         <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Everything Sharks</a>
         </div>
         <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav mr-auto">
               <li><a href="/">Home</a></li>
               <li class="active"><a href="/sharks">Sharks</a></li>
            </ul>
         </div>
      </div>
   </nav>
   <div class="jumbotron text-center">
      <h1>Shark Info</h1>
   </div>
   <div class="container">
      <div class="row">
         <div class="col-md-6">
            <p>
            <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.</div>
            <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">
            </p>
         </div>
         <div class="col-md-6">
            <p>
            <div class="caption">Other sharks are known to be friendly and welcoming!</div>
            <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
            </p>
         </div>
      </div>
    </div>
   </body>
</html>

Finally, create the custom CSS style sheet that you’ve linked to in index.html and sharks.html by first creating a css folder in the views directory:

mkdir views/css

Open the style sheet and add the following code, which will set the desired color and font for our pages:

.navbar {
        margin-bottom: 0;
}

body {
        background: #020A1B;
        color: #ffffff;
        font-family: 'Merriweather', sans-serif;
}
h1,
h2 {
        font-weight: bold;
}
p {
        font-size: 16px;
        color: #ffffff;
}

.jumbotron {
        background: #0048CD;
        color: white;
        text-align: center;
}
.jumbotron p {
        color: white;
        font-size: 26px;
}

.btn-primary {
        color: #fff;
        text-color: #000000;
        border-color: white;
        margin-bottom: 5px;
}

img, video, audio {
        margin-top: 20px;
        max-width: 80%;
}

div.caption: {
        float: left;
        clear: both;
}

Start the application:

npm start

Navigate your browser to http://your_server_ip:8080 or localhost:8080 if you are working locally. You will see the following landing page:

Click on the Get Shark Info button. You will see the following information page:

You now have an application up and running. When you are ready, quit the server by typing CTRL+C.

Step 3 — Writing the Dockerfile

In your project’s root directory, create the Dockerfile:

nano Dockerfile

Add the following code to the file:

~/node_project/Dockerfile

FROM node:10

RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app

WORKDIR /home/node/app

COPY package*.json ./

RUN npm install

COPY . .

COPY --chown=node:node . .

USER node

EXPOSE 8080

CMD [ "npm", "start" ]

This Dockerfile uses an alpine base image and ensures that application files are owned by the non-root node user that is provided by default by the Docker Node image.

Next, add your local node modules, npm logs, Dockerfile, and .dockerignore to your .dockerignore file:

node_modules
npm-debug.log
Dockerfile
.dockerignore

Build the application image using the docker build command:

docker build -t your_dockerhub_username/nodejs-image-demo .

The . specifies that the build context is the current directory.

Check your images:

docker images

You will see the following output:

OutputREPOSITORY                                         TAG                 IMAGE ID            CREATED             SIZE
your_dockerhub_username/nodejs-image-demo          latest              1c723fb2ef12        8 seconds ago       895MB
node                                               10                  f09e7c96b6de        17 hours ago        893MB

Run the following command to build a container using this image:

docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo 

Inspect the list of your running containers with docker ps:

docker ps

You will see the following output:

OutputCONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES
e50ad27074a7        your_dockerhub_username/nodejs-image-demo               "npm start"         8 seconds ago       Up 7 seconds        0.0.0.0:80->8080/tcp   nodejs-image-demo

With your container running, you can now visit your application by navigating your browser to http://your_server_ip or localhost. You will see your application landing page once again:

Now that you have created an image for your application, you can push it to Docker Hub for future use.

Step 4 — Using a Repository to Work with Images

The first step to pushing the image is to log in to the your Docker Hub account:

docker login -u your_dockerhub_username -p your_dockerhub_password

Logging in this way will create a ~/.docker/config.json file in your user’s home directory with your Docker Hub credentials.

Push your image up using your own username in place of <span class="highlight">your_dockerhub_username</span>:

docker push your_dockerhub_username/nodejs-image-demo

If you would like, you can test the utility of the image registry by destroying your current application container and image and rebuilding them.

First, list your running containers:

docker ps

You will see the following output:

OutputCONTAINER ID        IMAGE                                       COMMAND             CREATED             STATUS              PORTS                  NAMES
e50ad27074a7        your_dockerhub_username/nodejs-image-demo   "npm start"         3 minutes ago       Up 3 minutes        0.0.0.0:80->8080/tcp   nodejs-image-demo

Using the CONTAINER ID listed in your output, stop the running application container. Be sure to replace the highlighted ID below with your own CONTAINER ID:

docker stop e50ad27074a7

List your all of your images with the -a flag:

docker images -a

You will see the following output with the name of your image, your_dockerhub_username/nodejs-image-demo, along with the node image and the other images from your build:

OutputREPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE
your_dockerhub_username/nodejs-image-demo            latest              1c723fb2ef12        7 minutes ago       895MB
<none>                                               <none>              e039d1b9a6a0        7 minutes ago       895MB
<none>                                               <none>              dfa98908c5d1        7 minutes ago       895MB
<none>                                               <none>              b9a714435a86        7 minutes ago       895MB
<none>                                               <none>              51de3ed7e944        7 minutes ago       895MB
<none>                                               <none>              5228d6c3b480        7 minutes ago       895MB
<none>                                               <none>              833b622e5492        8 minutes ago       893MB
<none>                                               <none>              5c47cc4725f1        8 minutes ago       893MB
<none>                                               <none>              5386324d89fb        8 minutes ago       893MB
<none>                                               <none>              631661025e2d        8 minutes ago       893MB
node                                                 10                  f09e7c96b6de        17 hours ago        893MB

Remove the stopped container and all of the images, including unused or dangling images, with the following command:

docker system prune -a

With all of your images and containers deleted, you can now pull the application image from Docker Hub:

docker pull your_dockerhub_username/nodejs-image-demo

List your images once again:

docker images

You will see your application image:

OutputREPOSITORY                                     TAG                 IMAGE ID            CREATED             SIZE
your_dockerhub_username/nodejs-image-demo      latest              1c723fb2ef12        11 minutes ago      895MB

You can now rebuild your container using the command from Step 3:

docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

List your running containers:

docker ps

OutputCONTAINER ID        IMAGE                                                   COMMAND             CREATED             STATUS              PORTS                  NAMES
f6bc2f50dff6        your_dockerhub_username/nodejs-image-demo               "npm start"         4 seconds ago       Up 3 seconds        0.0.0.0:80->8080/tcp   nodejs-image-demo

Visit http://your_dockerhub_username/nodejs-image-demo or localhost once again to view your running application.