2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

複数のDockerComposeプロジェクトでLocalQualityの開発体験を得る

Last updated at Posted at 2022-04-11

はじめに

M1 Macを使い始めたことをきっかけに、コンテナベースのWeb開発に移行しました。
各実行環境をコンテナに隔離しつつ、エディタや各種GUIクライアントとの連携において、ローカルと同等の開発体験を得るために行ったことと、途中でハマったことを書いていこうと思います。

環境

  • M1 Mac Monterey 12.3
  • Docker Desktop 4.6.1
  • Visual Studio Code 1.66.1
  • Remote - Containers 0.231.5(本記事ではこちらの設定は割愛します。)

前提と要件

今回対象にしたのは、下記のような構成の既存のWebサービスです。
開発体験という観点で下記を要件として設定します。

要件①:コンテナA-webのHTMLレスポンスに含まれる、コンテナB-webのiframeをホストのブラウザで表示できること。
要件②:ホストからコンテナA-dbとコンテナB-dbに接続できること。
image-1.png

結論

ホスト → コンテナA-web

至極一般的ですが、ポートバインディングしたうえで、コンテナA-webのDjangoアプリケーションを0.0.0.0:8000でLISTENすれば、ホストからは当該アドレスでコンテナA-webに到達可能です。

# docker-compose-A
services:
  web:
    ports:
      - 8000:8000
# コンテナA-web
python manage.py runserver 0.0.0.0:8000
# Host
curl http://0.0.0.0:8000

コンテナA-web → コンテナB-web

異なるDocker Networkに属するコンテナ同士では通信ができないので、同じネットワークに接続します。今回はdocker-compose-Bのネットワークで統一しました。
external: trueによって、network-Bdocker-compose-Aのライフサイクルの外側で管理されていることを示し、新たなリソースとして作成されることを防ぎます。

# docker-compose-A
services:
  web:
    networks:
      - network-B
  db:
    networks:
      - network-B

networks:
  network-B:
    external: true

そのうえでコンテナA-webからコンテナB-webに対しては、ネットワークエイリアス(B-web)で通信します。エイリアスは他にもあるので、適当なものを選びます。

docker inspect ContainerB
"NetworkSettings": {
    "Networks": {
        "network-B": {
            "Aliases": [
                "xxxxxxxxxx",
                "B-web"
...略
# コンテナA-web
export SERVICE_B_ORIGIN="http://B-web:8001"

ブラウザ → コンテナB-web (iframe)

前提として関連サービスであるBのURLは、上記で設定した環境変数を元に組み立てるので、コンテナA-webのレスポンスに含まれるiframeのsrcは、コンテナB-webのネットワークエイリアスとなります。これをホストが名前解決できるように、ホストの /etc/hosts を編集します。

# /etc/hosts
0.0.0.0 B-web

かつコンテナB-webのDjangoは0.0.0.0:8001でLISTENします。
すべてのネットワークインターフェイスにバインドすることで、コンテナA-webからの通信が可能になります。

# コンテナB-web
python manage.py runserver 0.0.0.0:8001

ホスト → コンテナA-db, コンテナB-db

それぞれを違うポートで起動し、ポートバインディングしました。
一度Host networkでの起動を試みましたが、断念しています。詳細については続きをご参照ください。

# docker-compose-A
services:
  db:
    ports:
      - 5432:5432
    command: -p 5432

# docker-compose-B
services:
  db:
    ports:
      - 5433:5433
    command: -p 5433

ハマったこと

Host Networkで起動したPostgreSQLコンテナに接続できない。

2つのdocker-composeを同じネットワークに接続しなくとも、コンテナA*をHost networkで起動すればいいんでね?とやってみましたが、ホストからPostgreSQLコンテナに接続することができませんでした。

# docker-compose-A
services:
  web:
    network_mode: host
# Host
psql -U foo -d bar -p 5432

# Is the server running locally and accepting connections on that socket?

Dockerのドキュメントを改めて読んだところ、Host networkはLinuxのみでMacはサポートされていないという記述がありました。

The host networking driver only works on Linux hosts, and is not supported on Docker Desktop for Mac, Docker Desktop for Windows, or Docker EE for Windows Server.

MacやWindowsの場合、docker daemonはVM上で動作するため、network_mode: hostはVM自身を指すことになり、手元のMacからはアクセスできないということだと解釈しています。つまりMacとDockerコンテナの連携は、ポートバインディング一択となりそうです。

終わりに

今回は主にdocker-composeの設定周りが主となりましたが、LocalQualityの開発体験を得るには、これらに加えてエディタとコンテナの連携が必須と思います。Visual Studio CodeのRemote Containersの個人的なベストプラクティスについては、別記事でまとめられればと思います。

2
0
0

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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?