APIとSPAの両方をnginxで配信すれば,CORS問題が起きない(はず).初心者の僕にはわからないけど,一般的にもやられているのだろうか?今回は例として,Flask製のAPIとVue.js製のSPAでの場合について書く.基本的には他の組み合わせでも同じはず.
dockerで以下のイメージを用意する.
- application server (uwsgi)
- web server (nginx)
- db (mariadb)
ディレクトリ構成は以下を想定.
project_name/
web/
api/
Dockerfile
uwsgi.ini
api/
spa/
dist/
conf/
default.conf
data/db/
docker-compose.yml
ここからは project_name/
にいることを想定します.
version: '3'
services:
api:
build: ./web/api
ports:
- "5000:5000"
depends_on:
- db
volumes:
- ./web/api/api:/usr/local/api/api
nginx:
image: nginx
volumes:
- ./web/conf/default.conf:/etc/nginx/conf.d/default.conf
- ./web/spa/dist:/usr/share/nginx/html
ports:
- "8080:80"
links:
- api # いらないかも
db:
image: mariadb
volumes:
- ./data/db:/var/lib/mysql
ports:
- '3306:3306'
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=1
command:
- --character-set-server=utf8 # これと
- --collation-server=utf8_general_ci # これは大事.mb4は日本語文字化けした
buildはAPIだけでいい.僕はPipenvを愛用しているのですが,Pipenvを使ったFlask製APIのDockerfileの書き方についてはまた書こうと思います.
本番ではdbコンテナ(もしかしたらnginxも)は立てないと思うので,その場合,APIだけ立てればいい.docker-composeの恩恵?余談でした.
nginxの設定ファイルは以下のようにした.僕はnginx.confは触らずに(設定項目をよくわかっていない),default.confだけ書き換えることにしました.
upstream api {
server api:5000; # ここのapiはdockerのservice名
}
server {
listen 80;
location /api {
include uwsgi_params;
uwsgi_pass api;
}
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
}
upstream api
と uwsgi_pass api
の api
は同じであればなんでもいいです多分.
SPA (Vue.js)側で,apiを呼び出すと思うのですが,上記の設定だと,この時のアドレスは /api
になる. http
とかもいらないです.ここ大事.
Vue.jsだと以下のように設定を分けるといいです多分 ( process.env.VUE_APP_API_URL
を参照している場合).
VUE_APP_API_URL: http://locahost:5000/api
VUE_APP_API_URL: /api
これで, yarn build --mode production
とすれば,./web/spa/dist/
にproduction用のSPAができます.この辺の話は以下に書いてあります.
さて,ここまできたら, ./
で,
docker-compose build
docker-compose up -d # ログ見たかったら-d消す
とすれば全て立ち上がるはず.
ブラウザで http://localhost:8080
にアクセスすると,vue appが表示されるはずです.
終わりに
今回の話はweb serverとapplication serverを一つのマシン上で動かすことを想定しているけど,多分世の中そんなことはあんまりやられていないんじゃないかと思う.wordpressみたいな立場をとれば使えるかも.適宜一般化したので,動かない!とかなったらコメントしてください!読んでいただきありがとうございました.
余談: Vue RouterのHistory modeを使っている場合
Vue RouterのHistory modeを使っている場合,以下のようにしないと404が返ってくるので注意.
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}