異なるDocker環境でSSRする方法

  • #開発
  • #Docker
  • #SSR
  • #Next.js

こんにちは。CURUCURU エンジニアの兄山です。

今日は異なる Docker 環境で、SSR(Server Side Rendering)する際に気をつけることについてお話ししようと思います。

エラーの解消に手間取ってしまったため、皆さんの役に立てればと思っています。

何故異なる Docker 環境で SSR できなかったのかについて

結論、Docker のネットワーキングが違っていた

からです。

ネットワークが違うと IP のレンジも異なってくるので、

それぞれのホスト同士で接続できなかったというのが結論です。

調べてみたら当たり前のことでしたが、気づかず時間を溶かししまっていました。。。(基礎って大事ですね!)

参考までに、今回、苦戦していた環境が実際どのようなものであったか下の図に示します。

Docker環境

Next.js で Golang へリクエストを飛ばし、DB 情報を取得しようとしていましたが、エラーになっているという状況でした。

どうやって SSR できたのか

手順としては、 ① 該当 service に networks をリストで定義 ② services と同じ階層にリストで定義した networks を指定 ③ external: true にすることで、各 docker-compose.yml で管理されていないネットワークだということを明示

上記の手順で記述をすることで、異なる Docker 環境同士で通信できるようになります。

下記に Next.js, Golang の docker-compose.yml を表示しています。

Next.js の docker-compose.yml

version: "3"

services:
    next:
        build: ./xxx
        ...
        ...
        networks:
            - go-next
        ...
    ...
・・・
・・・
networks:
  go-next:
    external: true
    ・・・

Golang の docker-compose.yml


version: "3"

services:
    go:
        build: ./xxx
        ...
        ...
        networks:
            - go-next
        ...
    ...
・・・
・・・
networks:
  go-next:
    external: true
    ・・・

external なネットワークは docker-compose で作成されないので、コンテナを起動する前に以下コマンドで作っときます。

docker network create go-next

ネットワークが作成できたら確認してみましょう。

ネットワークの確認は以下のコマンドで可能です。

docker network ls

Docker のネットワーク一覧の確認

$docker network ls

NETWORK ID      NAME      DRIVER    SCOPE
9e8i743855758   go-next   bridge    local
1a64747373eb2   default   bridge    local
・・・

次に、コンテナをそれぞれ起動して、そのネットワークの詳細を見ていきましょう。

コマンドは以下です。

docker network inspect <コンテナ名(上記の「NAME」箇所)>

Docker のネットワーキングの詳細確認


$docker network inspect go-next
[
    {
        "Name": "go-next",
        "Id": "16773874877483857r847386576743657643657eurhfuky8i58882bf33024",
        "Created": "2022-08-31T07:04:26.47474745Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.17.16.0/20",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "hdjchjdhf848787573478yyryhdiu4er8yryy458r7r784375r35yr88b513364d": {
                "Name": "reverent_vaughan",
                "EndpointID": "848478487347yueriy4y87574874h6896f3169451571d91",
                "MacAddress": "99:76:vc:17:08:02",
                "IPv4Address": "172.17.0.1/16",
                "IPv6Address": ""
            }
            "52131435c4544557hhuhuh7433834772y439945885394ururdadb33b51336a8d": {
                "Name": "reverent_vaughan",
                "EndpointID": "5d467b8ee5412d5a87fe1081cbdf3d11456c3b5838d8966896f3169451571d91",
                "MacAddress": "91:42:il:31:01:12",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

ネットワークと IP レンジが同じになるので、コンテナ間通信ができるようになりました!!

コンテナのネットワークと IP のみを表示したい場合は、以下のコマンドで確認できます。

docker network inspect go-next | grep -i network

docker network inspect go-next | grep -i ipaddress (grep で特定のキーワード検索ができます。「-i」・・・大文字、小文字の区別をしない)

いかがでしたでしょうか?

ネットワークの基礎勉強が改めて大事だなと痛感した今日この頃の私でした笑

以上、今回は異なる Docker 環境でで SSR する際のお話でした。