1
1

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 3 years have passed since last update.

Docker環境のFlaskとVueをHerokuにデプロイする【備忘録】

Posted at

#ディレクトリ構成

ディレクトリ構成
.
├─ dist
|  └─ static
│  └─ index.html
└─ frontend
|  └─ node_modules
| └─ src
|  └─ package.json
|  └─ Dockerfile
|  └─ etc...
└─ app.py
└─ docker-compose.yml
└─ Dockerfile
└─ requirements.txt
└─ .gitignore

#Docker環境を整える
docker-composeとDockerfileをルートディレクトリに作成。

bash
$ git init
$ touch {docker-compose.yml,Dockerfile}
docker-compose.yml
version: "3"
services:
  frontend:
    container_name: frontend
    build:
      context: .
      dockerfile: ./frontend/Dockerfile
    volumes:
      - ./:/app
    ports:
      - "8080:8080"
    tty: true
    stdin_open: true

  backend:
    container_name: backend
    build:
      context: .
      dockerfile: ./Dockerfile
    volumes:
      - ./:/app
    ports:
      - "5000:5000"
    stdin_open: true
    tty: true
Dockerfile
FROM python:3.8

WORKDIR /app

COPY . .

RUN pip3 install flask

EXPOSE 5000

CMD python app.py

ここで起動コマンドCMD python app.pyを記述していないとHerokuにデプロイした時にエラーになる

#バックエンド準備
ルートディレクトリにPythonファイルを作成して、以下のように記述。
render_templateはVueのnpm run buildで書き出されたものを相対パスで指定する。

app.py
from flask import Flask, render_template
import os

app = Flask(__name__, static_folder='dist/static', template_folder='dist')

# ルートの設定
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
    return render_template("index.html")

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port, debug=True)

#フロントエンド準備
frontendフォルダにDockerfileを作成
VueCLIをインストールしておく

Dockerfile
FROM node:lts-alpine

WORKDIR /app

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

ENV HOST 0.0.0.0

##コンテナを起動

bash
$ docker-compose up -d --build

nodeコンテナに入る。

bash
$ docker-compose exec frontend sh

nodeコンテナに入ったらVueCLIをたたく。
マニュアルを選択してvue-routerをインストールして必要な環境は適時導入しておく

frontend/sh
$ vue create frontend

Vue CLI v4.5.13
? Please pick a preset:
  Default ([Vue 2] babel, eslint)
  Default (Vue 3) ([Vue 3] babel, eslint)
❯ Manually select features
frontend/sh
Vue CLI v4.5.13
? Please pick a preset: Manually select features
? Check the features needed for your project:
 ◉ Choose Vue version
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
❯◉ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◯ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

vueフォルダが生成されるので中身をすべてfrontendの中に移す。

ディレクトリ構成
└─ frontend
   └─ vue
   |  ├─ node_modules
  |  ├─ src
   |  ├─ package.json
   |  └─ etc...
   └─ Dockerfile

   ||
   \/

└─ frontend
   ├─ node_modules
  ├─ src
   ├─ package.json
   ├─ Dockerfile
   └─ etc...

##vue.config.jsを作成
staticフォルダが生成されるようにする。

frontend/sh
$ touch vue.config.js
vue.config.js
module.exports = {
  assetsDir: "static",
};

##package.jsonを編集

package.json
"scripts": {
    "serve": "vue-cli-service serve",
-    "build": "vue-cli-service build",
+    "build": "vue-cli-service build --dest ../dist",
  },

##.gitignoreを編集
今回はDockerコンテナをHerokuにPushするので必要ないが、Gitでデプロイする場合を考慮して一応.gitignoreから/distを除外しておく。

.gitignore
.DS_Store
node_modules
- /dist

# local env files
.env.local
.env.*.local

##faviconをstaticに移動

ディレクトリ構成
frontend
└─ public
   ├─ favicon.ico
   └─ index.html

   ||
   \/

frontend
└─ public
   ├─ static
   |   └─ favicon.ico
   └─ index.html

ローカルで確認してみる

frontend/sh
$ cd frontend
$ npm run serve

localhost:8080をブラウザで開いてVueの初期画面が出れば成功

screenshot-tranquil-forest-19074.herokuapp.com-2021.09.19-18_42_59.png

##ルートディレクトリにdistを作成

frontend/sh
$ cd frontend
$ npm run build
ディレクトリ構成
.
├─ dist              // 生成
├─ frontend
├─ app.py
├─ docker-compose.yml
├─ Dockerfile
├─ requirements.txt
└─ .gitignore

#requirements.txtの書き出し
requirements.txtを作成していないとHerokuでstackを読み込んでくれなかったためルートディレクトリに書き出しておく

##コンテナに入る

bash
$ docker-compose exec backend bash 

入ったら下記を実行

backend/bash
pip freeze > requirements.txt

#Herokuにデプロイ

CLIを使ってHerokuにログインする

bash
$ heroku login

アプリをHeroku上に作成

bash
$ heroku create

Gitでもデプロイすることができるが今回はDockerでデプロイする

bash
$ heroku container:login

コンテナをHerokuにプッシュ

bash
$ heroku container:push web

アプリをデプロイ

bash
$ heroku container:release web

#ハマったところ
次スタックしないための備忘録
##Dockerコンテナのアクセス権限
Docker-composeでVolumeをルートにせずにディレクトリ指定しているとバックエンドからアクセスできなかった。

変更前
    volumes:
      - frontend:/app
変更後
    volumes:
      - ./:/app

##ディレクトリ構成
Herokuにデプロイの関係上Dockerfileはルートディレクトリに置いておかないとうまくプッシュできなかった。
当初はディレクトリ構成をフロントとバックエンドで分けていたがバックエンドのファイル群をルートに移すことで解決した。

変更前
.
├─ dist
├─ frontend
├─ backend
└─ docker-compose.yml
変更後
.
├─ dist
├─ frontend
├─ app.py
├─ docker-compose.yml
├─ Dockerfile
├─ requirements.txt
└─ .gitignore

##Vue構築時の注意
自分の環境だとvue init webpack アプリ名でVueを構築するとHrokuにデプロイした時にindex.htmlが見つからないエラーがでた。

log
jinja2.exceptions.TemplateNotFound: index.html

試行錯誤の末vue create アプリ名でVueプロジェクトを作成するとうまくいった。

##起動コマンド
Herokuにデプロイするときは起動コマンドを記述してあげる必要がある。
色々ありそうだが今回はbackendのDockerfileにCMDで記述した。

Dockerfile
FROM python:3.8

WORKDIR /app

COPY . .

RUN pip3 install flask

EXPOSE 5000

CMD python app.py

#番外編
Gitでデプロイする場合はrequirements.txtがルートディレクトリにないとHerokuが何の言語を使っているのか判断できない。
さらに.gitignoreからdistを削除しておかないとdistを読み込んでくれないためindex.htmlを参照しない。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?