For this component, we will pick a framework with a minimal amount of boilerplate needed to get a service up and operational, which most people would say today is Node.js with Express. Since Node.js is based on JavaScript, which was originally based on a Java-like syntax, most people who worked on HTML should be able to figure out what the application code is be doing, but before we get there, we need to define our Node package and our dependencies, so create a new application_server directory on the same level as web_server and add the following to a file called package.json:
{
"name": "application-server",
"version": "0.0.1",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.15.4"
}
}
There's nothing really magical here; we're just using a Node package definition file to declare that we need Express as a dependency and that our npm start command should run node index.js.
Let's also make our Dockerfile now:
FROM node:8
# Make sure we are fully up to date
RUN apt-get update -q &&
apt-get dist-upgrade -y &&
apt-get clean &&
apt-get autoclean
# Container port that should get exposed
EXPOSE 8000
# Setup any variables we need
ENV SRV_PATH /usr/local/share/word_test
# Make our directory
RUN mkdir -p $SRV_PATH &&
chown node:node $SRV_PATH
WORKDIR $SRV_PATH
USER node
COPY . $SRV_PATH/
RUN npm install
CMD ["npm", "start"]
Many of these things should be very familiar here, especially with people familiar with Node. We are starting with the node:8 image, adding our application code, installing the dependencies we defined in package.json (with npm install), and then finally making sure that the app starts when run from the docker CLI.
The order here is pretty important to both avoid cache breaking and ensure proper permissions. We place things that we don't expect to change much (USER, WORKDIR, EXPOSE, mkdir, and chown) above COPY since they are much less likely to change as opposed to the application code and since they're mostly interchangeable, we arrange them in the ascending order of what we think are the least likely to change in the future in order to prevent rebuilding of layers and wasted computing power.
So far, we haven't really defined any application code, so let's see what that looks like too. First, we need an HTML view to be our landing page, and we can throw one together pretty quickly using a pug (formerly also known as jade) template. Create a views/ folder and put this in a file named index.pug located in that folder:
html
head
title Docker words
body
h1 Saved Words
form(method='POST' action='/new')
input.form-control(type='text', placeholder='New word' name='word')
button(type='submit') Save
ul
for word in words
li= word
You don't have to know much about this templating style except that it is a simple HTML page on which we will display all items from the words array passed into it during rendering, and if a new word is put in, there will be a form submitted as a POST request to the /new endpoint.