LoginSignup
30

More than 3 years have passed since last update.

docker-compose から docker network を少しだけ理解したい

Last updated at Posted at 2019-04-11

docker-compose での疑問

docker公式っぽいやつの docker-compose の例 : https://docs.docker.com/compose/gettingstarted/

ここでのapp.pyredishostが以下のように指定されています。


cache = redis.Redis(host='redis', port=6379)

なぜ host='redis'で別のコンテナのredisにつなぐことが出来るんだい?

上記の公式サイトには以下のように解説されています。

In this example, redis is the hostname of the redis container on the application’s network. We use the default port for Redis, 6379.

はぇ〜

application’s network ってなに

ここでいう application’s network とは docker container におけるネットワークのことっぽい?

docker-compose up 等で起動されたコンテナ群は、すべて同一のネットワークに所属することになるようです。

参考にさせていただいた記事 : https://qiita.com/roba4coding/items/efd3a38db08eb476d412

つまりどういうことだってばよ

docker inspect コマンドを使うことでふわっと概要がわかります。

inspect するためにまず コンテナのIDを調べます。


$ docker ps
CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                    NAMES
aa690f2ae5d4        example_docker_compose_web   "python app-server/s…"   2 minutes ago       Up 2 minutes        0.0.0.0:5000->5000/tcp   example_docker_compose_web_1
4f39c7c9cc47        redis:alpine                 "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        6379/tcp                 example_docker_compose_redis_1

inspect します。


$ docker inspect 4f39c7c9cc47
...
            "Networks": {
                "example_docker_compose_default": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": [
                        "4f39c7c9cc47",
                        "redis"
                    ],
                    ...
                }
            }
...

コンテナのID : 4f39c7c9cc47(example_docker_compose_redis_1) が redis というエイリアスで登録されているのですね。

このエイリアスを使うことが出来るのが、同一 docker network に所属するものだけだということですね。

上記でいうと コンテナ aa690f2ae5d4(example_docker_compose_web_1) が エイリアスを使うことが出来るということですね。

どこで redis というエイリアスの名前が決まったかということですが、docker-compose.ymlに書いてある servicesの直下の定義の名のことみたいですね。


version: '3'
services:
  # ↓これ
  web:
    build: .
    ports:
     - "5000:5000"
  # ↓これ
  redis:
    image: "redis:alpine"

docker network ってなに

docker network ls で現在存在する docker network の一覧を見ることができます。


$ docker network ls
NETWORK ID          NAME                               DRIVER              SCOPE
ac27f0096628        bridge                             bridge              local
e72136cdac25        example_docker_compose_default     bridge              local
d2b0552308a8        host                               host                local

ここで 最初の docker-composeexample で作られたであろう example_docker_compose_defaultdocker networkの詳細を見てみましょう。

コマンドは docker network inspect です。


$ docker network inspect example_docker_compose_default
[
    {
        "Name": "example_docker_compose_default",
        "Id": "e72136cdac25de9dbc9875467aacd59e916ba8b7122cbede91f81387a2a18715",
...
        "Containers": {
            "4f39c7c9cc478dc30aca3bd21c6dc1eda2bb189c0b5264a325f98b38ad8cd7c6": {
                "Name": "example_docker_compose_redis_1",
                ...
            },
            "aa690f2ae5d483c0c2cf213d9929a3d49025859464abe095f861c05bbb66ee32": {
                "Name": "example_docker_compose_web_1",
                ...
            }
        },
...
]

Containers に 先ほど docker-compose で作られたコンテナ達がありますね。コンテナIDも一致しているようです。

参考にさせていただいた記事 : https://qiita.com/TsutomuNakamura/items/ed046ee21caca4a2ffd9

docker-compose を使わずにやってみよう

今回は別の例として mysql が起動しているコンテナ に対して python が起動したコンテナからアクセスしたいと思います。

docker networkを知らなかった時

まずmysqlのコンテナをたてます。


$ docker run -e MYSQL_ROOT_PASSWORD=root -d -p 3307:3306 --name test-mysql mysql:5.6
4f7475ea1ac4db5d4aad630cbe585faf2dca39db61d7e405e14e9554414bd486

python が起動しているコンテナから mysqlのコンテナにアクセスするためには、そのコンテナのアドレスを知る必要があります。


$ docker exec test-mysql cat /etc/hosts
127.0.0.1   localhost
.. 
172.17.0.2  4f7475ea1ac4

こうすることでようやく接続することができました。(もっといいやり方あったら教えてください..)


>>> import mysql.connector
>>> conn = mysql.connector.connect(host="172.17.0.2",user="root",password="root",port=3306,database="mysql")
>>> conn.is_connected()
True

docker networkを使った場合

まず、コンテナが所属するための docker network を作ります。

docker networkに関して参考にさせていただいたブログ : https://www.sambaiz.net/article/7/


$ docker network create -d bridge test-network
25d355cf117def0e6ce801341e1b535320cd688435a436ce063dc49bbb3c9c0e
$ docker network ls
NETWORK ID          NAME                               DRIVER              SCOPE
ac27f0096628        bridge                             bridge              local
e72136cdac25        example_docker_compose_default     bridge              local
d2b0552308a8        host                               host                local
07263a6d0de1        test-network                       bridge              local

コンテナが作成される時に、作ったネットワークに所属してもらうようにするには、--net オプションを使うようです。


$ docker run -e MYSQL_ROOT_PASSWORD=root -d -p 3307:3306 --name test-mysql --net=test-network --net-alias mysql  mysql:5.6
0f901dbda634c3d05cce10d2bf91fb0ef82d39fbd1b1046f284db522bc8387f8

こうすることで、docker-compose で起動したコンテナと同様にエイリアスが登録されます。


$ docker inspect 0f901dbda634
...
            "Networks": {
                "test-network": {
                    ...
                    "Aliases": [
                        "mysql",
                        "0f901dbda634"
                    ]
            ...
            }
...

そして python が起動するコンテナも同一docker network上にたててあげれば、


$ docker run -it --net=test-network test-python
>>> import mysql.connector
>>> conn = mysql.connector.connect(host='mysql',user='root',password='root',port=3306,database='mysql')
>>> conn.is_connected()
True

無事、コンテナを名前解決できるようになり、host='mysql' で接続できているのがわかると思います。

--link の場合

$ docker run -e MYSQL_ROOT_PASSWORD=root -d -p 3307:3306 --name test-mysql --net=test-network  mysql:5.6
2d96784fb9ae77cec276558d3439e3b455782bb4bac4291b76b65a27d5c27480
$ docker run -it --net=test-network --link test-mysql:mysql test-python
Python 3.7.3 (default, Mar 27 2019, 23:48:15)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mysql.connector
>>> conn = mysql.connector.connect(host='mysql',user='root',password='root',port=3306,database='mysql')
>>> conn.is_connected()
True

同様に繋ぐことが出来ました。

link の場合 AliasesではなくLinksに名前解決するための情報が書かれていました。

...
            "Networks": {
                "test-network": {
                    ...
                    "Links": [
                        "test-mysql:mysql"
                    ],
                    "Aliases": [
                        "d0d2ed057334"
                    ],
                ...
                }
            }
...

--net-alias--link の使い分けに関してはまだ知識が浅いのでいつか調べたいと思います。

まとめ

docker-compose を使おう!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30