AsaDesign

Dockerを思い出す②

今回の目的

DockerコンテナのIPアドレスをローカルPCのIPアドレスに変換する。
そうするとスマホ端末とDockerコンテナが同じネットワーク、ということになる。

参考サイト:ExpoをDocker上で動かしたい! | React Native+Expo+Docker – Zenn

127.0.0.1というのは「自分宛てのIPアドレス」という意味だそうです。今こうなっているのが問題です。
「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典より)

ちなみに、本当にネットワークの問題なのか?ということを確かめるために一旦ローカルPCにEXPOをインストールしてQRコードを読み取ると問題なく初期画面が表示されました。IPアドレスも192.~~だったのでやはりネットワーク関連の問題なんだな〜と言うことを実感しました。

192.168.2.104って何?

192.168.2.104 は、ローカルやプライベートネットワークなどの特殊な用途のために予約されている IP アドレスです。一般的に公開インターネットには表示されません。

AIが見つけてくれた記事

10.X.X.X、172.X.X.X、192.168.X.XはプライベートIPアドレスといって、IPアドレス枯渇問題に対応したもので、「それぞれの会社や家のLAN内では同じIP使っても問題ないよね」というものだそうです。
@ITネットワーク用語辞典より)

手段

  • .envファイルに環境変数REACT_NATIVE_PACKAGER_HOSTNAMEを使ってローカルPCのIPアドレスを設定する。
  • docker-compose up時に読み込ませる

Docker Composeって何?

Compose とは、複数のコンテナを定義し実行する Docker アプリケーションのためのツールです。Compose は YAML ファイルを使い、アプリケーションのサービスを設定します。コマンドを1つ実行するだけで、設定内容に基づいた全てのサービスを生成・起動します。

Compose を使うには、基本的に3つのステップを踏みます。

  1. アプリケーションの環境を Dockerfile に定義すると、アプリケーションはどこでも再構築できるようになります。
  2. アプリケーションを構成するサービスを docker-compose.yml ファイル内に定義すると、各サービスは 独立した 環境で同時に実行できるようになります。
  3. docker compose up を実行すると、この Docker compose コマンド によって、アプリ全体を起動・実行します。あるいは、 docker-compose バイナリを使えば、 docker-compose up でも実行できます。
Docker Compose 概要 – Docker公式

Docker Composeとは複数のコンテナを実行するためのもので、下準備としてDockerfile(Dockerイメージを設定するファイル)とdocker-compose.yml(複数のDockerFileを束ねるファイル) が必要ということらしいです。

docker-compose.ymlにREACT_NATIVE_PACKAGER_HOSTNAMEを設定

    environment:
      - REACT_NATIVE_PACKAGER_HOSTNAME=${LOCAL_IP_ADDR}

.envにLOCAL_IP_ADDRを設定(直書きしたくない情報をここに書く)

LOCAL_IP_ADDR=192.168.2.104

get-local-ip-addr.sh(Macの仕様でコロコロ変わるIPアドレスを取得して.envに書き直すスクリプトだそうです)

#!/bin/bash

IP=`ifconfig | grep inet | cut -d " " -f2 | grep "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | awk 'NR==2'`
sed -i".bak" -e "/LOCAL_IP_ADDR=/d" .env
echo "LOCAL_IP_ADDR=$IP" >> .env

ここまで準備したものをMakefile(自作のコマンド)で使います。

expo_sample:
	chmod +x ./get-local-ip-addr.sh
	./get-local-ip-addr.sh
	docker-compose up -d
	docker-compose exec expo_sample bash --login

1行目:shファイルの実行権限を与えて、
2行目:shファイルを実行して(IPアドレスが.envに書き込まれる)、
3行目:docker-compose.ymlに書いてある通りにコンテナを起動して、
4行目:Dockerコンテナに接続します。

この一連の流れが自作した「make expo_sample」コマンドで実行されます。

「docker ps」でコンテナが起動しているか確認します。

設定通りに起動しました!

Expoをインストールします。

root@900d093c60e4:/# node --version
v20.18.0
root@900d093c60e4:/# npx create-expo-app@latest quiz
Need to install the following packages:
create-expo-app@3.0.0
Ok to proceed? (y) y

