🔗Part I: Running DADI Web in a container
This is the first article in a series of articles which will take you through the containerization of three core DADI web services: Web, API, and CDN.
The first service we’ll containerize is DADI Web, our schemaless templating layer. First we’ll create a standard Web project, and then we’ll containerize it. We’ll go through some of the basics of Docker, and how we can use them alongside DADI Web.
🔗Docker
Docker is an open container platform providing developers and sysadmins with a lightweight method of process & resource isolation, the ability to package an application and all it’s dependencies into a single image, allowing greater levels of automation and portability.
The DADI suite runs on Node.js and works perfectly fine without containers, but by utilising containers, we can gain greater isolation, scalability, and enhance our automation ability as well.
If you haven’t used Docker before, then I’d recommend reading through the Docker getting started guide.
🔗Requirements
For this article I’ll be working with Docker 17.06.2-ce-mac27
and macOS Sierra
. If you don’t have Docker installed, you can get it from the Docker Community Edition website.
I’ll also be installing DADI applications with the DADI command line interface, to install that run npm install @dadi/cli -g
.
🔗Getting started
We’ll begin by creating a directory for our project and installing DADI Web using the DADI command-line interface tool. When asked to pick a template engine, select @dadi/web-dustjs
.
$ mkdir web-project
$ cd web-project
$ dadi web new
Once Web is installed, you should have a number of files & directories. By default, no configuration is necessary. Read more about DADI Web configuration.
Let’s start the application and preview the default site.
$ npm start
Now open http://127.0.0.1:3001.
You should be greeted by the default site. Cool, now let’s containerize it.
🔗Configuring Web
The first thing we need to do is configure DADI Web to work inside a container. Containers don’t by default have a local loopback so we can’t bind our port to 127.0.0.1
, instead we need to bind to 0.0.0.0
. Open up the config/config.development.json
file in your favourite text editor and change the host to 0.0.0.0
, and while we’re here, the port to 80
as well.
$ vi config/config.development.json
``````json
{
"global": {
"site": "Your site name",
"description": "An exciting beginning."
},
"globalEvents": \[
"global"
\],
"server": {
"host": "0.0.0.0",
"port": 80
},
"cluster": false,
"allowJsonView": true,
"debug": true
}
DADI Web should now be ready to run in a container.
🔗Creating a Dockerfile
Dockerfiles are like recipes for container images. Traditionally they are kept in the root of the project. Create a file named Dockerfile
and open it up in your text editor.
$ vi Dockerfile
```
FROM node:6.11
RUN mkdir /var/web
ADD . /var/web
WORKDIR /var/web
RUN npm install -q
CMD [“npm”, “start”]
First we specify a parent container image that we want to build on top of, in this case, `node:6.11`, the official Node.js image. Then we create a directory for the service and add in our project files. We set the working directory, run `npm install` and then, finally, specify the command to run on execution (`npm start`).
## Building a Docker image
Now that we have our `Dockerfile` setup, we need to build our container image. Docker has images, which are binaries generally built from Dockerfiles, and containers, which are running instances of those images.
Before we do this, let's create a `.dockerignore` file. This works a lot like a `.gitignore` file, and lets us exclude files and directories from being sent to the Docker daemon. This'll make our build process quicker and more efficient.
```bash
$ vi .dockerignore
```
node_modules
log
Now let's build our image. With Docker installed, we simply need to tell the Docker CLI to build the image from the current directory. We'll give it a tag with the `-t` flag as well so we can refer to it easier later on.
```bash
$ docker build -t web-project .
Once the build has finished, we should be able to see the image:
$ docker images | grep web-project
web-project latest 2398fc7376be About a minute ago 770MB
Great. Now we’re ready to run the container.
🔗Running the Docker container
There are two methods that we can use to run the container: in the foreground with an attached tty, or in the background detached. First, let’s test everything’s running okay by running it in the foreground. The -ti
flags tell Docker that we want to attach an interactive tty, and the --rm
flag will remove the container once we exit.
$ docker run -ti --rm web-project
> @dadi/web-boilerplate@ start /var/web
> node server.js
----------------------------
DADI Web (Repo Default)
Started 'DADI Web'
----------------------------
Server: http://0.0.0.0:80
Version: 4.0.2
Node.JS: 6.11
Environment: development
Engine: dust
API: Disabled
----------------------------
You’ll see that the application starts up and is listening, by default, on http://0.0.0.0:80
, but we can no longer access the Web service from our browser. We need to setup some port mapping. Let’s exit out of the container with ctrl-c
.
Each container connects by default to the docker0
bridge network. This is fine for us but we need to map a port on our host to port 80
on the container. The easiest way to do this is with a direct port mapping using the -p
or --publish
flag.
Let’s map port 8000
on our host to port 80
on our container.
$ docker run -ti -p 8000:80 --rm web-project
If you open up http://127.0.0.1:8000
, you should now be greeted by the default website. Great, it works! Let’s exit out of the container with ctrl-c
again and now we’ll start the container in the background, using the -d
or --detach
flag. We no longer want the container to remove-on-exit so we’ll also remove the --rm
flag. We’ll also give the container a name so that we can refer to it later on. You can also refer to containers via their long or short UUID identifiers, but names are much nicer, aren’t they?
$ docker run -d -p 8000:80 --name web-project web-project
403d5e10f5416d7f7a445fb88a851019e6dfd1335a59c35e0d8e2f83c9524c64
We can now see that the container web-project
is running.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
403d5e10f541 web-project "npm start" 22 seconds ago Up 21 seconds 0.0.0.0:8000->80/tcp web-project
We can stop and start this container with the docker stop <id/name>
and docker start <id/name>
commands, and if we want to create a fresh container with the name web-project
then we can remove it with docker rm <id/name>
.
That’s all there is to it. You now have a website running in DADI Web.
Next up, Part II: Running DADI API in a container.