Network

Exercise - Network introduction

As a result of the “Images” exercise you can now see the following containers in your list:

docker ps

$ docker ps
CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS          PORTS                                       NAMES
b2a968f4f4b0   postgres:latest    "docker-entrypoint.s…"   6 minutes ago    Up 6 minutes    0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   postgresdb
d266fc71ab06   todoui:v0.1        "/__cacert_entrypoin…"   8 minutes ago    Up 8 minutes    0.0.0.0:8090->8090/tcp, :::8090->8090/tcp   todoui
265da979af36   todobackend:v0.1   "/__cacert_entrypoin…"   12 minutes ago   Up 12 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   todobackend

If you pick the backend container and execute a shell, you will be able to find out that there is no connection between the instances.

docker exec -it todobackend /bin/sh

Once connected try to ping another container on the network:

ping postgresdb

You will get an error:

/opt/todobackend # ping postgresdb
ping: bad address 'postgresdb'

It’s actually not even possible to ping the own container by name:

ping todobackend

/opt/todobackend # ping todobackend
ping: bad address 'todobackend'

Exit the shell again using exit.

This is due to all containers running isolated from each other:

graph
    subgraph Docker
        subgraph s1["Container"]
            D(postgresdb:5432)
        end
        subgraph s2["Container"]
            B(todoui:8090)
        end
        subgraph s3["Container"]
            C(todobackend:8080)
        end
    end

(In fact, recent Docker plugs all containers into a default network called “bridge” unless specified otherwise, just to follow the principle of least surprise: this ensures that no Pod will fail due to not having any network at all. So, the containers do already have an IP address each and could connect to each other using that. Still, the better approach is to use a dedicated virtual network as follows.)

However, Docker provides the possibility to create virtual networks to connect the containers.

To list the default commands start with

docker network

which will give you the overview:

$ docker network
Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.

Create your first virtual network using:

docker network create todonet

And list the networks

docker network ls

$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
10b9448cc71d   bridge    bridge    local
2d2089ec09bd   host      host      local
81e8bb2089d0   none      null      local
3ba6a91f405b   todonet   bridge    local

Your new network is now visible.

Milestone: DOCKER/NETWORK/CREATE

Exercise - Attaching container to a network

The next logical step is to connect the running containers to the network. Start with:

docker network connect todonet todoui

docker network connect todonet postgresdb

Milestone: DOCKER/NETWORK/CONNECT, requires: DOCKER-IMAGES-GIT-CLONE

To validate if the networks are now attached run either:

docker network inspect todonet

Under section “Containers” you will find the attached containers along with network information:

        "Containers": {
            "b2a968f4f4b0cda3bcac717b881ca4ab6d8dfaba1e9fd6b761acd68b7e08c86d": {
                "Name": "postgresdb",
                "EndpointID": "6103277ef5fb2203cdb3cd1b2c6d7b1f288dd3c6135b9faf09e3d7d30bb03202",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "d266fc71ab06e63485a810a4f74e896a58bec62d65bceb743a6cfbb99e384332": {
                "Name": "todoui",
                "EndpointID": "ec0113564d07f5e725454afe080c034605e326d8e44cb951655032343decf9d6",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },

If you execute the shell within a container again you can also validate from “inside”:

docker exec -it todoui /bin/sh

Repeat the ping command to the own host:

ping todoui

PING todoui (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.134 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.081 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.110 ms

And also try to reach the DB container:

ping postgresdb

PING postgresdb (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.316 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.108 ms
64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.177 ms

Exit the shell again using exit. The containers are now connected.

Exercise - Attaching container to a network directly from startup

An alternative option to connect to a network is directly from the start of the container.

In order to demonstrate this, use the container for the backend application. First stop and remove the container:

docker stop todobackend

docker rm todobackend

Re-create the container using the following command, ensuring by setting an appropriate environment that it will make use of our postgresdb:

docker run -d -p 8080:8080 --network todonet -e SPRING_PROFILES_ACTIVE=prod -e POSTGRES_HOST=postgresdb --name todobackend todobackend:v0.1

Milestone: DOCKER/NETWORK/CONNECT-TODOBACKEND

Once running you can also validate connectivity by inspecting the container instead of the network:

docker container inspect todobackend

And see the details here:

            "Networks": {
                "todonet": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": [
                        "e20623eb6832"
                    ],
                    "NetworkID": "3ba6a91f405b5d11067f2d6c97a4cf106188738c98b8b46d9ff5b1c2a24216b4",
                    "EndpointID": "e8da35d21896a540e0bf32ff28b9334ab822b2535989753fc9fe6f1de5a2e92c",
                    "Gateway": "172.19.0.1",
                    "IPAddress": "172.19.0.4",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:13:00:04",
                    "DriverOpts": null
                }
            }

With this step the base part of the container exercises are completed. All containers are now up and running and connected to each other.

Exercise - Connect to application via your browser

At the end, our containers will be connected like this:

graph LR;
    A{User VM} -->|Port 8090| B
    subgraph Docker
        subgraph s1["Container"]
            B(todoui)
        end
        subgraph s2["Container"]
            C(todobackend)
            B -->|Port 8080| C
        end
        subgraph s3["Container"]
            D(postgresdb)
            C -->|Port 5432| D
        end
    end

Then you could access the todoui application at the IP address of your personal VM using your browser under

http://<your IP address>:8090/

Alternatively, just check the availability of the todoui interface locally from the command line of your personal VM via curl:

curl --silent localhost:8090; echo