Nginx + Vue(Vite) + Flask + Dockerで開発環境を構築してみた

はじめに

私の働いている企業ではアプリ開発の際、個人の環境に左右されないようにDockerを使用して開発を行っています。Nginx + Vue(Vite) + Flaskを使用した構成にした際に詰まった部分がありましたので、備忘録として残しておきます。

構成

アプリをデプロイする際にはフロントエンドをビルドしてNginx内に配置しますが、開発時にはホットリロードの効いた状態で変更を確認しながらサクサク進めたいものです。最初はnpm run devでフロントエンドサーバーを立てて開発していましたが、やはりバックエンド側と通信がしたくなります。そこでローカル開発用でdocker-composeを以下のように構成し、Dockerのコンテナ間通信を使用してフロントエンドとバックエンドを繋げようと考えました。

docker-compose.yaml
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/src

Nginxは以下のように設定してあり、ホストマシンの4000番ポートへのアクセスをfrontendコンテナへプロキシするようになっています。

nginx_local.conf
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のサーバー設定から許可しました。

JavaScript
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を編集しました。

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;
    }
}

無事にホットリロードも機能して、快適な開発環境を得られました。めでたし。

参考にした記事

この記事を執筆するにあたり、以下の記事を参考にさせていただきました。

NginxのリバースプロキシでWebソケットを通す際の設定

コメント

タイトルとURLをコピーしました