Docker Basics- How to connect containers using docker networks.
Tags: docker, networking, node
Published: 2017-11-16 12:24:42

---
title: Docker Basics- How to connect containers using docker networks.
published: true
description: Connecting docker containers for decentralized architecture.
tags: docker, networking, node
cover_image: https://images.unsplash.com/photo-1494412519320-aa613dfb7738?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80
---

# Introduction
So docker is a wonderful tool, easily extensible to replicate almost any environment across multiple setups, There's a lot of buzz words out there about docker and what its capable of, but in this session, we are going to review building decentralized architecture using docker and getting functional with it. A typical setup for this play would be separating two different modules of the same application so that they can communicate separately, a fun fact is that with docker running the show, they could both be connected to the same data source using docker networking.

# Pre-requisites
So here's what we'll presume in this article. 
- You have prior experience with docker. i.e [deploying a simple container](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-getting-started)
- You understand what docker is.

For the sake of clarity, we are still going to define some docker concepts.

##  What is Docker

> Docker is a technology-focused on building container-based architecture for improving the developer's workflow.

> A container image is a lightweight, stand-alone, executable package of a piece of software that includes everything needed to run it: code, runtime, system tools, system libraries, settings. Available for both Linux and Windows-based apps, containerized software will always run the same, regardless of the environment

## Setting up Docker and Docker Compose
Docker being a widely used tool has a lot of resources related to getting started, without much ado, I'd highlight a few resource that can help you get started.  

