Docker コンテナに Python + Flask + Vue.js + Vuetify の Webアプリケーションを構築する
前回の記事で、Docker コンテナに Python + Flask の開発環境を構築しました。
フロントエンドはシングルページアプリケーションにしたいので、Python + Flask + Vue.js + Vuetify の Webアプリケーションへ進化させていきます。
なお、Vue.js のフロントエンドツールは vite を使用します。
今回のゴール
- Webアプリケーションを Vue.js + Vuetify のシングルページアプリケーションにする
- Windows からローカルホストでアクセスして「Hello World」を表示する
ディレクトリ構成
今回のディレクトリ構成は下記のようになります。
vite で Vue.js アプリケーションを構築する時にデフォルトで作成されるファイルは残しているため、今回のアプリケーションの動作に必須ではないファイルも含まれている点はご留意ください。
なお、ディレクトリ作成や、ファイルを編集するコマンドは説明から省きます。
/home/appuser
├── workspace
│ ├── docker-compose.yaml
│ └── web_app003
│ ├── Dockerfile
│ └── opt
│ ├── flask_start.sh
│ └── web_app
│ ├── frontend
│ │ ├── README.md
│ │ ├── env.d.ts
│ │ ├── index.html
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── src
│ │ │ ├── App.vue
│ │ │ ├── assets
│ │ │ │ ├── base.css
│ │ │ │ ├── logo.svg
│ │ │ │ └── main.css
│ │ │ ├── components
│ │ │ │ ├── HelloWorld.vue
│ │ │ │ ├── TheWelcome.vue
│ │ │ │ ├── WelcomeItem.vue
│ │ │ │ └── icons
│ │ │ │ ├── IconCommunity.vue
│ │ │ │ ├── IconDocumentation.vue
│ │ │ │ ├── IconEcosystem.vue
│ │ │ │ ├── IconSupport.vue
│ │ │ │ └── IconTooling.vue
│ │ │ ├── main.ts
│ │ │ ├── plugins
│ │ │ │ └── vuetify.ts
│ │ │ ├── router
│ │ │ │ └── index.ts
│ │ │ └── views
│ │ │ ├── AboutView.vue
│ │ │ └── HomeView.vue
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ └── vite.config.ts
│ └── src
│ ├── app_controller.py
│ └── templates
│ └── {空ディレクトリ}
手順
資材作成
-
docker-compose.yaml
ファイルを修正
docker-compose.yaml
ファイルを下記のように修正します。- Flask アプリケーションが自動的に起動しないように
command
を追加 - ローカル(Ubuntu)のディレクトリと同期するように
volumes
を追加 - Vue.js の開発サーバーを5173番ポートで公開する
docker-compose.yamlversion: '3' services: ############################################################################## # Web Application container(Python + Flask + Vue.js + Vuetify) ############################################################################## web_app003: build: "./web_app003/" command: "/bin/bash" # Flask アプリケーションが自動的に起動しないようにする設定 tty: true volumes: - "./web_app003/opt/web_app/:/opt/web_app/" # ローカル(Ubuntu)のディレクトリと同期する ports: - "5000:5000" # Flask port - "5173:5173" # Vue.js port image: "web_app003:develop" container_name: "web_app003"
- Flask アプリケーションが自動的に起動しないように
-
Dockerfile
ファイルを修正
Dockerfile
ファイルを下記のように修正します。- nodejs をインストール対象に追加
Dockerfile# Amazon Linux 2023 FROM public.ecr.aws/amazonlinux/amazonlinux:2023 # ミドルウェアをインストール RUN dnf install -y \ util-linux \ shadow-utils \ vim-enhanced-2:9.* \ sudo-1.9.* \ python3.11-3.11.* \ python3.11-pip-22.3.* \ python3.11-devel-3.11.* \ nodejs-1:18.* # Python のライブラリをインストール RUN pip3.11 install flask==3.0.* RUN pip3.11 install flask_socketio==5.3.* RUN pip3.11 install flask-cors==4.0.* RUN pip3.11 install flask-wtf==1.2.* # ホストOS と同じユーザーを追加する # 1000 : host OS $(id -g) RUN groupadd -g 1000 appuser # 1000 : host OS $(id -u) RUN adduser -m appuser -u 1000 -g appuser # Add SUDO group. RUN groupadd sudo # Add SUDO authority. RUN usermod -aG sudo appuser # 資材を配置する WORKDIR /opt/web_app/ RUN mkdir -p /opt/web_app/ COPY ./opt/web_app/ /opt/web_app/ COPY ./opt/flask_start.sh /opt/ # オーナーとパーミッションを変更する RUN chown appuser:appuser /opt/web_app -R RUN chmod 775 /opt/web_app -R # 起動時のコマンドを設定する CMD ["sh","/opt/flask_start.sh"]
-
Flask のテンプレートを削除
Flask のテンプレートファイルindex.html
を削除します。
(vite でビルド時に、当該ディレクトリに出力するため)Ubuntusudo rm -r /home/appuser/workspace/web_app003/opt/web_app/src/templates/*
-
Docker Compose でビルド&起動
Docker Compose でカスタムイメージをビルドして起動します。Ubuntucd /home/appuser/workspace docker-compose build docker-compose up -d
-
起動した Docker コンテナに入る
docker exec
コマンドで bash を指定すると、対話型のセッションが開始されるので、起動した Docker コンテナに入ったような操作ができるようになります。Ubuntudocker exec -it web_app003 bash
下記のように出力されれば、対話型のセッションが開始されています。
web_app003bash-5.2#
-
Vue.js プロジェクトを作成
create-vue をインストールし、Vue.js プロジェクトをfrontend
という名前で作成します。web_app003cd /opt/web_app/ npm install -g create-vue@3.10.4
下記のように出力されれば成功です。
web_app003added 1 package in 1s npm notice npm notice New minor version of npm available! 10.5.0 -> 10.9.0 npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.9.0 npm notice Run npm install -g npm@10.9.0 to update! npm notice
対話型で、
frontend
という名前の Vue.js プロジェクトを作成します。web_app003create-vue
下記「◆」の通りに入力/選択します。
web_app003Vue.js - The Progressive JavaScript Framework ✔ Project name: … ◆frontend ✔ Add TypeScript? … No / ◆Yes ✔ Add JSX Support? … No / ◆Yes ✔ Add Vue Router for Single Page Application development? … No / ◆Yes ✔ Add Pinia for state management? … ◆No / Yes ✔ Add Vitest for Unit Testing? … ◆No / Yes ✔ Add an End-to-End Testing Solution? › ◆No ✔ Add ESLint for code quality? … ◆No / Yes ✔ Add Vue DevTools 7 extension for debugging? (experimental) … ◆No / Yes
下記のように出力されれば成功です。
web_app003Scaffolding project in /opt/web_app/frontend... Done. Now run: cd frontend npm install npm run dev
vue.js のパッケージをインストールします。
web_app003cd /opt/web_app/frontend/ npm install
下記のように出力されれば成功です。
web_app003added 126 packages, and audited 127 packages in 24s 13 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
-
追加ライブラリをインストール
CSS ライブラリの Vuetify をインストールします。web_app003cd /opt/web_app/frontend/ npm install vuetify@3.7.2
下記のように出力されれば成功です。
web_app003added 2 packages, and audited 129 packages in 3s 14 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
Webフォントの @mdi/font をインストールします。
web_app003npm install @mdi/font@7.4.47
下記のように出力されれば成功です。
web_app003added 1 package, and audited 130 packages in 890ms 14 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
-
Vue.js のプログラムを修正
vite.config.ts
ファイルを下記のように修正します。- server:開発サーバーを起動した時に、Windows のブラウザからローカルホストでアクセスできるようにする設定
- build:ビルド時に、Flask のテンプレートディレクトリに出力するようにする設定
vite.config.tsimport { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vueJsx from '@vitejs/plugin-vue-jsx' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), vueJsx(), ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, server: { host: '0.0.0.0', port: 5173 }, build: { outDir: '../src/templates/', assetsDir: './static/' } })
App.vue
ファイルを下記のように修正します。- Vuetify のテンプレート(ワイヤーフレーム)を使って画面レイアウトを構成する
App.vue<script setup lang="ts"> import { RouterLink, RouterView } from 'vue-router' import HelloWorld from './components/HelloWorld.vue' </script> <template> <v-app> <!-- ヘッダ1 --> <v-system-bar color="secondary"> System Bar </v-system-bar> <!-- メニュー --> <v-navigation-drawer> <v-container> <v-list> <v-list-item title="List1" /> </v-list> </v-container> </v-navigation-drawer> <!-- ヘッダ2 --> <v-app-bar color="primary"> <v-app-bar-title> Application Bar </v-app-bar-title> </v-app-bar> <!-- メインコンポーネント --> <v-main> <v-container> <v-alert type="info">Hello World</v-alert> </v-container> </v-main> <!-- フッタ --> <v-footer color="primary" app> Footer </v-footer> </v-app> </template> ~~~~~~~~~~ 以下省略 ~~~~~~~~~~
vuetify.ts
ファイルを下記のように作成します。- @mdi/font を有効化する
- Vuetify を有効化する
vuetify.ts// Styles import '@mdi/font/css/materialdesignicons.css' import 'vuetify/styles' // Vuetify import { createVuetify } from 'vuetify' import * as components from 'vuetify/components' import * as directives from 'vuetify/directives' import { aliases, mdi } from 'vuetify/iconsets/mdi' import '@mdi/font/css/materialdesignicons.css' export default createVuetify({ components, directives, icons: { defaultSet: 'mdi', aliases, sets: { mdi, } }, });
main.ts
ファイルを下記のように修正します。- Vuetify を有効化する
main.tsimport './assets/main.css' import { createApp } from 'vue' import App from './App.vue' import router from './router' import vuetify from './plugins/vuetify'; const app = createApp(App) app.use(router) app.use(vuetify) app.mount('#app')
事前動作確認
-
Vue.js の開発サーバを起動
コンテナ内で Vue.js の開発サーバを起動します。web_app003cd /opt/web_app/frontend/ npm run dev
下記が出力されれば成功です。
web_app003> frontend@0.0.0 dev > vite VITE v5.4.8 ready in 727 ms ➜ Local: http://localhost:5173/ ➜ Network: http://172.19.0.2:5173/ ➜ press h + enter to show help
-
ローカルホストでアクセス
Windows のブラウザからローカルホストでアクセスします。
Vue.js の開発サーバ は5173番ポートで公開しているので、URLはhttp://localhost:5173/
となります。
下記の画面が表示されれば成功です。
-
Vue.js を Flask にビルド
Vue.js の開発サーバを一度停止した後、コンテナ内で Vue.js を Flask のテンプレートディレクトリにプロダクションビルドします。web_app003cd /opt/web_app/frontend/ npm run build
下記のように出力されれば成功です。
web_app003> frontend@0.0.0 build > run-p type-check "build-only {@}" -- > frontend@0.0.0 type-check > vue-tsc --build --force > frontend@0.0.0 build-only > vite build vite v5.4.8 building for production... (!) outDir /opt/web_app/src/templates is not inside project root and will not be emptied. Use --emptyOutDir to override. ✓ 515 modules transformed. ../src/templates/index.html 0.43 kB │ gzip: 0.28 kB ../src/templates/static/materialdesignicons-webfont-Dp5v-WZN.woff2 403.22 kB ../src/templates/static/materialdesignicons-webfont-PXm3-2wK.woff 587.98 kB ../src/templates/static/materialdesignicons-webfont-B7mPwVP_.ttf 1,307.66 kB ../src/templates/static/materialdesignicons-webfont-CSr8KVlo.eot 1,307.88 kB ../src/templates/static/AboutView-C6Dx7pxG.css 0.09 kB │ gzip: 0.10 kB ../src/templates/static/index-Dm78o2We.css 770.43 kB │ gzip: 111.49 kB ../src/templates/static/AboutView-Bub0W0gQ.js 0.23 kB │ gzip: 0.20 kB ../src/templates/static/index-C7UOd8v6.js 518.05 kB │ gzip: 166.74 kB (!) Some chunks are larger than 500 kB after minification. Consider: - Using dynamic import() to code-split the application - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit. ✓ built in 4.92s
-
Flask を起動する
シェルを実行して Flask を起動します。web_app003sh /opt/flask_start.sh
下記のように出力されれば成功です。
web_app003* Serving Flask app 'app_controller' * Debug mode: off Address already in use Port 5000 is in use by another program. Either identify and stop that program, or start the server with a different port.
-
ローカルホストでアクセス
Windows のブラウザからローカルホストでアクセスします。
Flask は5000番ポートで公開しているので、URLはhttp://localhost:5000/
となります。
下記の画面が表示されれば成功です。
-
起動した Docker コンテナから退出
対話型のセッションから退出します。web_app003exit
Docker ビルドに Vue.js のビルド処理を適用
-
Docker Compose を停止
Docker Compose をいったん停止します。Ubuntucd /home/appuser/workspace docker-compose down
-
不要ファイルを削除
Docker コンテナ内のファイルが全て同期されたため、プログラムファイルとして管理しない不要ファイルを削除します。- Flask のテンプレートファイル(vite でビルド時に、当該ディレクトリに出力するため)
- node_modules(
package.json
の情報でビルド時にインストールするため)
Ubuntusudo rm -r /home/appuser/workspace/web_app003/opt/web_app/frontend/node_modules/ sudo rm -r /home/appuser/workspace/web_app003/opt/web_app/src/templates/*
-
Dockerfile
ファイルを修正
Dockerfile
ファイルを下記のように修正します。- vite で Vue.js 環境を構築してプロダクションビルドするコマンドを追加
Dockerfile# Amazon Linux 2023 FROM public.ecr.aws/amazonlinux/amazonlinux:2023 # ミドルウェアをインストール RUN dnf install -y \ util-linux \ shadow-utils \ vim-enhanced-2:9.* \ sudo-1.9.* \ python3.11-3.11.* \ python3.11-pip-22.3.* \ python3.11-devel-3.11.* \ nodejs-1:18.* # Python のライブラリをインストール RUN pip3.11 install flask==3.0.* RUN pip3.11 install flask_socketio==5.3.* RUN pip3.11 install flask-cors==4.0.* RUN pip3.11 install flask-wtf==1.2.* # ホストOS と同じユーザーを追加する # 1000 : host OS $(id -g) RUN groupadd -g 1000 appuser # 1000 : host OS $(id -u) RUN adduser -m appuser -u 1000 -g appuser # Add SUDO group. RUN groupadd sudo # Add SUDO authority. RUN usermod -aG sudo appuser # 資材を配置する WORKDIR /opt/web_app/ RUN mkdir -p /opt/web_app/ COPY ./opt/web_app/ /opt/web_app/ COPY ./opt/flask_start.sh /opt/ # オーナーとパーミッションを変更する RUN chown appuser:appuser /opt/web_app -R RUN chmod 775 /opt/web_app -R # vite で Vue.js 環境を構築してプロダクションビルドする WORKDIR /opt/web_app/frontend/ RUN npm install RUN npm run build # 起動時のコマンドを設定する CMD ["sh","/opt/flask_start.sh"]
-
docker-compose.yaml
ファイルを修正
docker-compose.yaml
ファイルを下記のように修正します。- Flask アプリケーションが自動的に起動しないようにする
command
をコメントアウト - ローカル(Ubuntu)のディレクトリと同期する
volumes
をコメントアウト
docker-compose.yamlversion: '3' services: ############################################################################## # Web Application container(Python + Flask + Vue.js + Vuetify) ############################################################################## web_app003: build: "./web_app003/" # command: "/bin/bash" # Flask アプリケーションが自動的に起動しないようにする設定 tty: true # volumes: # - "./web_app003/opt/web_app/:/opt/web_app/" # ローカル(Ubuntu)のディレクトリと同期する ports: - "5000:5000" # Flask port - "5173:5173" # Vue.js port image: "web_app003:develop" container_name: "web_app003"
- Flask アプリケーションが自動的に起動しないようにする
動作確認
-
Docker Compose でビルド&起動
Docker Compose でカスタムイメージをビルドして起動します。Ubuntucd /home/appuser/workspace docker-compose build docker-compose up -d
-
ローカルホストでアクセス
Windows のブラウザからローカルホストでアクセスします。
Flask は5000番ポートで公開しているので、URLはhttp://localhost:5000/
となります。
下記の画面が表示されれば成功です。
最後に
いかがでしたでしょうか。
最初は対話型に Vue.js のプロジェクトを作成しましたが、2回目以降は Docker Compose を起動するだけで、Vue.js をプロダクションビルドし、Flask アプリケーションとして起動するところまでを自動化することができました。
プロジェクトメンバーが増えても、開発環境構築をスムーズに行うことが期待できますね。