はじめに
Dockerコンテナで開発サーバを立てた時、http://localhost:3000とあるからスマホでhttp://localhost:3000って入力してるのにアクセス出来ないよ! となります。割と当たり前の話ではありますが、じゃあどうすればいいの?と後輩に聞かれた時のためのチートシートです。
要約
理論なんてどうでもいいから方法を教えろ!という方のために。
- docker-compose.ymlの中のサービス名の中のportsオプションに
"ports":"8000:3000"
を指定する。(もちろん"ports":"3000:3000"
でいいが、どのポートにどのポートが対応しているか分かりやすくするために今回は"ports":"8000:3000"
を指定する。) - Windowsならshellで
ipconfig
、Macならifconfig
を実行し、IPv4アドレスをコピーする。 - Dockerコンテナ上で開発サーバーをhttp://0.0.0.0:3000で立てる。
- Dockerを起動したPCと同一ネットワーク上に接続されている別端末でhttp://<2.で調べたアドレス>:8000をブラウザのURL欄に入力
対象読者
インフラ関係全然わからん、IPアドレスってネットの住所ってことくらいは知ってるよという人。
本文
タイトルはDocker関連の話ですが、本文はほとんどWebの基礎知識についての話題になります。先述したように、理論はどうでもいいという方は要約を読んでください。
ただし、Dockerネットワークについては結構踏み込んだ話題となり、少し長くなりすぎるのでここでは説明しません。あくまで目標はDockerのUbuntuコンテナで立てた開発サーバに、実機端末でアクセスすることとします。また、理解しやすいように一部簡略化しています。
ちなみに、これを読むと全て解決します。
特別なIPアドレス
プライベートIPアドレスとグローバルIPアドレスの説明については省きます。よく分からない方はこのあたりを読んでください。
ここで、プライベートIPアドレスの中で特別なものが存在し、0.0.0.0と、127.0.0.1の2つがあります。
0.0.0.0
基本的に無効なIPアドレスですが、開発サーバとしてhttp://0.0.0.0上に立てた場合に限り、同一ネットワーク上にある全てのデバイスからアクセス可能なサーバーになります。同一ネットワーク上のデバイス全てに対するネットワークインターフェースを持つ、と言ったりします。
つまるところ、同じWiFiに繋がっていれば、別端末でもアクセス可能になるということです。
しかし、その際にはホスト側のPCのIPアドレスに接続すべきで、0.0.0.0にアクセスするとOSによっては(というかWindowsの場合)アクセスできません。
127.0.0.1
このIPアドレスに馴染みがなくとも、localhostという単語に聞き覚えはあるのではないでしょうか。localhostを名前解決する(ドメイン -> IPアドレスへと変換することです。このことをDNSと呼びます。)と127.0.0.1となります。
そして、この127.0.0.1とはループバックアドレスと呼び、自分 -> 自分へのアクセスを指すことになります。ループバック、という単語と意味の対応がしやすいと思います。だから、WindowsPC(Dockerではなく、本当にWindowsのローカル環境)で開発サーバをhttp://localhostと立てた際には、同じWindowsPCでhttp://localhostとアクセスすることで開発サーバにアクセスできるようになる、ということです。
そして、重要なのが127.0.0.1は同一ホスト内の通信しか許可しません(ネットワークインターフェースは自分のみ)。なので、開発サーバをhttp://127.0.0.1で立てた場合、別端末からそのサーバにアクセスすることはできません。
docker run -p 8000:3000の意味
そして、docker runの際に指定する-p 8000:3000
はちょっと調べただけだと、「ポート開放」のためだとか、「ポートフォワーディング」のためだとか、分かっている人向けへの説明しかないですが、これはホストPCの8000番ポートへの通信は全てコンテナの3000番ポートへ流すというオプションになります。
だから、ホストPCがhttp://localhost:8000とアクセスすると、これはコンテナの3000番ポートへのアクセスへと流すということになります。
(内部的にはiptablesのテーブルを変更しています。が、冗長になるのでここでは説明しません。)
ここまで読めば、大体なぜ要約のようにすることで実機端末でアクセスできるか分かると思います。
最初の要約と対応させて以下の箇条書きを読んでください。
- ホストPCの8000番ポートへのアクセスをコンテナの3000番ポートへのアクセスに流すオプションを付けてコンテナを起動。
- ホストPCのIPアドレスを取得。
- コンテナ側で0.0.0.0:3000でサーバを起動。
- スマホでホストPCの8000番ポートへとアクセス -> コンテナの3000番ポートへとアクセスを流すことで開発サーバを確認できる
- docker-compose.ymlの中のサービス名の中のportsオプションに
"ports":"8000:3000"
を指定する。(もちろん"ports":"3000:3000"
でいいが、どのポートにどのポートが対応しているか分かりやすくするために今回は"ports":"8000:3000"
を指定する。)- Windowsならshellで
ipconfig
、Macならifconfig
を実行し、IPv4アドレスをコピーする。- Dockerコンテナ上で開発サーバーをhttp://0.0.0.0:3000で立てる。
- Dockerを起動したPCと同一ネットワーク上に接続されている別端末でhttp://<2.で調べたアドレス>:8000をブラウザのURL欄に入力
何か間違っている事があればコメントをお願いします…