Skip to content

Instantly share code, notes, and snippets.

@potikanond
Last active January 12, 2023 12:30
Show Gist options
  • Save potikanond/eeaea3b2968b37257ee5af3397b2718b to your computer and use it in GitHub Desktop.
Save potikanond/eeaea3b2968b37257ee5af3397b2718b to your computer and use it in GitHub Desktop.
Example#3.2: build a simple Node.js app image

Example#3.2: build a simple Node.js app image

Clone a Node.js application from GitHub

First, clone from the following URL to Ubuntu VM:

https://github.com/potikanond/docker-node-sample2

On Ubuntu VM run the following command:

$ git clone https://github.com/potikanond/docker-node-sample2

This will clone the application from GitHub to docker-node-sample2 directory.

Create a Dockerfile inside the Node.js app directory

First, create a Dockerfile inside the docker-node-sample2 directory.

Dockerfile:

# Instructions from the app developer
# - you should use the 'node' official image, with the alpine 6.x branch
FROM node:6-alpine
# - this app listens on port 3000, but the container should launch on port 8080
  #  so it will respond to http://localhost:80 on your computer
EXPOSE 3000
# - then it should use alpine package manager to install tini: 'apk add --update tini'
RUN apk add --update tini
# - then it should create directory /usr/src/app for app files with 'mkdir -p /usr/src/app'
RUN mkdir -p /usr/src/app
# - Node uses a "package manager", so it needs to copy in package.json file
WORKDIR /usr/src/app
COPY package.json package.json
# - then it needs to run 'npm install' to install dependencies from that file
# - to keep it clean and small, run 'npm cache clean --force' after above
RUN npm install && npm cache clean
# - then it needs to copy in all files from current directory
COPY . .
# - then it needs to start container with command '/sbin/tini -- node ./bin/www'
CMD [ "/sbin/tini", "--", "node", "./bin/www" ]
# - in the end you should be using FROM, RUN, WORKDIR, COPY, EXPOSE, and CMD commands

For more detail on dockerizing a Node.js web app, see the following link: https://nodejs.org/en/docs/guides/nodejs-docker-webapp/

Create .dockerignore file in the same directory as the Dockerfile

.dockerignore:

node_modules
npm-debug.log

This will prevent local_modules and debug logs from being copied onto your Docker image and overwriting modules installed within your image.

Building your Node.js docker image

Use the docker image build ... command to build and tag image.

$ docker image build -t cpe405/example32 .
Sending build context to Docker daemon  441.9kB
Step 1/9 : FROM node:6-alpine
 ---> bd44e728e149
Step 2/9 : EXPOSE 3000
 ---> Running in 92771260a610
Removing intermediate container 92771260a610
 ---> 44f47b1f6c53
Step 3/9 : RUN apk add --update tini
 ---> Running in ffafd075394b
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz
(1/1) Installing tini (0.9.0-r1)
Executing busybox-1.24.2-r14.trigger
OK: 6 MiB in 14 packages
Removing intermediate container ffafd075394b
 ---> fb979adbbed9
Step 4/9 : RUN mkdir -p /usr/src/app
 ---> Running in 660d7418de0b
Removing intermediate container 660d7418de0b
 ---> 09865e1827cc
Step 5/9 : WORKDIR /usr/src/app
 ---> Running in d6410224d07c
Removing intermediate container d6410224d07c
 ---> 84b7b6f1f717
Step 6/9 : COPY package.json package.json
 ---> a69ce9fd01a3
Step 7/9 : RUN npm install && npm cache clean
 ---> Running in 83a78d40e7d7
