9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

DockerでVue.jsとFlaskを連携するSPA開発

Last updated at Posted at 2022-11-20

はじめに

ハッカソンでフロントエンドにVue.js、バックエンドにFlaskを採用してSPA開発する機会があったが、その両者をDockerで連携する記事が少なかったため、ここにまとめることにする。
なお、今回はフロントエンドとバックエンドを1つのリポジトリで実装する。

前提知識:Docker/Docker-composeの概念をある程度理解している
実行環境:Windows10, DockerHub
到達レベル:Dockerでフロントエンドとバックエンドを連携したSPA開発を理解できる

Dockerfile

まず、フロントエンドのVue.jsとバックエンドのFlaskのDockerコンテナを立ち上げるために、それぞれのDockerfileを定義する。

Dockerfile_python
FROM python:3.9

WORKDIR /usr/src/app

COPY ./ /usr/src/app

RUN pip install --upgrade pip && \
    pip install flask && \
    pip install flask-cors

ここでは、バックエンドのDockerfile名はDocker_pythonにしているが、任意のファイル名でも問題ない。
また、今回はPython3.9のDockerイメージを基に作成し、後の開発のためflask-corsをインストールしている。

同様にフロントエンドのDockerfileも定義する。

Dockerfile_node
FROM node:16.13.0

WORKDIR /usr/src/app

COPY ./ /usr/src/app

RUN npm install && \
    npm install -g @vue/cli && \
    npm install axios

node16.13.0のDockerイメージを基に作成した。
後の開発のためにaxiosをインストールしている。

docker-compose.yml

今回は2つのDockerコンテナを立ち上げるため、docker-compose.ymlファイルを記述し、複数個のコンテナを起動するように設定する。

docker-compose.yml
version: '3'
services:

  flask:
    build:
      context: .
      dockerfile: Dockerfile_python
    container_name: flask_container
    tty: true
    volumes:
      - ./:/usr/src/app
    ports:
      - "5000:5000"

  vue:
    build:
      context: .
      dockerfile: Dockerfile_node
    container_name: vue_container
    tty: true
    volumes:
      - ./:/usr/src/app
    ports:
      - "8080:8080"

serviceは起動するコンテナを記述する。(今回はflaskとvue)
この後にローカルサーバをフロントエンドとバックエンドから起動するが、両者のポート番号が重複しないように予め指定しておく。

flaskとvueのデフォルトポート番号は決まっているため、今回は必要ないが明確にするためにも...

コンテナ起動

Dockerfileとdocker-compose.ymlを定義したのでさっそくコンテナを起動してみる。

docker-compose up -d

※ -dは--detachの略記

-dオプションをつけることでバックグラウンドでコンテナを起動できる。(デタッチモード)

docker-compose ps

でコンテナの起動状態を確認することができる。

ディレクトリ構造

今の状態のディレクトリ構造は以下のようになる。

.
├── Dockerfile_node
├── Dockerfile_python
├── README.md
├── docker-compose.yml

今回はフロントエンド側とバックエンド側を1つのリポジトリで管理するため、それぞれのフォルダを作成する必要がある。

最終的に以下のディレクトリ構造になる。

.
├── Dockerfile_node
├── Dockerfile_python
├── README.md
├── backend
├── docker-compose.yml
├── frontend
├── node_modules
├── package-lock.json
└── package.json

frontendディレクトリ

まずは、フロントエンド側から実装する。

vue create frontend

上記のコマンドでVueのプロジェクトを作成する。
対話形式で必要なモジュールなどを聞かれるが基本Yesで問題ない。
今回はSPA開発なのでVuexやRouterなどを追加した。

完了すると以下のようなディレクトリ構造になる。

.
├── Dockerfile_node
├── Dockerfile_python
├── README.md
├── docker-compose.yml
├── frontend
├── node_modules
├── package-lock.json
└── package.json

それではフロントエンド側のローカルサーバを起動してみよう。

cd frontend

frontendディレクトリに移動し、

npm run build

でサーバに反映するためにビルドする。
すると、distディレクトリが作成される。

それではローカルサーバを起動してみよう。

PS C:\Users\〇〇〇\〇〇〇〇\frontend> npm run serve

> frontend@0.1.0 serve 
> vue-cli-service serve

 INFO  Starting development server...


 DONE  Compiled successfully in 4126ms                                                                             19:17:14


  App running at:
  - Local:   http://localhost:8081/
  - Network: http://192.168.10.162:8081/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

image.png
上記のようにVueが表示されれば起動成功である。

backendディレクトリ

バックエンド側も実装する。

mkdir backend

でbackendディレクトリを作成し、その中にapp.pyファイルを作成する。

app.py
# render_template:参照するテンプレートを指定
# jsonify:json出力
from flask import Flask, render_template, jsonify

# CORS:Ajax通信するためのライブラリ
from flask_cors import CORS
from random import *

# static_folder:vueでビルドした静的ファイルのパスを指定
# template_folder:vueでビルドしたindex.htmlのパスを指定
app = Flask(__name__, static_folder="../frontend/dist/static", template_folder="../frontend/dist")

app.config.from_object(__name__)

CORS(app)

# 任意のリクエストを受け取った時、index.htmlを参照
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
    return render_template("index.html")

# app.run(host, port):hostとportを指定してflaskサーバを起動
if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

Flaskでは、render_templateでレンダリングするファイルを指定するが、今回はbackendディレクトリではなく、frontendディレクトリの内容をレンダリングする必要がある。
そのため、static_folder="../frontend/dist/static", template_folder="../frontend/dist"の記述を加えることで、デフォルトのレンダリングするディレクトリを変更する。

また、今回はSPA開発なので

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
    return render_template("index.html")

とする。
詳細は以下の公式ドキュメントを参照されたい。

static系のファイルをstaticフォルダに参照するように変更しているが、
デフォルトではstaticフォルダは生成されないので、自分で作成して、その配下にstatic系のファイルを生成するように設定する必要がある。

そのため、frontendフォルダ直下にvue.config.jsを作成する。

vue.config.js
module.exports = {
  assetsDir: "static",
};

ディレクトリを構造を変更したので、
npm run buildを実行してサーバに反映させるのを忘れずに!

それでは、バックエンド側でサーバを起動してみよう。

PS C:\Users\〇〇〇\〇〇〇〇\backend> flask run
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit

image.png

上記のようにVueが表示されれば連携完了である。

参考記事

まとめ

今回はVue.jsとFlaskを1つのリポジトリで連携させた。
以降の開発では、corsaxiosを使用して、Ajax通信でフロントエンドとバックエンドを連携させ、SPA開発をする。

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?