はじめに
私の働いている企業ではアプリ開発の際、個人の環境に左右されないようにDockerを使用して開発を行っています。Nginx + Vue(Vite) + Flaskを使用した構成にした際に詰まった部分がありましたので、備忘録として残しておきます。
構成
アプリをデプロイする際にはフロントエンドをビルドしてNginx内に配置しますが、開発時にはホットリロードの効いた状態で変更を確認しながらサクサク進めたいものです。最初はnpm run devでフロントエンドサーバーを立てて開発していましたが、やはりバックエンド側と通信がしたくなります。そこでローカル開発用でdocker-composeを以下のように構成し、Dockerのコンテナ間通信を使用してフロントエンドとバックエンドを繋げようと考えました。
version: '3'
services:
web:
image: nginx:1.23.3-alpine
ports:
- 4000:80
volumes:
- ../nginx/nginx_local.conf:/etc/nginx/conf.d/default.conf
api:
build:
context: ../api
dockerfile: Dockerfile # Flaskサーバーの立ち上げ
ports:
- 5000:5000
volumes:
- ../api/src:/opt/app/src
frontend:
build:
context: ../frontend
dockerfile: devDockerfile # パッケージインストール後にnpm run dev を実行する
volumes:
- ../frontend/src:/opt/app/srcNginxは以下のように設定してあり、ホストマシンの4000番ポートへのアクセスをfrontendコンテナへプロキシするようになっています。
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
proxy_pass http://frontend:5173/;
}
location /api/ {
proxy_pass http://api:5000/api/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}Nginx経由でVueコンテナ内のサーバーがのぞけない
docker-compose up するとコンテナが立ち上がりますが、4000番ポートにアクセスしても以下のエラーが出てアクセスできません。

調べてみるとviteはデフォルトでは外部からのアクセスを受け付けないようです。外部アクセスを許可するには二通りの方法がありますが、今回はvite.config.jsのサーバー設定から許可しました。
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
host: true, # この部分を追加
}
})Viteのホットリロードが効かない
無事にフロントエンドが表示されるようになりましたが、今度は当初の目的であるホットリロードが効きません。開発者ツールでエラーを見てみるとWebソケット通信ができていないようです。
そもそもホットリロードとは?
Viteのホットリロードは、ブラウザ上に表示されているコンテンツとサーバーがWebソケットを用いて相互通信することで成り立っています。今回はNginxの設定で単純なプロキシのみ行っているため通信ができていないようでした。
そこで以下のようにnginx_local.confを編集しました。
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
location / {
proxy_pass http://frontend:5173/;
}
location /api/ {
proxy_pass http://backend:5000/api/;
}
location /swaggerui/ {
proxy_pass http://backend:5000/swaggerui/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}無事にホットリロードも機能して、快適な開発環境を得られました。めでたし。
参考にした記事
この記事を執筆するにあたり、以下の記事を参考にさせていただきました。

コメント