Open8

Docker Desktop から Rancher Desktop に変更したときのトラブルシューティング

bisquebisque

環境

  • MacBook Pro(2021, Apple M1 Pro)
  • MacOS: 12.6.1
  • Docker Desktop: 4.13.1
  • Rancher Desktop: 1.6.2

※書いている途中で変わる(上がる)可能性があります

Dockerの構成

Railsアプリケーションの開発環境として使用しているものです。
必要な情報だけ記載しています。

docker-compose.yml
version: "3"

volumes:
  db-data:
  backend-bundle:
  backend-vendor:
  backend-tmp:

services:
  db:
    image: postgres:14
    volumes:
      - db-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
  backend:
    ports:
      - "8080:8080"
    command: > # 残っているかもしれないプロセスを消してから立ち上げる
      /bin/sh -c "rm -f tmp/pids/server.pid &&
      bundle exec rails s -p 8080 -b '0.0.0.0'"
    volumes:
      # コンテナのグローバルにインストールされたgemを、Docker Volumeにキャッシュとして保存する
      - backend-bundle:/usr/local/bundle
      # アプリケーションのソースコードをコンテナにマウントする
      - ./backend:/app
      # 以下はパフォーマンスのためローカルをマウントしない
      - backend-vendor:/app/vendor
    depends_on:
      - db
    tty: true
    stdin_open: true
bisquebisque

まずは移行方法

前提としてDocker Desktopを使っているものとします。

  • Docker Desktopを終了します(アンインストールしなくてOK)
  • Rancher Desktopをインストール・開始

コンテキストの切り替え

Docker CLI が Docker Desktop or Rancher Desktop のコンテキストを切り替えることができます。Rancher Desktopをインストール直後は、コンテキストが rancher-desktop になります。コンテキストの確認は docker info でできます。

Docker Desktopに切り戻す場合

  • Rancher Desktopを終了します
  • Docker Desktopを開始します
  • docker context use desktop-linux

Rancher Desktopに切り替える場合

  • Docker Desktopを終了します
  • Rancher Desktopを開始します
  • docker context use rancher-desktop
bisquebisque

Railsの再読み込みが効かない

Railsではdevelopment環境のデフォルトで、ファイルの変更を検知して再読込する機能があります。これによりRailsサーバーを再起動せずとも変更を反映することができます。Rancher Desktopにしたところ、これが効かなくなりました。

再読み込みの仕組み

デフォルトのRailsは、変更されたファイルをイベンテッドファイルモニタで検出しますが、自動読み込みパスを調べてファイル変更を検出することも可能です。これは、config.file_watcherの設定で制御されます。
https://railsguides.jp/autoloading_and_reloading_constants.html#再読み込み

config.file_watcherActiveSupport::FileUpdateChecker にすればいいという情報は見つかるのですが、 デフォルトのイベンテッドファイルモニタがなぜ効かないのか気になります。イベンテッドファイルモニタは、 gem listen が行っているようです。

デフォルトのRailsではActiveSupport::FileUpdateChecker、およびActiveSupport::EventedFileUpdateChecker(これはlistenに依存します)が指定されます。
https://railsguides.jp/configuring.html#config-file-watcher

listenのissueを探してみると、inotify watches was used up という情報が見つかりました。
https://github.com/guard/listen/issues/559#issuecomment-1186346254

inotify についてRancher Desktopのissueを探してみると、どうやら初期値がすごく小さいという情報が見つかりました。
https://github.com/rancher-sandbox/rancher-desktop/discussions/1567

案内されたissueに初期値の変更手順が書いてあります。
https://github.com/rancher-sandbox/rancher-desktop/issues/713#issuecomment-1009377616

bisquebisque

まずは一時的に変更してみる

コンテナに接続して現状の値を確認

# cat /proc/sys/fs/inotify/max_user_watches
30515

変更してみる

# echo fs.inotify.max_user_watches=524288 | tee -a /etc/sysctl.conf
# sysctl -p
sysctl: permission denied on key "fs.inotify.max_user_watches"

このkeyはpermission deniedって言われてしまう。
コンテナを再起動してみてもダメ。

なるほど、ホスト側のVMと共有しているので、ホスト側を変えないとダメらしい
https://qiita.com/enta0701/items/bc9f8f8c780222979784

VMにsshするには、rdctlを使えばいいらしい
https://github.com/rancher-sandbox/rancher-desktop/discussions/2324

ローカルにrdctl が入っていない?

$ rdctl shell
zsh: command not found: rdctl

パスが通っていないだけでした。max_user_watches の値がコンテナと同じであることが確認できた。

$ ~/.rd/bin/rdctl shell
# cat /proc/sys/fs/inotify/max_user_watches
30515

VMの中でmax_user_watchesを変えてみる。

$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
fs.inotify.max_user_watches=524288
$ sudo sysctl -p
fs.inotify.max_user_watches = 524288
$ cat /proc/sys/fs/inotify/max_user_watches
524288

コンテナを再起動して、コンテナの中でも確認。

# cat /proc/sys/fs/inotify/max_user_watches
524288

やったね。

がしかし、再読み込みはまだ効かず🥲

bisquebisque

Docker Desktopの方はどうなのか?

# cat /proc/sys/fs/inotify/max_user_watches
1048576

同じ数にしてみよう

$ echo fs.inotify.max_user_watches=1048576 | sudo tee -a /etc/sysctl.conf
$ sudo sysctl -p

やっぱり再読み込みは効かない。なにか別の問題があるのだろう。

bisquebisque

ちなみに config.file_watcher = ActiveSupport::FileUpdateChecker にすると、再読み込みは効きました。

bisquebisque

ローカルに立ち上げたフロントエンドサーバーからコンテナにアクセスできない

最初は問題が起きていなかったが、最近になってできなくなってしまった。

環境

  • MacOS: 12.6.1
  • Rancher Desktop: 1.6.2

状況

  • APIサーバーをコンテナで起動する。port: 8080。ブラウザやAPIクライアントからはアクセスできる。
  • フロントエンドサーバーをローカルで起動する。port: 3000。APIサーバーにアクセスしようとすると Error: connect ECONNREFUSED ::1:8080 となる。
    • 該当のURLに対してブラウザからアクセスすると成功する。
    • APIサーバーをDocker Desktopで起動するとフロントエンドサーバーからのアクセスに成功する。
bisquebisque

フロントエンドサーバーからのAPIサーバーの宛先ホストを localhost から 127.0.0.1 にすることでアクセスに成功した。ほかのブラウザやcurlなどからは localhost で接続できているのに、なぜだろう。