ディレクトリ構成
.
├─ 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をルートディレクトリに作成。
$ git init
$ touch {docker-compose.yml,Dockerfile}
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
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
で書き出されたものを相対パスで指定する。
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をインストールしておく
FROM node:lts-alpine
WORKDIR /app
RUN npm install -g @vue/cli && \
npm install -g @vue/cli-init
ENV HOST 0.0.0.0
コンテナを起動
$ docker-compose up -d --build
nodeコンテナに入る。
$ docker-compose exec frontend sh
nodeコンテナに入ったらVueCLIをたたく。
マニュアルを選択してvue-routerをインストールして必要な環境は適時導入しておく
$ 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
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フォルダが生成されるようにする。
$ touch vue.config.js
module.exports = {
assetsDir: "static",
};
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
を除外しておく。
.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
ローカルで確認してみる
$ cd frontend
$ npm run serve
localhost:8080をブラウザで開いてVueの初期画面が出れば成功
ルートディレクトリにdistを作成
$ cd frontend
$ npm run build
.
├─ dist // 生成
├─ frontend
├─ app.py
├─ docker-compose.yml
├─ Dockerfile
├─ requirements.txt
└─ .gitignore
requirements.txtの書き出し
requirements.txtを作成していないとHerokuでstackを読み込んでくれなかったためルートディレクトリに書き出しておく
コンテナに入る
$ docker-compose exec backend bash
入ったら下記を実行
pip freeze > requirements.txt
Herokuにデプロイ
CLIを使ってHerokuにログインする
$ heroku login
アプリをHeroku上に作成
$ heroku create
Gitでもデプロイすることができるが今回はDockerでデプロイする
$ heroku container:login
コンテナをHerokuにプッシュ
$ heroku container:push web
アプリをデプロイ
$ 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が見つからないエラーがでた。
jinja2.exceptions.TemplateNotFound: index.html
試行錯誤の末vue create アプリ名
でVueプロジェクトを作成するとうまくいった。
起動コマンド
Herokuにデプロイするときは起動コマンドを記述してあげる必要がある。
色々ありそうだが今回はbackendのDockerfileにCMDで記述した。
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を参照しない。