はじめに
社内のFEエンジニア向けにプロジェクト構成の考え方を教える勉強会を企画しています。この勉強会では、あるアプリケーションを作成することをベースに、プロジェクトの考え方や構成方法を具体的に解説していくことを想定しています。参加者はFEエンジニアで、FE領域に専門知識を持つ人たちです。しかし、今回のプロジェクトでは専用のバックエンドも必要となるため、事前にFEとBEの基本部分を作成し、Gitを通じて配布することにしました。FE側のテンプレートにはViteを採用し、Dockerで簡単に起動できるようにします。また、エンドポイントの振り分けにはNginxを使用する予定です。
よしこれでいこう!とこの初期状態のプロジェクトの作成をし始めたところ、DockerでViteとNginxを起動してルーティングするところまではいけたのですがなぜか502エラーでFEにアクセスできないという問題に直面しました。問題の解決の方法自体は簡単でしたが、その答えにたどり着くまでに時間がかかったため、今回はその解決策を忘備録としてまとめることにしました。
前提条件
- Dockerを使っています
- この記事ではBEには触れません
- FEのテンプレートはViteなので、Viteの場合の解決策になります
- NginxやDockerの設定は自分の知識の中からやっています、最適な設定ではない可能性があります
- 今回はあくまでDocker起動して、Nginxを通してViteで起動してるFEを閲覧できるようにするまでです。Nginxの説明やViteの詳細には入りません
まずは起動を試みる
Vite
+ Docker
+ Nginx
は初めてだったので、色々調べながら、とりあえず起動までは漕ぎ着けます。
Nginxの設定
まずはNginxの設定から。今回はDockerfile.dev
とdefault.conf
だけ設定します。
FROM nginx
COPY ./default.conf /etc/nginx/conf.d/default.conf
upstream frontend {
# "client"の部分がFEのためのDockerサービス名
server client:5173;
}
server {
listen 80;
server_name localhost;
location / {
# "frontend"の部分がupstreamを指している
proxy_pass http://frontend/;
# 下の設定はFEのコードがHot Reloadされるために設定している
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Viteの設定
Viteはただpnpm create vite
を実行して作成されたファイルと、Dockerfile.dev
です。
.
├── Dockerfile.dev
├── README.md
├── index.html
├── node_modules
├── package.json
├── pnpm-lock.yaml
├── public
│ └── vite.svg
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ └── react.svg
│ ├── index.css
│ ├── main.tsx
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
Dockerfile.dev
の中身は以下です。
FROM node:20-alpine
WORKDIR /app
COPY package.json ./
RUN npm install -g pnpm
RUN pnpm install
COPY ./ ./
CMD ["pnpm", "run", "dev"]
docker-compose.ymlの設定
今回は背景がDockerで起動できるようにして受講者にはFEだけに集中できるようにすることなので、docker composeを起動できるようにdocker-compose.yml
を作成します。
version: "3"
networks:
dev:
driver: bridge
services:
nginx:
restart: always
build:
dockerfile: Dockerfile.dev
context: ./nginx
ports:
- 5176:80
volumes:
- ./nginx:/etc/nginx/conf.d/
depends_on:
- client
client:
build:
dockerfile: Dockerfile.dev
context: ./frontend
volumes:
- /app/node_modules # container内のnode_modulesを使用
- ./frontend:/app
expose:
- 5173
stdin_open: true
中身はそんなにないです、docker composeを使ってnginx
ディレクトリにあるDockerfile.dev
とfrontend
ディレクトリにあるDockerfile.dev
を使ってDockerを起動できるようにします。
特筆すべき点は、nginxはport 5176を聞いてそれをport 80に流すようにしていて、FEはport 5173を解放していることです。default.conf
内を見てもらうと、nginx
自体はport 80を聞いていて、それを最終的にport 5173にマッピングしています。これは学習用のアプリケーションのため、あざとマッピングがあっちこっちいくようにしています。
起動
ここまできたら、起動させましょう。プロジェクトのルートでコンソールを開いて、docker compose up -d --build
を実行します。
筆者PC @~/dev/vite-with-nginx: docker compose up -d --build
~~ビルド情報~~
[+] Running 2/3
⠧ Network vite-with-nginx_default Created 0.7s
✔ Container vite-with-nginx-client-1 Started 0.6s
✔ Container vite-with-nginx-nginx-1 Started 0.2s
筆者PC @~/dev/vite-with-nginx:
最終的に上記の表示になっていれば問題なしです。
ブラウザを開いてlocalhost:5176を開く。
なんで?
設定的には、portも開いてるはずだし5176もアクセスできているし....502ということはnginxにはちゃんとアクセスできている。
さらに、別のコンソールを開いてpnpm run dev
をすると普通にViteのプロジェクトを開ける。
ということは、何かでnginxからViteにアクセスできていないことになる。
結論
かなり調査をして、原因がわかった。
どうやら、Dockerを使ってるためかViteのhostを晒してあげる必要があるらしい。
設定はとても簡単で、vite.config.ts
を開いて、server.host
をttrue
にするだけ。
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: true,
},
plugins: [react()],
});
開けた....
これを見つけるのに3時間くらい無駄にしました。
最初は、nginxが悪いのかとその辺りを調べていました。ローカルでViteを起動する分にはちゃんとアクセスできてたので、Viteは問題ないはず!と思い込んでViteが問題だとは思っていませんでした。
あとがき
皆さんも、ここは問題ないはず!という思い込みはやめましょう。