cowsay-express
cowsay-express copied to clipboard
Learn how to Dockerise a Node application. Run it in the cloud and then run it locally in prod and dev modes. And, most importantly, have fun! ☕
Docker for WebDevs Workshop
Welcome, this is a tutorial on Docker-ising a WebApp.
If you're curious about the tutorial's context, check out the presentation slides.

The tutorial consists of 5 main parts:
- Running the example app locally
- Create the Dockerfile
- Deploying the app to the cloud and have it built using the Dockerfile
- Running the example app locally in a Docker container (Production Mode)
- Running the example app in a Docker container listening for code changes (Development Mode)
1. Running the example app locally
1.1. Clone the repo
git clone https://github.com/cassilup/express-cowsay
1.2. Since this is a node.js app, we need to grab the needed packages from npm
npm install
If all went well, you now have a new folder named node_modules/.
1.3. Start the app by running:
node index.js
You should see the following in your terminal:

1.4. Open http://localhost:8080 in your browser.
You should see the following:

1.5. Stop the app and clean the project
We want to reset the project to its original state, without any npm packages installed. That is because we will start the server inside a Docker container and the node_modules/ folder will be created inside the container, without our
First, we will stop the server by hitting CTRL+C.
Secondly, we will delete the node_modules/. We will later generate it from inside of our Docker container.
2. Create the Dockerfile
This is the magical part. Dockerfile is like a recipe. It builds our project environment based on the ingredients (instructions) we specify here.
Here is the Dockerfile that we'll be using for this tutorial:
FROM node:boron
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app
RUN npm install
COPY . /usr/src/app
EXPOSE 8080
CMD [ "npm", "start" ]
Each step in the Dockerfile generates an intermediate container.
This is the strategy that allows Docker to be fast.
Few Dockerfile keywords that you should be aware of:
FROM: Image that our container will be built from. (Note: you can build/package/deploy your own images.)RUN: Execute a command in the bash of our Linux container.WORKDIR: Equivalent ofcd <path/to/folder>COPY: Copies files from the host machine (your native OS) to the container's filesystem.EXPOSE: Opens up a port so that we can access our container.CMD: Special command that is run every time the container is started.
For more info about possible keywords, click here.
3. Deploying the app to the cloud and have it built using the Dockerfile
3.1. Install now.sh
Follow the official instructions.
3.2. Run the following command
now --docker
Notice the new URL for our deployed app in the command line:

3.3. Access the app's URL
Accessing that URL returns information about our deployment:

Notice that the local terminal mirrors the same logs we can see in the browser:

Once the deployment is ready, we can see our app running from a Docker container in the app's URL:

Awesome!
4. Running the example app locally in a Docker container (Production Mode)
Note: Make sure you have Docker for Mac/Win installed.
For more information on the VM used by Docker, click here.
Steps to generate a Docker image out of our Dockerfile:
4.1. Build the project into a Docker image
docker build -t cowsay-express .
Notice the intermediate containers being created.

4.2. Start a container from the image we just built
docker run -p 10080:8080 -d cowsay-express

4.3. Navigate to http://localhost:10080 and voilá!

Very Important: Notice that there's no node_modules/ in our code. This means that the app is actually running in the Docker container.
4.4. Access the internal folder structure of the container by opening a shell inside it
docker exec -it <container id> sh
Now list the contents of the app's folder and notice the node_modules/ folder being present:
ls -l /usr/src/app

Other useful commands:
docker images—> lists all images on systemdocker ps—> lists running containers on systemdocker ps -a—> lists all containersdocker stop <container id>-> stop a containerdocker rm <container id>-> remove a containerdocker image rm <image name>-> remove an image
For more info, click here
5. Running the example app in a Docker container listening for code changes (Development Mode)
By default, node doesn't "listen" for code changes. So when you make code changes, you need to restart the node process in order to have it take changes into account.
nodemon is a tool that fixes that and is commonly used in development of node projects.
In order to be able to develop in our own host OS and have the code changes reflected inside and served through the Docker container, we have to:
- Install
nodemoninto the container at build time (by adding it to ourDockerfile). - Mount the source of the app as a shared folder from our host OS to the
Dockercontainer (by usingdocker-compose).
The steps we need to take are:
5.1. Create a new file docker-compose.yml:
version: "2"
services:
web:
build: .
command: nodemon --inspect=5858
volumes:
- .:/usr/src/app
- /usr/src/app/node_modules
ports:
- "10080:8080"
- "5858:5858"
Through this file, we're telling Docker to mount our current folder as a shared folder in the container's filesystem.
Mounting our current folder enables us to make changes and have them be served directly from the container as they occur.
Note: We need the - /usr/src/app/node_modules line in order to have the node_modules/ folder persisted as intermediate containers are being built.
5.2. Install nodemon through Dockerfile
Add the following line to the Dockerfile:
FROM node:boron
RUN npm i -g nodemon # <-- New Line
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app
RUN npm install
COPY . /usr/src/app
EXPOSE 8080
CMD [ "npm", "start" ]
5.3. Run docker-compose up in order to bring up the project with the mounted folder and nodemon listening for changes:

5.4. Navigate to http://localhost:10080

5.5. Make a change in the code and reload http://localhost:10080

Bonus: You can debug the Node app directly in the browser.
Congrats. You're now a Docker guru (almost). 😎
Thanks for reading so far down! If you find any inconsistencies, please be sure to let me know. I hope this tutorial got you on the right track, Docker-wise.
If you enjoyed this, drop me a line! I'd love to hear from you.