Local microservice containers

Deploying website and microservice containers to production.

This is one of 3 blog posts

In the previous blog post Microservices with fuge I have built a Seneca microservice and tested it locally using the new tool Fuge. It is time to build the Docker containers and deploy it to the cloud.

If you need a quick intro to Docker for a single Nodejs project, take a look at this gist.

Building and running Docker containers

The fuge tool creates docker-compose.yml file that gives the blueprints for several Docker containers to the docker compose tool. (You do need to run fuge generate system command for this, not just a single service)

fuge/compose-dev.yml
1
2
3
4
5
6
frontend:
build: ../site/
container_name: site
addition:
build: ../addition/
container_name: addition

Let us build our docker containers from these directions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ docker-compose -f compose-dev.yml build
Building addition
Step 1 : FROM node
---> 3a18b51160d3
Step 2 : ADD ./package.json /
---> Using cache
---> a3be2199d89a
Step 3 : RUN npm install
...
Building frontend
Step 1 : FROM node
---> 3a18b51160d3
...
Successfully built c8078b269fd1

The tool went into each build folder, found Dockerfile and built an image. Now let us run the images.

Running Docker images locally

In addition to fuge/compose-dev.yml file, the fuge tool generates docker-compose.yml file that tells each container the IP and port numbers of the other services (and their Docker mappings). Basically, it is a map that allows each service to find other services across Docker boundaries.

Since the containers will be running in a virtual box (at least on Mac OSX), we need to tell the containers what the local IP of the virtual box is. Let us look it up

1
2
3
$ docker-machine ls
NAME ACTIVE URL STATE URL DOCKER
default - virtualbox Running tcp://192.168.99.100:2376 v1.9.1

If we start our Docker containers, they will be hosted at IP 192.168.99.100. Open the fuge/docker-compose.yml file and copy / paste the above IP as PROXY_HOST in several places (these lines are commented out initially).

fuge/docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
frontend:
build: ../site/
container_name: site
environment:
- SERVICE_HOST=0.0.0.0
- SERVICE_PORT=20000
- PROXY_HOST=192.168.99.100
- frontend_PORT=10000
- addition_PORT=10001
ports:
- 10000:20000
addition:
build: ../addition/
container_name: addition
environment:
- SERVICE_HOST=0.0.0.0
- SERVICE_PORT=20001
- PROXY_HOST=192.168.99.100
- frontend_PORT=10000
- addition_PORT=10001
ports:
- 10001:20001

Note: I am note sure if we need to build the containers (previous step) AFTER we set the PROXY_HOST. Seems the order listed makes more sense, but I might be mistaken.

Now let us run the containers locally.

Run the containers locally

Start the containers using docker-machine -f fuge/compose-dev.yml up and see each service start and run in its own container

1
2
3
4
5
6
7
8
$ docker-compose -f docker-compose.yml up
Starting addition
Starting service2
Starting service1
Recreating site
Attaching to addition, service2, service1, site
addition | INFO hello Seneca/0.7.2/d2emecf4ases/1454559948825/6/-
addition | INFO listen {host:0.0.0.0,port:20003}

Notice that the site and the service run isolated: each thinks it runs at host 0.0.0.0 and port 2000x, but our website knows which ports are mapped where. Thus the site's api when using the Seneca client maps correctly

site/api/services.js
1
2
3
4
5
seneca.client({
host: process.env.PROXY_HOST,
port: process.env.addition_PORT,
pin: {role: 'addition'}
});

which produces the following log output (notice the true proxy host and the mapped port)

1
site    INFO client  {host:192.168.99.100,port:10003,pin:{role:addition}}

Then open the browser, pointing it at the PROXY_HOST:frontend_PORT url, in our case it will http://192.168.99.100:10000/. Click "Add" button and observe the result.

local docker

Let us deploy our microservices and site to the cloud, but this will require its own blog post.

Conclusion

To develop the site and the services locally, use the following commands

  1. fuge run fuge/compose-dev.yml
  2. docker-machine -f fuge/compose-dev.yml build
  3. docker-machine -f fuge/compose-dev.yml up