🌏

ExpoをDocker上で動かしたい! | React Native+Expo+Docker

2021/12/05に公開

本記事の内容

iOS/Androidアプリを、ほとんど同じコードで開発できてしまうフレームワークであるReact Native。そしてそれを支える便利なツールチェーンであるExpo。また、環境構築での悩み・ストレスを吹っ飛ばしてくれるDocker。

どれも便利すぎて大好きな技術ですが、、、「これらを組み合わたら(ほとんど)コマンド1つでゼロからアプリ開発環境ができるんじゃね!?」と思い、やってみました!! (需要が有るかはさておき...)

サンプルコード

こちらに上げています。

試す場合は以下のコマンドを順に実行してみて下さい。(Expo Goは前提としています。端末はホストPCと同じネットワーク内で)

  1. git clone https://github.com/Hibagon1go/react_native_expo_docker_sample.git
  2. cd react_native_expo_docker_sample
  3. make expo_sample
  4. expo init your_app_name
  5. cd your_app_name
  6. expo start
  7. ホストPCと同じネットワーク内の端末で、Expo Goアプリからアプリを起動

環境

Dockerさえ入っていればOKです!

コードの内容

基本的には上記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を作成します。

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 initexpo startの動作が少し重いような気がします。これはPCのスペックにもよるのかもしれませんが。

また、ローカルIPアドレス取得シェルスクリプトをmacOS以外にも使えるよう書けるといいなあと思います()

まとめ

Dockerを用いて、コマンドをほぼ叩かずともexpoの開発環境を作れました!需要があるかわかりませんが、ぜひ参考になればと思います。
なお、記事の内容に誤りや不備がございましたら、指摘していただけるとありがたいです🙇‍♂️

おまけ

弊社では、現役東大生の家庭教師がかんたんに見つかる家庭教師個人契約アプリカテアプリ東大生を開発、運営しています。ぜひインストールしてみてください!
UIUXでアドバイスなどあればぜひお願いします!

Discussion