Docker: container linking using Docker engine CLI

By | 01/04/2016

Introduction

Let’s do something fun. In this post I created a simple todo app by building an Express application that exposes a REST API. We were then consuming this REST API immediately with Jade templates. In other words, this was a full todo application including a user interface for people to add, update or delete todo items. In this post, we will try to run this entire application on Docker containers. In fact, we will have 2 containers: one will be for the frontend part, running the application code. The other container will be created to run the Mongo database. Both containers will then be linked to each other using the Docker daemon. Lets get started.

Run the web application directly on Ubuntu

As it has been a while since we created the todo application, let’s first see if all still works as expected. To do so, let’s git clone the repository and get things running. The code can be found here.

git clone https://github.com/wapptastic/Express_Todo_Mongo_API_Jade.git

You will now have a folder called ‘Express_Todo_Mongo_API_Jade.git’ on your server. Let’s start the application.

root@ubuntu-docker-1:/home/cloud-user/Express_Todo_Mongo_API_Jade# nodejs bin/www
Listening on port 3000

OK, seems like everything is running perfectly fine. Let’s see if we have something to see on our browser by going to http://:3000. See below for an example of what you should see.
express_app_1

Dockerize the webapplication

Now that we have verified that everything is working directly on the host system, we can move ahead and work on the dockerization (is this even a good word?) of the entire webapplication.

To do that, we will create a Dockerfile. Actually, pretty similar to what we discussed in this post, but just a little different also :-).

As mentioned in the introduction of this post, the idea would be to have two containers, one for the application itself and one for the database. So we will first launch a container for mongo, as we will need that to make some small changes in the database url string in the application code.

root@ubuntu-docker-1:/home/cloud-user# docker run -d -it --name=mongo-container -p 27017:27017 mongo
Unable to find image 'mongo:latest' locally
latest: Pulling from library/mongo
4ef63ae43b23: Pull complete
e419e14aaaf0: Pull complete
00bcd509441e: Pull complete
86ddd9a494e6: Pull complete
e16ca7583ca5: Pull complete
5124629510bc: Pull complete
8dd57b47c31b: Pull complete
fb048d383d05: Pull complete
6b7acfab5c16: Pull complete
be0844c69ea6: Pull complete
8d021de31b6a: Pull complete
ce524241d32b: Pull complete
df00bdf661ae: Pull complete
293f5bd4f98d: Pull complete
7cae6ee05590: Pull complete
48444bb92b81: Pull complete
b791cba50a0e: Pull complete
0b2e8afa0b8c: Pull complete
Digest: sha256:be6bbba5cf0f206632fb0e782def85214d45b896f700be370cbdac421f53441a
Status: Downloaded newer image for mongo:latest
83f2fc14664224075141938480bc2f43abb8406aa692987afb79c5a46f203273
root@ubuntu-docker-1:/home/cloud-user#

Using the above docker command will launch a docker container based on the mongo image. We can verify if it is running well using the ‘docker ps’ command.

root@ubuntu-docker-1:/home/cloud-user# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
83f2fc146642        mongo               "/entrypoint.sh mongo"   16 seconds ago      Up 6 seconds        0.0.0.0:27017->27017/tcp   mongo-container

Note: if you are following along and you find the following error message:

Error response from daemon: Cannot start container : failed to create endpoint mongo-container on network bridge: Error starting userland proxy: listen tcp 0.0.0.0:27017: bind: address already in use

this likely means that you already have Mongo running on your host system (and you did indeed if you are following along => see the first part of this tutorial). For now, I would suggest just killing that mongod process using ‘ps -aux |grep mongo’ and then ‘kill

So now we have a mongo container up and running, let’s move ahead with the application part now. The tricky part if the fact that the application code right now still contains a reference to a mongo database running on localhost. To see this with your own eyes, go to the application folder and then check out config/database.js

module.exports = {
        url : 'mongodb://localhost/todo'
}

We will need to change to url to point to the IP address of the container where mongo is running on. Luckily, Docker is making this pretty easy for us. We gave our container a name ‘mongo-container’. It appears that Docker is automatically putting this into the /etc/hosts file of the container, so we can use it in our application code. See below.

module.exports = {
	url : 'mongodb://mongo-container:27017/todo'
}

OK, now let’s continue with the Dockerfile. Actually, it will be pretty similar to the one we already used in this post. I added it below for your convenience:

root@ubuntu-docker-1:/home/cloud-user/Express_Todo_Mongo_API_Jade# cat Dockerfile
FROM ubuntu:14.04

RUN apt-get update
RUN apt-get -y install build-essential
RUN apt-get -y install nodejs
RUN apt-get -y install npm
RUN apt-get -y install git
RUN apt-get -y install git-core

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install

# Bundle app source
COPY . /usr/src/app

EXPOSE 3000

CMD ["nodejs", "/usr/src/app/bin/www"]

Note that this Dockerfile on takes care of the application containers as we already have a mongo container up and running. We will go ahead and build this container in the next step:

root@ubuntu-docker-1:/home/cloud-user/Express_Todo_Mongo_API_Jade# docker build -t wiwa1978/express-app .

So we should now perform a ‘docker run’ command while keeping in mind we also need to link both containers to each other. Again, Docker makes things rather easy for us.

root@ubuntu-docker-1:/home/cloud-user/Express_Todo_Mongo_API_Jade# docker run -d -it --name=express-app -p 3000:3000 --link mongo-container wiwa1978/express-app

The above command will link both containers to each other. More in particular, we now have a container running the application part (the frontend) on port 3000 (while doing a mapping for port 3000 on our host to port 3000 inside our container) which has the name ‘express-app’ and at the same time, we have been creating a link between the container referenced with the name ‘mongo-container’ and the container referenced with the name ‘wiwa1978/express-app’. That should do the trick. Let’s see if everything is working as expected:

root@ubuntu-docker-1:/home/cloud-user/Express_Todo_Mongo_API_Jade# docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                      NAMES
229096b071d3        wiwa1978/express-app   "nodejs /usr/src/app/"   30 seconds ago      Up 30 seconds       0.0.0.0:3000->3000/tcp     express-app
83f2fc146642        mongo                  "/entrypoint.sh mongo"   18 minutes ago      Up 18 minutes       0.0.0.0:27017->27017/tcp   mongo-container
root@ubuntu-docker-1:/home/cloud-user/Express_Todo_Mongo_API_Jade# docker images
REPOSITORY             TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
wiwa1978/express-app   latest              0ef76aef904a        About a minute ago   452.8 MB
ubuntu                 14.04               c88b54fedc4f        12 hours ago         188 MB
mongo                  latest              0b2e8afa0b8c        9 days ago           309.8 MB

The above commands show we indeed have two containers up and running. So if all went well, we should be able to open our browser and go to http://:3000. Below are some screenshots that should be rather familiar.

express_app_2

Note: you can also log into your docker container and it should display some logs from our application:

root@ubuntu-docker-1:/home/cloud-user/Express_Todo_Mongo_API_Jade# docker logs 229096b071d3
Listening on port 3000
Showing all todo items
GET /todos 304 278.525 ms - -
Showing all todo items
GET /todos 304 62.665 ms - -
GET / 304 6.262 ms - -
GET /todos 304 33.639 ms - -

That’s it for today. Hope you learned something new and hope to see you back later!

Leave a Reply

Your email address will not be published. Required fields are marked *