5 min read
Mar 9, 2019
This is Part I of a two part series of how to build and deploy Dockerized applications. In this article you will see a breakdown of the Dockerfile and how to use Docker Compose on a simple application. We will run the app locally and in Part II, we'll stand it up in the cloud using AWS EC2.
It assumes that you have Docker installed on your machine, if you don't check here. You can follow this tutorial with only Docker installed but for the first step you will need Node.js. If you don't have it get it here. You also should know a little about Git and Github so that you can clone the repo.
I have created a repo of this app on Github. Clone it from here and follow along!
Now that we got that stuff out of the way, let's get started!
My folder structure looks like this:
/app
docker.compose.yml
Dockerfile
index.html
package.json
server.js
README.md
If you have cloned the repo, you can simply run the command npm i && npm start
from the root directory and then in your browser visithttp://localhost:8080
and see the app run using Node.
You should see this in your browser:
This is a super simple node app — I can't stress that enough. Not much going on here, just a simple express server that serves up an HTML file. There is also one api
type route /doc
.
Now that we know that the app works, let's get to the fun stuff with Docker.
Stop the app using cmd + c or control + c
.
Now we can start the app in a container using Docker by running in our terminal, the command docker run node-test
. We will run it from the root directory as well. In your terminal you should see something like this:
Return to the browser and you should see the same HTML vialocalhost:8080
as you did before. Excellent!
Let's talk about what is happening.
First, let's look at our Dockerfile
. This is the file that Docker will use to build our image automatically.
Our Dockerfile is really simple but let's start from the top, as does Docker.
FROM node:11.3.0
RUN mkdir -p /app
WORKDIR /app
COPY . /app
RUN npm i
ENTRYPOINT [ "npm" ]
CMD ["start"]
Let's look at it line by line:
FROM node:11.3.0
The first line is our base image that we will build upon. FROM
will get that image from the Docker registry. It could be any image but we'll use the official image from Node. It has everything that we will need to build on for this service.
RUN mkdir -p /app
The RUN
command will allow us to run Linux commands on this image. In this step, we are telling it to make a new folder and if that folder already exist we will override/overwrite it and create the folder anyway using the -p
flag. Click here for a Linux command cheat sheet — very helpful.
WORKDIR /app
We will assign a working directory of /app
using WORKDIR
. Any command that we run after this will be ran in the /app
directory.
COPY . /app
Next, we COPY
everything (file/directories) from the place .
(root) that we first ran the docker run node-test
command. We use this command to copy everything to the /app
directory of our image.
RUN npm i
RUN
executes the command npm i
to install the necessary dependencies.
ENTRYPOINT [ "npm" ]
Create an ENTRYPOINT
that will “allow you to configure a container that will run as an executable”. For example, we could run docker run node-test
update and update the version of NPM in our container.
CMD ["start"]
Lastly, we set CMD
which is what will follow the ENTRYPOINT
. So now if we run docker run node-test
the command that will be ran inside the container is npm start
.
Magic 🎉 our app is being served on port 8080
!
As an added, I have created a docker-compose.yml
file. Docker-compose is necessary when you have a multi-container app but can work fine with single container apps as well. Let's take a look at a very simple docker-compose.yml
.
version: '3'
services:
node-test:
build:
context: .
image: node-test
container_name: node-test
ports:
- "8080:8080"
The first line of this YAML file is specifying the version
of the file format. At the time of this post the current version 3.7 but we only need to specify 3 for this post. See more about the versions here.
Next we begin to define our various services
. Our first and only service will be node-test
.
Next, we setup our build
. We will give it a context
which we have set to be the root, indicated by the dot. Context is about telling Docker where to find the Dockerfile for this service.
By specifying an image
, we tell Docker Compose to name this image node-test
.
The container_name
is to give our container a name of our choosing. If we don't specify it here one will be generated for us.
Lastly, we will indicate our port bindings. Here we can make as many bindings as we want but for the purpose of this we'll only use “8080:8080”
. This is the short form of assigning port bindings the long form can be seen here. The first 8080
is for the host machine (your machine). That represents the port you can visit to see your app in the browser. The second port is the port that the app runs on inside of the container. Play around with it by changing the numbers to get a better understanding of how it works. Just make sure to keep you port numbers above 60
as suggested by the docs.
And that's about all there is to it! Granted, this is a simple application and there are many other options/steps that are available to us when using Docker but this is a great starting point.
In my next post, that will be available on March 17, 2019, I will be demonstrating how to deploy this app on AWS using EC2.
Please clap, comment, and follow! And contact me for help if you need it concerning Docker or any of the technologies in this post or my others. I will be happy to consult.