ExpoをDocker上で動かしたい! | React Native+Expo+Docker
本記事の内容
iOS/Androidアプリを、ほとんど同じコードで開発できてしまうフレームワークであるReact Native。そしてそれを支える便利なツールチェーンであるExpo。また、環境構築での悩み・ストレスを吹っ飛ばしてくれるDocker。
どれも便利すぎて大好きな技術ですが、、、「これらを組み合わたら(ほとんど)コマンド1つでゼロからアプリ開発環境ができるんじゃね!?」と思い、やってみました!! (需要が有るかはさておき...)
サンプルコード
こちらに上げています。
試す場合は以下のコマンドを順に実行してみて下さい。(Expo Goは前提としています。端末はホストPCと同じネットワーク内で)
git clone https://github.com/Hibagon1go/react_native_expo_docker_sample.git
cd react_native_expo_docker_sample
make expo_sample
expo init your_app_name
cd your_app_name
expo start
- ホストPCと同じネットワーク内の端末で、Expo Goアプリからアプリを起動
環境
Dockerさえ入っていればOKです!
コードの内容
- https://qiita.com/wf-yamaday/items/2ad9f230ce0a230d88c0
- https://qiita.com/hidenoritoki/items/9cd972ba102d12faec0e
基本的には上記2つの記事を見て、いいとこ取りをしました。
ここではポイントを3つ程、ご紹介したいと思います。
1. IPアドレスの設定
通常Expoでアプリを開発する際は、ホストPCでexpoサーバーを動かし、そこに端末のExpo Goアプリからアクセスしてアプリを動かします。
アクセスの方法は、端末が、自分と同じネットワークの中からexpoサーバーが走っているホストを探します。つまり、端末とexpoサーバーのローカルIPアドレス(のネットワーク部分)が同じである必要があります。
さて今回は、ホストPCのdockerコンテナ上でexpoサーバーが動かし、そこに端末からアクセスしたいわけです。もちろん今回も、端末とexpoサーバーは同じネットワークに存在しなければなりません。
しかし何も設定せずにやろうとすると、端末からexpoサーバーにアクセスできません。コンテナはホストPCのIPアドレスを知らず、コンテナ自身の(ホストPCとは関係のない)IPアドレスでexpoサーバーが走るので、端末とexpoサーバーは同じネットワークにいないことになってしまいます。
(↑↑コンテナ自身のIPアドレスは172.22.0.2であると確認)
(↑↑何もしないと、コンテナ自身のIPアドレス172.22.0.2でexpoサーバーが走っているのがわかります)
そこで、コンテナにホストPCのローカルIPアドレスを知らせ、expoサーバーをそこで動かしてやるようにします。具体的には、dockerコンテナの中に、環境変数REACT_NATIVE_PACKAGER_HOSTNAME
としてホストPCのローカルIPアドレスを設定します。この環境変数は、.envファイルに書いておくとdocker-compose up
時に勝手に読み込んでくれます。
また、ローカルIPアドレスは、移動することなどで変化し、その度に調べて書き直すのは大変なので、ローカルIPアドレスの取得処理をシェルスクリプトに書いて、自動で.envファイルに書き込まれるようにすると便利です。ただし、参考した記事によると、これはmacOS依存の記述のようなので注意してください。
これで、無事にホストPCのローカルIP(192.168.2.104)でexpoサーバーが動きます🎉
2. ポートの設定
次はポートの設定です。基本的には、ホストとコンテナの間でポートがマッピングされていればOKで、docker-compose.ymlファイルにこのように記述すれば良いです。
ports:
- "19000:19000"
- "19001:19001"
- "19002:19002"
しかし、参考にした記事のように docker-compose build
し、docker-compose run
してコンテナの中に入り、そこでexpoサーバーを立ち上げて端末からアクセスしようとすると、うまくいきません。
なぜだー、、と思ったんですが、docker runの公式ドキュメントやこちらの記事を読んで、docker-compose run
時には、 docker-compose.ymlで記述しているポート情報は反映されないことを知りました。(他のコンテナとのポートの競合の防止とかなんとか)
ということで、親の顔より見たdocker-compose up
を使い、このようなコマンドにすると、無事想定通りに動きました🎉
3. Makefileでコマンド1発!!
最後に、今までの手順を一つのコマンドで一気にやってくれるように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
ホストPCのローカルIPを取得、.envに書き込み、コンテナを立ち上げて接続するという感じです。
make expo_sample
で実行できます。
コンテナに入れたら、expo init your_app_name
でexpoアプリの雛形を作り、cd your_app_name
の後、expo start
でexpoサーバーを走らせます!そして、端末からExpo Goを用いてアクセスし、アプリを動かせます🎉
なお、ローカルにファイルをマウントしているので、ローカルでコードを変更したら、ちゃんとアプリもホットリロードされるはずです!
気になる点
コンテナ内でサーバーを走らせているせいか、expo init
やexpo start
の動作が少し重いような気がします。これはPCのスペックにもよるのかもしれませんが。
また、ローカルIPアドレス取得シェルスクリプトをmacOS以外にも使えるよう書けるといいなあと思います()
まとめ
Dockerを用いて、コマンドをほぼ叩かずともexpoの開発環境を作れました!需要があるかわかりませんが、ぜひ参考になればと思います。
なお、記事の内容に誤りや不備がございましたら、指摘していただけるとありがたいです🙇♂️
おまけ
弊社では、現役東大生の家庭教師がかんたんに見つかる家庭教師個人契約アプリカテアプリ東大生を開発、運営しています。ぜひインストールしてみてください!
UIUXでアドバイスなどあればぜひお願いします!
Discussion