What this is
- This is a short example on how to Dockerize an ExpressJS application.
- This post also assumes you are working from a *NIX based OS such as Ubuntu 18.10
What this is not
- This is not a thorough guide on Docker, NodeJS, ExpressJS, or any other technologies that may be used.
- This does not explain or walk you through the installation process of Docker or any technologies used.
Create Directory
We need to create a directory. This is where we are going to place all of our Docker Images' files as well as our ExpressJS files.
foo@foo:~/path/to/current/directory$ mkdir node_docker_project
Create Dockerfile
CD
into the new directory and create a new file and name it Dockerfile
without any extension name.
foo@foo:~/path/to/current/directory$ cd node_docker_project
foo@foo:~/node_docker_project$ touch Dockerfile
Place the next piece of code inside of the Dockerfile
.
# Tell Docker to use the "node" Docker Image at version "10.15.3"
FROM node:10.15.3
# Create our containers WORKDIR and "node_modules" directory.
# Give the user:group "node" ownership of all files/directories in our containers WORKDIR
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
# Tell our container which directory to use as the WORKDIR
WORKDIR /home/node/app
# Copy over our local version of "package.json" and "package-lock.json" into our container
COPY package*.json ./
# Creates a user for our container
USER node
# Installs our NPM packages from the "package.json" file we moved from local in to our container
RUN npm install
# Tells our container who owns the copied content
COPY --chown=node:node . .
# Exposes the port "3000" from our container
# This is also how we can connect to our container from our host machine (the one you're reading this from now)
EXPOSE 3000
# An array of commands our container needs to run when we start it
CMD ["npm", "run", "start"]
Create app.js
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hello, world!')
})
app.listen(3000, () => console.log('Server listening @ 3000'))
Create package.json
Let's create our package.json file to hold our dependencies.
foo@foo:~/node_docker_project$ npm init -y
Then we need to install those dependencies.
foo@foo:~/node_docker_project$ npm i express
foo@foo:~/node_docker_project$ npm i --save-dev nodemon
We need Express as that is going to be the framework we are using for our server and we need Nodemon so that we can have automatic server restart by default. This will come in handy as you change files from local to the container. Without Nodemon, you would need to restart your container every time you make a change just to see the changes.
Create our Docker Image
Think of a Docker Image as the recipe and a Docker Container as the meal. In order to eat the meal we need to cook it using a recipe.
foo@foo:~/node_docker_project$ docker build -t node_project
foo@foo:~/node_docker_project$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node_project latest 3esadssa 10 Seconds Ago 908MB
foo@foo:~/node_docker_project$ docker run --name myNodeProject -v $(pwd):/home/node/app -d -p 3000:3000 node_project
foo@foo:~/node_docker_project$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
123klasdkj node_project "npm run start" 6 seconds ago
STATUS PORTS NAMES
Up 4 seconds 0.0.0.0:3000->3000/tcp myNodeProject
Check your work
Now that we've created our container and it's up and running, we are able to connect to our container via the opened port(s). In our case we opened one port at 3000.
Open your browser and navigate to http://localhost:3000
and you should be greeted with our Hello, World!
message that we place in the app.get('/' ...)
request in the app.js
file we created earlier.
Check that we can change the container files from our host machine
Go ahead and change the response text in our app.js
file from Hello, World!
to Docker is amazing!
.
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Docker is amazing!') // change this line
})
app.listen(3000, () => console.log('Server listening @ 3000'))
Back in your browser, either refresh with f5
or navigate back to http://localhost:3000
and you should see the new response.
Summary
The basics of Docker is actually pretty simple. All you need to do is:
- Get a Docker Image
- Create a Docker Container
- Connect to your container via the opened port(s)
Top comments (2)
You might have forgotten what command(s) need to be set in scripts.start. By default (npm init -y), it's not even defined. I could only assume the
npm run start
script command should benodemon node app.js
.I agree this would not work unless npm run start was defined in the package.json that was not shared.