For the Linux developers in the house apart from the docs from docker's site, these resources ensure Debian based users get the gist easy and quickly.
- For Linux users (Debian guys in particular (ubuntu, Debian, kali, etc)) [Click here](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04)
- For Windows Users, we know you guys use installations files a lot, so the docker docs provide good leverage [click here](https://docs.docker.com/docker-for-windows/install/)
- For Mac users, The documentation also did justice to this and here you go [click here](https://docs.docker.com/docker-for-mac/install/)

After installing docker you'll need docker-compose, Docker for Mac and Docker for Windows already have this installed, so you are good to go, for the Linux users in the house, we have work to do.

1. Run this command to download the latest version of docker-compose

```bash
sudo curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose'
```
if you have problems installing with curl [click here](https://docs.docker.com/compose/install/#alternative-install-options)

2. Apply executable permissions to the binary
```
$ sudo chmod +x /usr/local/bin/docker-compose
```

3. Test your installation
```
$ docker-compose --version
$ docker-compose version 1.17.0, build 1719ceb
```


## Architecture of A Container
Containers are not as complex as they sound, turns out they are pretty simple concept and so is their architecture, a docker container is simply a service running on a setup

Your containers run on the docker architecture using the configuration in the DockerFile, the docker-compose.yml file or the image specified in the docker run command to set up your containers. These containers usually have exposed ports if they are to connect to each other.

Your containers are services on their own and can work off each other using resources from the other via the network setup in them, these networks are created the docker-compose file

Your docker file setup typically sets you up with an image, a profile based on which the container is created, To fully explain this we'll dockerize a node application.

## Dockerizing a node app
For this simple set up we are going to set up docker on a web app, node-based to show the cool nature of docker.
The code of the project can be found in the reference repository.

### Step 1 - Setting up the base app
So first we set up the express application
```bash
$ npm i -g express-generator #setup the express-generator
$ express # setup an express app
$ touch processes.json
```
> the processes.json setup is required to run pm2 which helps manage the processes of the server
, usually, we can run the application using the
```bash
$ node ./bin/www
```
And essentially get the app running, but with pm2 we go a step further adding load balancing and basically preparing the app to scale.


### Step 2 - Setting up the docker image
Next, we set up the docker image in the base file

```docker
#Step 1.
FROM node:6.11-wheezy

#Step 2
LABEL version="1.0"
LABEL description="This is our base docker image"
LABEL maintainer "mozart.osita@gmail.com"

#Step 3.
ENV appDir /var/www/app/current

#Step 4.
ENV NODE_ENV production

#Step 5..
# Set the work directory
RUN mkdir -p /var/www/app/current
WORKDIR ${appDir}

#Step 6
ADD package.json ./
RUN yarn install --production


RUN yarn global add forever pm2

ADD . /var/www/app/current

EXPOSE 4500

CMD ["pm2", "start", "processes.json", "--no-daemon"]


```
In the setup, the first parts specify which images we are trying to build our image from.
```docker
#Step 1.
FROM node:6.11-wheezy
```
Using the Label tags we specify other information about the image we are setting up, 
```docker
#Step 2
LABEL version="1.0"
LABEL description="This is our base Docker image"
LABEL maintainer "mozart.osita@gmail.com"
```
After this, we, set environmental variables, set our environment to production and set up the Work Directory on the server using the `appDir` variable

```docker
#Step 3.
ENV appDir /var/www/app/current

#Step 5.
ENV NODE_ENV production

#Step 6..
# Set the work directory
RUN mkdir -p /var/www/app/current
WORKDIR ${appDir}
```

Next we set up `package.json` in the `workdir` and run the yarn install command with the production flag, we also add our other directories and file into the working directory.

```docker
#Step 7
ADD package.json ./
RUN yarn install --production


RUN yarn global add forever pm2

ADD /var/www/app/current
```
After all these, we expose the 4500 port which would be used in connecting with the outside environment.

```docker
EXPOSE 4500

CMD ["pm2", "start", "processes.json", "--no-daemon"]
```
The CMD command after that starts up the server with pm2, a node based process manager.


### Step 3 - Build the image and deploy
After this, we build our image and set it up run it.

```bash
$ docker build -t <image name> . #please remember the .(dot)
```
This runs a process to build your images, after this you can add your image to docker hub to be able to pull them from anywhere.
If you have a docker hub account, proceed to log in on your terminal
```bash
$ docker login --username=yourhubusername --email=youremail@company.com
```
Next, you get the image id
```bash
$ docker images
```
From the list, output get the id of your images and tag your image with the repositories name
```bash
$ docker tag bb38976d03cf yourhubusername/reponame:yourtag
```
Next, you can push this to dockerhub
```bash
docker push yourhubusername/reponame
```
After this running, your container is a breeze
```bash
$ docker run --rm -it -p bindport:exposedport <image-name>:latest
```
A container is launched and set.

## Connecting Containers
To connect our container with another container we can set this up using docker-compose, the fun part is we can run multiple containers and decentralized parts of the same application. To accomplish this we'll set up a docker-compose file and build the container from it, as a service, using the docker-compose setup we can set up multiple containers as services and link them via the container's name

Here's a sample docker-compose.yml file
```docker
version: '3'

services:
  appplication:
    image: mozartted/base-node:latest
    ports:
      - "4000:4500"
```
But we can connect our container with another via the link tag, let's say we want to have our node service run alongside a MongoDB service.

So we update the docker-compose configuration file.
```docker
version: '3'

services:
  application:
    image: mozartted/base-node:latest
    ports:
      - "4000:4500"
    links:
      - mongo
  mongo:
      image: mongo:latest
      ports:
        - "27018:27017"
      volumes:
        - ./data:/data/db
```
Using the links tag we connected the application container or service to the mongo service, and with the volume tag we set up a directory data in our project folder as the data volume of the mongo container, using the link in the application's configurations we can connect to the mongo service using the name mongo as the service's address and the exposed port 27017 as the port in the container.

But this method of connecting containers limits us to a project set therefore we cant connect containers across two different projects,
Using the network tags we can set up a network that we can use across different containers and project bases.
```docker
version: '3'

services:
  appplication:
    image: mozartted/base-node:latest
    ports:
      - "4000:4500"
    links:
      - mongo
    networks: 
      - backend
  mongo:
    image: mongo:latest
    ports:
      - "27018:27017"
    volumes:
      - ./data:/data/db
    networks: 
      - backend
networks:
  backend:
    driver: "bridge"
  
```
With this setup the containers are connected to the backend network, therefore, external containers can also connect with the backend network to be able to access the services in it.
To get a list of the networks connected to the container simply run the command
```bash
$ docker network ls
```
Using the network name you can connect external content to the network using the command 
```bash
$ docker network connect <network_name> <container_name>
```
to be able to view the containers with access to the network simply run the command
```bash
$ docker inspect <network_name>
```

Looking to follow up on this process, you can find a sample repo of this setup [here](https://github.com/Mozartted/DockerizedNode)

## Conclusion
With these, you can be able to set up containers for different projects and connect them making them use services found in the others, and with more configurations would be ready to pull off a microservice-based architecture in deployment, Docker is a really great tool and taking full advantage of what it offers is worthwhile.