musicLineアプリ開発日記

作曲を誰でも楽しく簡単に♪

ローカル環境にサーバーを構築する

musicLineのテストサーバーをローカル環境に構築してデバッグを簡単にした話。
WindowsでDockerとVSCodeを使って、サーバーをデバッグしたい時に役立つ内容です。


課題

musicLineでは、コミュニティ(クラウド)にデータをアップロード・ダウンロードする際は、Herokuのサーバーを経由してデータをやり取りしています。
Herokuサーバーでは、DBでデータを管理しており、Androidの端末からサーバーへAPIを投げてDBでデータ操作をしています。

コミュニティ
構成図

現在、デバッグ用のテストサーバーもHerokuにあるため、デバッグする際はコードを修正するだけではなく、Herokuサーバーにも修正したコードを適用する必要があります。
このデプロイ作業が地味に手間であり、コードを修正する度に発生するため、デバッグがしづらい状況でした。

また、2022年秋くらいにHerokuのプランが変更となり、今まで無料プラン内に収まっていたデバッグ用のテストサーバーが有料になってしまいます。

blog.jnito.com

これを機会に、サーバーのデバッグ環境をローカルに移行することを考えました。


環境構築

サーバー環境をローカルのPCに作るために、Dockerを使用しました。

docs.docker.com

そのまま開発環境をローカルのPCに作ってもいいですが、様々な開発環境が混同すると思わぬエラーとかに引っ掛かったり、インストールしたパッケージもよくわからなくなります。
かといってインストールしたパッケージを管理するのも面倒くさい。。
なのでDockerのコンテナーを使用します。

Dockerで環境を作ることのメリット
www.brain-gate.net


また、VSCodeの開発環境をDockerの仮想環境に作れるように、VSCode拡張のDev Containerを使用します。

