【Docker】networksで複数のDocker Compose環境間を通信可能にする

## はじめに
まず今回やりたいことを図で説明するとこんな感じになります。
![sample.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884629/1d488e95-8470-8ea5-3d06-d5b877b59a76.png)

一つのDocker Composeの中であれば、はじめから各コンテナはお互いに通信可能です。

> デフォルトで Compose はアプリに対して１つの ネットワーク を作成します。サービス用の各コンテナはデフォルトのネットワークに接続し、そのネットワーク上で他のコンテナと相互に「 接続可能reachable 」になります。
https://docs.docker.jp/compose/networking.html

しかし複数のDocker Compose間の通信はデフォルトの状態ではできません。
そこで、Docker Composeのネットワーク機能を使って複数のDocker Composeを通信可能にしよう、というのがこの記事の趣旨です。

## 環境
- M1 Mac macOS Monterey12.1
- Docker 20.10.20
- Docker Desktop 4.13.1

## ネットワーク機能を使う
今回は例として「一つのDBコンテナを複数のDocker Compose間で共有する」というケースを考えてみます。
リポジトリhogeのDBコンテナをリポジトリfugaでも使いたい状況です。
![sample.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884629/1e64d037-8298-077b-864c-13a1430408f6.png)

まず最終的なディレクトリ・ファイル構成を載せておきます。

```
.
├── fuga
│   ├── Dockerfile
│   ├── docker-compose.yml
│   ├── go.mod
│   ├── go.sum
│   └── main.go
└── hoge
    └── docker-compose.yml
```

```yml:hogeのdocker-compose.yml
version: '3'
services:
  db:
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: password
    volumes:
      - db-store:/var/lib/postgresql/data

volumes:
  db-store:
```

```yml:fugaのdocker-compose.yml
version: '3'
services:
  go:
    build: .
    tty: true

networks:
  default:
    name: hoge_default
    external: true
```
<details>
<summary>Dockerfile</summary>

```dockerfile:Dockerfile
FROM golang:1.19.4-bullseye

COPY . /go/src

WORKDIR /go/src

CMD ["/bin/bash"]
```

</details>

まずhogeのdockerコンテナを立ち上げます。
```bash
$ docker compose up -d
```

次にdbコンテナに入ります。
```bash
$ docker compose exec db /bin/bash
root@5498c9cec982:/#
```

postgresを操作して適当なデータを入れておきます。
```
root@5498c9cec982:/# psql -U postgres
> psql (15.1 (Debian 15.1-1.pgdg110+1))
> Type "help" for help.
postgres=#

postgres=# alter table postgres with encrypted password '1234';

postgres=# create table books (id serial, name varchar(255), author varchar(255));
> CREATE TABLE

postgres=# insert into books values (1, 'H✖️H', '冨樫');
> INSERT 0 1

postgres=# select * from books;
id | name | author 
----+------+--------
  1 | H✖️H  | 冨樫
(1 row)
```

今度はfugaのDocker Composeを立ち上げます。
```bash
$ docker compose up -d
```

ここでmain.goのコードを覗きますが、ここでのミソは**DBのホストにdbコンテナを指定している**点です。

```go:main.go
package main

import (
	"database/sql"
	"fmt"

	_ "github.com/lib/pq"
)

type BOOKS struct {
	ID     string
	Name   string
	Author string
}

func main() {
    // DBのホストにdbコンテナを指定している
	db, err := sql.Open("postgres", "host=db port=5432 user=postgres password=1234 dbname=postgres sslmode=disable")

	defer db.Close()

	if err != nil {
		fmt.Println(err)
	}

	rows, err := db.Query("SELECT * FROM books")

	if err != nil {
		fmt.Println(err)
	}

	var es []BOOKS
	for rows.Next() {
		var e BOOKS
		rows.Scan(&e.ID, &e.Name, &e.Author)
		es = append(es, e)
	}

	fmt.Println("%v", es)
}
```

goのコンテナに入ってコードを実行してみます。
```bash
$ docker compose exec go /bin/bash
root@e3a1ce68206a:/go/src#

root@e3a1ce68206a:/go/src# go run main.go
> %v [{1 H✖️H 冨樫}]
```

fugaのコンテナからhogeのdbコンテナにアクセスしてbooksテーブルのレコードを取得できました🎉

## 詳しく見る
fugaのdocker-compose.ymlでnetworksを指定しています。
この定義でネットワークを共有することで各コンテナ間の通信を可能にしています。
```yml:fugaのdocker-compose.yml
version: '3'
services:
  go:
    build: .
    tty: true

networks:
  default:
    name: hoge_default
    external: true
```
ここでnetworksの定義の意味は以下のとおりです。
- networks・・・ネットワークの定義
- default・・・fugaのDocker Compose環境のコンテナすべてに以下のネットワークを指定する
- name・・・定義したいネットワークの名前
- external・・・既存のネットワークを使用するにはtrueを指定する

冒頭で「一つのDocker Composeの中であれば、はじめから各コンテナはお互いに通信可能です。」という話をしました。
> デフォルトで Compose はアプリに対して１つの ネットワーク を作成します。サービス用の各コンテナはデフォルトのネットワークに接続し、そのネットワーク上で他のコンテナと相互に「 接続可能reachable 」になります。
https://docs.docker.jp/compose/networking.html

このネットワークの「名前」は何も指定しなければ「ディレクトリ名 + _default」となります。

なのでhogeディレクトリのネットワーク名は「hoge_default」となり、このネットワーク名をnameに指定しているというわけです。

以下コマンドで現在作成されているネットワークの一覧を取得できます。
```bash
$ docker network ls
NETWORK ID     NAME                               DRIVER    SCOPE
5d0e5ea33cb1   bridge                             bridge    local
1ceaf292e9bb   hoge_default                       bridge    local
8e686400f1a3   host                               host      local
4c404bd7f6af   none                               null      local
```

:::note info
bridge、host、noneはDockerのインストール時に自動で作成されているネットワークです。
:::

また、docker inspectコマンドでネットワークが共有されていることを確認できます。
※ContainersにそれぞれのDocker Composeのコンテナ（hoge-db-1、fuga-go-1）が含まれていることが分かります。
```
$ docker network inspect 1ceaf292e9bb
[
    {
        "Name": "hoge_default",
        "Id": "1ceaf292e9bb5580b79e11f8b6070085bc861a736457b1873c9fed994f682ab7",
        "Created": "2022-12-08T00:52:35.359427213Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "********",
                    "Gateway": "********"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "5498c9cec982201befa9a2fe74e6165721c7077b556af3c4f55b3f2d7e410479": {
                "Name": "hoge-db-1",
                "EndpointID": "108308bbd26820b272630a7c846ebd702798317ace71aab11bebc385f728fe80",
                "MacAddress": "********",
                "IPv4Address": "********",
                "IPv6Address": ""
            },
            "e3a1ce68206a554a2babc8b82cd631b9c9fb64f11b779034f9635ac94b4e8795": {
                "Name": "fuga-go-1",
                "EndpointID": "2ec20e292c07e9ec945553cf2b3c8d7ff4b74f056633a8797b07abcf98a2e3c3",
                "MacAddress": "********",
                "IPv4Address": "********",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "hoge",
            "com.docker.compose.version": "2.12.1"
        }
    }
]
```

以上になります。
Dockerネットワークで快適なDockerライフをお過ごしください。

## 最後に
#### GoQSystemでは一緒に働いてくれる仲間を募集中です！
ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site/?qiita=63fc1fb70056b8784dfd