✔ Downloaded and extracted project files.

作られたプロジェクトフォルダに移動して、中身を確認します。色々作られています。

root@900d093c60e4:/# cd quiz
root@900d093c60e4:/quiz# ls -la
total 828
drwxr-xr-x   9 root root   4096 Oct 17 07:52 .
drwxr-xr-x   1 root root   4096 Oct 17 07:51 ..
-rw-r--r--   1 root root    119 Oct 17 07:51 .gitignore
-rw-r--r--   1 root root   1742 Oct 26  1985 README.md
drwxr-xr-x   3 root root   4096 Oct 17 07:51 app
-rw-r--r--   1 root root    773 Oct 17 07:51 app.json
drwxr-xr-x   4 root root   4096 Oct 17 07:51 assets
-rw-r--r--   1 root root    108 Oct 26  1985 babel.config.js
drwxr-xr-x   4 root root   4096 Oct 17 07:51 components
drwxr-xr-x   2 root root   4096 Oct 17 07:51 constants
drwxr-xr-x   2 root root   4096 Oct 17 07:51 hooks
drwxr-xr-x 743 root root  28672 Oct 17 07:52 node_modules
-rw-r--r--   1 root root 754569 Oct 17 07:52 package-lock.json
-rw-r--r--   1 root root   1353 Oct 17 07:51 package.json
drwxr-xr-x   2 root root   4096 Oct 17 07:51 scripts
-rw-r--r--   1 root root    242 Oct 26  1985 tsconfig.json

「npx expo start」すると、、

IPアドレスがPCと同じになりました!

スマホとPCのIPアドレスが違う問題

早速QRコードを読み込んでみたのですが、同じ接続エラーが出てしまいました。

調べてみると、iPhone側もセキュリティ重視でランダムにIPアドレスを割り振るようです。

iPhone:192.168.1.2
PC:192.168.1.6

なのでiPhone側で手動で設定します。

IPアドレス揃えても接続出来ず

PCのIPアドレスと揃えたのにタイムアウトしてしまいました…。
アプリの設定を見てローカルネットワーク権限許可してる事も確認済みです。

なんでだ…

解決

Expoが使うポートが変わった

「8081 ポート 19000」で検索して出てきました。

Expo CLI now defaults to port 8081 for all projects, rather than 19000.」
(Expo CLI は、すべてのプロジェクトでデフォルトのポート 19000 ではなく 8081 を使用するようになりました。)

Expoキャッチアップ会 〜Expo SDK 49まとめ〜 (2023/09/05) – Zenn

なので、docker-compose.ymlを変更しました。

    ports:
      - "8081:8081"

これでPCで初期画面を表示することはできましたが、スマホでは出来ず、、

トンネル接続タイプ…でプロキシ URL…を介して接続する

Expo Clientがうまくいかない場合 – @hitotchさん

「初回ビルドが遅すぎてClient側が待てなくてタイムアウトすることもあります。。。
 いろいろ試してダメな場合は、ConnectionでTunnelを選んでやり直してみてください。」

ということだったのですが、その設定をする画面を見つけられなかったので、

expo app がつながらなくなった – @minahow3さん を参考にすることにしました。

「トンネリングという方法を用いて、プロキシ URL を介して開発サーバーに接続する。」というのを実行しました。

# @expo/ngrokのインストール
npm i -g @expo/ngrok
# トンネルURLから開発サーバを起動
npx expo start --tunnel

これでついにスマホで見れるようになりました!

まとめ

プライベートネットワークで使われるIPアドレスがわかった

10.X.X.X、172.X.X.X、192.168.X.X

これらを見たら「外部と繋がってない、ここだけのネットワークなんだな」ということが分かりました。

Dockerfileとdocker-compose.yml

Dockerfileは必須ではない。自分でDockerイメージを作りたい時に使う。

docker-compose.ymlは、前に使った「docker run」コマンドの内容をファイルにまとめた感じ。

docker run こんなの↓

[LOCAL]$ docker run \
-it \
-p 13000:3000 \
-v /Users/hoge/workspaces/docker:/app \
--name node20.18-docker \
-w /app \
node:20.18-bullseye-slim