ローカルと仮想の開発環境を同期
(引用:https://code.visualstudio.com/docs/devcontainers/containers)

1. Docker環境

以下のURLを参考にDocker環境を作ります。

chigusa-web.com

ポイント

  • DockerはLinux環境で動作する
  • WindowsLinux環境を作るにはWSL2を使う

2. VSCode環境

以下のURLを参考にVSCode環境を作ります。

code.visualstudio.com

ポイント

  • Dev Containers拡張機能を使用
  • devcontainer.jsonファイルを作成
  • Dev Containerを起動する前にDockerを立ち上げる

3. Android側の設定

APIに使用していたIPアドレスをHerokuからローカルホストに変更します。
ローカルホストはデバック環境によって異なるため、動的に取得できるようにします。
以下のコードはデバッグ時のみ(BuildConfigで)、ローカルホストを参照できるように、build.gradleに記載してます。

productFlavors {
    develop {
        ...

        // REF:[Network]ローカルホストアドレスの動的取得
        def localHostAddress = InetAddress.getLocalHost().getHostAddress()

        buildConfigField "String", "HOST_ADDRESS", "\"http://${localHostAddress}:4567/\""
    }
}

また、デバッグ時は平文(http)で通信を行いたいので、AndroidManifestにandroid:usesCleartextTraffic="true"を追記します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    ...
    <application android:usesCleartextTraffic="true" />
</manifest>
デバッグ時のみ設定を適用 http通信はデバッグ時のみ適用されるようにしたいので、src/debug/AndroidManifest.xmlに記載します。
qiita.com

4. DBをローカルへ移行

HerokuにあるDBをローカルへ移行する時は、TablePlusの機能を使いました。

TablePlus

TablePlusでHerokuのDBをBackupして、ローカルにRestoreすれば簡単に移行できました。


問題発生

環境構築ですんなり成功することはないですよね。
私の環境で発生した問題と解決方法を載せておきます。

1.Dockerを起動できない

WSL2とDockerDesktopをインストールしたのに、Dockerがスタートできない!
DockerDesktopのメニュー下は黄色い表示で一時停止状態でした。

Docker Desktopのメニュー

Ubuntuは前にインストールしたもので、UbuntuのWSLバージョンを2にできていなかったことが原因でした。

zenn.dev

wsl --set-version Ubuntu 2コマンドでWSLバージョンを2に変更して解決しました。

2.Dev Containerで開けない

Dev Containerのコンテナーでファイルを開くとエラーが発生。

[7639 ms] Error: An error occurred setting up the container.
[7639 ms]     at loe (c:\Users\*****\.vscode\extensions\ms-vscode-remote.remote-containers-0.266.1\dist\spec-node\devContainersSpecCLI.js:1832:2820)
[7639 ms]     at process.processTicksAndRejections (node:internal/process/task_queues:96:5)
[7639 ms]     at async Poe (c:\Users\*****\.vscode\extensions\ms-vscode-remote.remote-containers-0.266.1\dist\spec-node\devContainersSpecCLI.js:1899:2301)
[7639 ms]     at async Zf (c:\Users\*****\.vscode\extensions\ms-vscode-remote.remote-containers-0.266.1\dist\spec-node\devContainersSpecCLI.js:1899:3278)
[7640 ms]     at async aue (c:\Users\*****\.vscode\extensions\ms-vscode-remote.remote-containers-0.266.1\dist\spec-node\devContainersSpecCLI.js:2020:15276)
[7640 ms]     at async oue (c:\Users\*****\.vscode\extensions\ms-vscode-remote.remote-containers-0.266.1\dist\spec-node\devContainersSpecCLI.js:2020:15030)
[7652 ms] Exit code 1
[7657 ms] Command failed: C:\Users\*****\AppData\Local\Programs\Microsoft VS Code\Code.exe --ms-enable-electron-run-as-node c:\Users\*****\. ...
[7658 ms] Exit code 1

VSCodeのDevContainerを開くときに表示されたエラーでは原因がわからず。。
まずはDockerのコンテナーが適切に起動できるかを試してみました。

PowerShelldocker compose -f .devcontainer/docker-compose.yml buildコマンドをして、Dockerのymlファイルをビルドします。

 => ERROR [6/6] RUN bundle install                                                                                 0.8s
------
 > [6/6] RUN bundle install:
#0 0.717 Your Ruby version is 2.7.7, but your Gemfile specified 2.7.6
------
failed to solve: executor failed running [/bin/sh -c bundle install]: exit code: 18

これでエラーの原因が分かりました。
HerokuとDockerのコンテナ環境でRubyのバージョンが異なっていたようです。

github.com

GemfileでRubyのバージョン指定をruby "~> 2.7.6"に変更することで解決しました。

3. Android端末からAPIを投げても反応がない

Dockerのコンテナーログを見ても、APIが投げられた痕跡がない。。

結果、セキュリティに引っ掛かってました。

qiita.com

Windows Defenderファイアーウォールの規則で特定のポートを解放することで解決!
と安心すると、しばらくしてまた反応がなくなりました。

結果、セキュリティに引っ掛かってました。
今度はESETの方

eset-support.canon-its.jp

ローカルPCでセキュリティソフトを入れている場合は、設定を要チェックです。

ESETのブロック確認 ESETの場合設定 > ネットワーク保護 > トラブルシューティングウィザード
にブロックされたデバイスが表示されます。
セキュリティに引っ掛かってそうな時に確認するといいかも。

ファイアウォールやセキュリティソフトの設定を確認することで解決しました。

4. Android端末からAPIを投げても反応がない2

環境構築 > 3. Android側の設定APIを投げるローカルのIPアドレスAndroidプロジェクトをビルドする時に、動的に設定するようにGradleファイルに記述しました。
でもそのIPアドレスの取得方法では、複数のネットワークがある場合は間違ったIPアドレスが取得される可能性があることがわかりました。
Dockerの起動時にプロジェクトをビルドすると、Linuxの仮想環境が立ち上がる為、ローカルホストを取得する時に、WifiIPアドレスではなくWSLのIPアドレスを取得されることが原因でした。

ネットワーク構成
1番目にWSL、4番目にWi-Fiとなり、WSLがローカルホストになる

// REF:[Network]Wifiローカルホストアドレスの動的取得
def wifiNetwork = NetworkInterface.getNetworkInterfaces().toList().stream()
        .filter(network -> network.name == "wlan0")
        .findFirst().get()
def wifiHostAddress = wifiNetwork.inetAddresses.toList().stream()
        .filter(net -> net instanceof Inet4Address)
        .findFirst().get().hostAddress

適切なローカルIPアドレスを取得することで解決しました。

参考

zenn.dev

qiita.com

zenn.dev

qiita.com