🏗️
DevContainer上で動かしているViteサーバーにホスト側からアクセスできない時の対処方法
状況
npm run dev
で開発サーバーをDevContainer内で立ち上げ、ホスト側のChromeからアクセスしたところ接続ができない。
ホスト側からDevContainerのポートが空いているかを確認
lsof -i:ポート番号
コマンドで指定したポート番号が空いているかを確認することができる。
lsof -P -i:5173
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Code\x20H 1033 me 29u IPv4 0xd9abe49ae1cac34 0t0 TCP localhost:5173 (LISTEN)
ポートは空いているようだ。
リモート側からViteサーバーの応答があるかを確認
curl http://localhost:5173
コマンドで初期画面のHTMLが帰ってくることで確認できる
$ curl http://localhost:5173
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>New Remix App</title><meta name="description" content="Welcome to Remix!"/></head><body><div style="font-family:system-ui, sans-serif;line-height:1.8"><h1>Welcome to Remix</h1><ul><li><a target="_blank" href="https://remix.run/tutorials/blog" rel="noreferrer">15m Quickstart Blog Tutorial</a></li><li><a target="_blank" href="https://remix.run/tutorials/jokes" rel="noreferrer">Deep Dive Jokes App Tutorial</a></li><li><a target="_blank" href="https://remix.run/docs" rel="noreferrer">Remix Docs</a></li></ul></div><script>((STORAGE_KEY, restoreKey) => {
if (!window.history.state || !window.history.state.key) {
let key = Math.random().toString(32).slice(2);
window.history.replaceState({
key
}, "");
}
try {
let positions = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || "{}");
let storedY = positions[restoreKey || window.history.state.key];
if (typeof storedY === "number") {
window.scrollTo(0, storedY);
}
} catch (error) {
console.error(error);
sessionStorage.removeItem(STORAGE_KEY);
}
})("positions", null)</script><link rel="modulepreload" href="/@id/__x00__virtual:remix/browser-manifest"/><link rel="modulepreload" href="/app/entry.client.tsx"/><link rel="modulepreload" href="/app/root.tsx"/><link rel="modulepreload" href="/app/routes/_index.tsx"/><script>window.__remixContext = {"url":"/","basename":"/","future":{"v3_fetcherPersist":false,"v3_relativeSplatPath":false,"v3_throwAbortReason":false,"unstable_singleFetch":false},"isSpaMode":false,"state":{"loaderData":{"root":null,"routes/_index":null},"actionData":null,"errors":null}};</script><script type="module" async="">import "/@id/__x00__virtual:remix/inject-hmr-runtime";import "/@id/__x00__virtual:remix/browser-manifest";
import * as route0 from "/app/root.tsx";
import * as route1 from "/app/routes/_index.tsx";
window.__remixRouteModules = {"root":route0,"routes/_index":route1};
import("/app/entry.client.tsx");</script></body></html>
ローカルからはアクセスできるようだ
Vite以外のサーバーを立ち上げて接続を確認
npx serve
で簡単にサーバーを立ち上げてListenできる。
こちらは問題なく立ち上がっているようだ
状況の整理
- DevContainer上ではViteサーバーが立ち上がっている
- ホストマシンからはViteサーバーにアクセス不可
- DevContainer内からはViteサーバーにアクセス可能
- Vite以外のサーバーを立ち上げた場合
- ホストからアクセスできるようになった
上記の理由からViteサーバー周りが怪しいと仮説をたてた。
調査
ViteのドキュメントからServer周りのConfigを調査。
server.hostをtrueにすることで全てのアドレスをListenすることが可能とのこと。
つまり、デフォルトではローカル(DevContainer)のみアクセス可能で、LAN内(ホストマシン含む)は弾かれるようになっているようだ。
解決方法
Viteのコンフィグを以下のように修正することで、ホストマシンからlocalhost:5173でアクセスできるようになる。
vite.config.ts
import { vitePlugin as remix } from "@remix-run/dev";
import { installGlobals } from "@remix-run/node";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
installGlobals();
export default defineConfig({
plugins: [remix(), tsconfigPaths()],
+ server: {
+ host: true,
+ }
});
Discussion