dockerfile-assignment-1@0.0.0 /usr/src/app
+-- body-parser@1.16.1
| +-- bytes@2.4.0
| +-- content-type@1.0.4
| +-- debug@2.6.1
| +-- depd@1.1.2
| +-- http-errors@1.5.1
| | +-- inherits@2.0.3
| | +-- setprototypeof@1.0.2
| | `-- statuses@1.5.0
| +-- iconv-lite@0.4.15
| +-- on-finished@2.3.0
| | `-- ee-first@1.1.1
| +-- qs@6.2.1
| +-- raw-body@2.2.0
| | `-- unpipe@1.0.0
| `-- type-is@1.6.16
|   +-- media-typer@0.3.0
|   `-- mime-types@2.1.20
|     `-- mime-db@1.36.0
+-- cookie-parser@1.4.3
| +-- cookie@0.3.1
| `-- cookie-signature@1.0.6
+-- debug@2.6.9
| `-- ms@2.0.0
+-- express@4.14.1
| +-- accepts@1.3.5
| | `-- negotiator@0.6.1
| +-- array-flatten@1.1.1
| +-- content-disposition@0.5.2
| +-- debug@2.2.0
| | `-- ms@0.7.1
| +-- encodeurl@1.0.2
| +-- escape-html@1.0.3
| +-- etag@1.7.0
| +-- finalhandler@0.5.1
| | +-- debug@2.2.0
| | | `-- ms@0.7.1
| | `-- statuses@1.3.1
| +-- fresh@0.3.0
| +-- merge-descriptors@1.0.1
| +-- methods@1.1.2
| +-- parseurl@1.3.2
| +-- path-to-regexp@0.1.7
| +-- proxy-addr@1.1.5
| | +-- forwarded@0.1.2
| | `-- ipaddr.js@1.4.0
| +-- qs@6.2.0
| +-- range-parser@1.2.0
| +-- send@0.14.2
| | +-- debug@2.2.0
| | | `-- ms@0.7.1
| | +-- destroy@1.0.4
| | +-- mime@1.3.4
| | `-- statuses@1.3.1
| +-- serve-static@1.11.2
| +-- utils-merge@1.0.0
| `-- vary@1.1.2
+-- hbs@4.0.1
| +-- handlebars@4.0.5
| | +-- async@1.5.2
| | +-- optimist@0.6.1
| | | +-- minimist@0.0.10
| | | `-- wordwrap@0.0.3
| | +-- source-map@0.4.4
| | | `-- amdefine@1.0.1
| | `-- uglify-js@2.8.29
| |   +-- source-map@0.5.7
| |   +-- uglify-to-browserify@1.0.2
| |   `-- yargs@3.10.0
| |     +-- camelcase@1.2.1
| |     +-- cliui@2.1.0
| |     | +-- center-align@0.1.3
| |     | | +-- align-text@0.1.4
| |     | | | +-- kind-of@3.2.2
| |     | | | | `-- is-buffer@1.1.6
| |     | | | +-- longest@1.0.1
| |     | | | `-- repeat-string@1.6.1
| |     | | `-- lazy-cache@1.0.4
| |     | +-- right-align@0.1.3
| |     | `-- wordwrap@0.0.2
| |     +-- decamelize@1.2.0
| |     `-- window-size@0.1.0
| `-- walk@2.3.9
|   `-- foreachasync@3.0.0
+-- morgan@1.7.0
| +-- basic-auth@1.0.4
| +-- debug@2.2.0
| | `-- ms@0.7.1
| `-- on-headers@1.0.1
`-- serve-favicon@2.3.2
  `-- ms@0.7.2

Removing intermediate container 83a78d40e7d7
 ---> 18949fa31b43
Step 8/9 : COPY . .
 ---> 994e49aedc4a
Step 9/9 : CMD [ "/sbin/tini", "--", "node", "./bin/www" ]
 ---> Running in 84db1bfb7480
Removing intermediate container 84db1bfb7480
 ---> ad4794043057
Successfully built ad4794043057
Successfully tagged cpe405/example32:latest

Check docker image list after

# docker image ls
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
cpe405/example32               latest              ad4794043057        2 minutes ago       63MB
...

Start the node-sample2 app in a new container

Now we start a new container with --rm option so that after exit the container will be removed automatically. Note: we start the container without -d option

We can access the application with the URL: http://localhost:8080.

$ docker container run -p 8080:3000 --rm cpe405/example32
GET / 200 161.035 ms - 290
GET /stylesheets/style.css 200 42.941 ms - 111
GET /images/picard.gif 200 51.667 ms - 417700
GET /favicon.ico 404 20.711 ms - 970
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment