0
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?

Docker コンテナに Python + Flask + Vue.js + Vuetify の Webアプリケーションを構築する

Last updated at Posted at 2024-10-10

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 アプリケーションを構築する時にデフォルトで作成されるファイルは残しているため、今回のアプリケーションの動作に必須ではないファイルも含まれている点はご留意ください。
なお、ディレクトリ作成や、ファイルを編集するコマンドは説明から省きます。

Ubuntu
/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
│                       └── {空ディレクトリ}

手順

資材作成

  1. docker-compose.yamlファイルを修正
    docker-compose.yamlファイルを下記のように修正します。

    • Flask アプリケーションが自動的に起動しないようにcommandを追加
    • ローカル(Ubuntu)のディレクトリと同期するようにvolumesを追加
    • Vue.js の開発サーバーを5173番ポートで公開する
    docker-compose.yaml
    version: '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"
    

  2. 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"]
    

  3. Flask のテンプレートを削除
    Flask のテンプレートファイルindex.htmlを削除します。
    (vite でビルド時に、当該ディレクトリに出力するため)

    Ubuntu
    sudo rm -r /home/appuser/workspace/web_app003/opt/web_app/src/templates/*
    

  4. Docker Compose でビルド&起動
    Docker Compose でカスタムイメージをビルドして起動します。

    Ubuntu
    cd /home/appuser/workspace
    docker-compose build
    docker-compose up -d
    

  5. 起動した Docker コンテナに入る
    docker execコマンドで bash を指定すると、対話型のセッションが開始されるので、起動した Docker コンテナに入ったような操作ができるようになります。

    Ubuntu
    docker exec -it web_app003 bash
    

    下記のように出力されれば、対話型のセッションが開始されています。

    web_app003
    bash-5.2#
    

  6. Vue.js プロジェクトを作成
    create-vue をインストールし、Vue.js プロジェクトをfrontendという名前で作成します。

    web_app003
    cd /opt/web_app/
    npm install -g create-vue@3.10.4
    

    下記のように出力されれば成功です。

    web_app003
    added 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_app003
    create-vue
    

    下記「◆」の通りに入力/選択します。

    web_app003
    Vue.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_app003
    Scaffolding project in /opt/web_app/frontend...
    
    Done. Now run:
    
      cd frontend
      npm install
      npm run dev
    

    vue.js のパッケージをインストールします。

    web_app003
    cd /opt/web_app/frontend/
    npm install
    

    下記のように出力されれば成功です。

    web_app003
    added 126 packages, and audited 127 packages in 24s
    
    13 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    

  7. 追加ライブラリをインストール
    CSS ライブラリの Vuetify をインストールします。

    web_app003
    cd /opt/web_app/frontend/
    npm install vuetify@3.7.2
    

    下記のように出力されれば成功です。

    web_app003
    added 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_app003
    npm install @mdi/font@7.4.47
    

    下記のように出力されれば成功です。

    web_app003
    added 1 package, and audited 130 packages in 890ms
    
    14 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    

  8. Vue.js のプログラムを修正
    vite.config.tsファイルを下記のように修正します。

    • server:開発サーバーを起動した時に、Windows のブラウザからローカルホストでアクセスできるようにする設定
    • build:ビルド時に、Flask のテンプレートディレクトリに出力するようにする設定
    vite.config.ts
    import { 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.ts
    import './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')
    

事前動作確認

  1. Vue.js の開発サーバを起動
    コンテナ内で Vue.js の開発サーバを起動します。

    web_app003
    cd /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
    

  2. ローカルホストでアクセス
    Windows のブラウザからローカルホストでアクセスします。
    Vue.js の開発サーバ は5173番ポートで公開しているので、URLはhttp://localhost:5173/となります。
    下記の画面が表示されれば成功です。
    スクリーンショット.png

  3. Vue.js を Flask にビルド
    Vue.js の開発サーバを一度停止した後、コンテナ内で Vue.js を Flask のテンプレートディレクトリにプロダクションビルドします。

    web_app003
    cd /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
    

  4. Flask を起動する
    シェルを実行して Flask を起動します。

    web_app003
    sh /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.
    

  5. ローカルホストでアクセス
    Windows のブラウザからローカルホストでアクセスします。
    Flask は5000番ポートで公開しているので、URLはhttp://localhost:5000/となります。
    下記の画面が表示されれば成功です。
    スクリーンショット.png

  6. 起動した Docker コンテナから退出
    対話型のセッションから退出します。

    web_app003
    exit
    

Docker ビルドに Vue.js のビルド処理を適用

  1. Docker Compose を停止
    Docker Compose をいったん停止します。

    Ubuntu
    cd /home/appuser/workspace
    docker-compose down
    

  2. 不要ファイルを削除
    Docker コンテナ内のファイルが全て同期されたため、プログラムファイルとして管理しない不要ファイルを削除します。

    • Flask のテンプレートファイル(vite でビルド時に、当該ディレクトリに出力するため)
    • node_modules(package.jsonの情報でビルド時にインストールするため)
    Ubuntu
    sudo 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/*
    

  3. 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"]
    

  4. docker-compose.yamlファイルを修正
    docker-compose.yamlファイルを下記のように修正します。

    • Flask アプリケーションが自動的に起動しないようにするcommandをコメントアウト
    • ローカル(Ubuntu)のディレクトリと同期するvolumesをコメントアウト
    docker-compose.yaml
    version: '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"
    

動作確認

  1. Docker Compose でビルド&起動
    Docker Compose でカスタムイメージをビルドして起動します。

    Ubuntu
    cd /home/appuser/workspace
    docker-compose build
    docker-compose up -d
    

  2. ローカルホストでアクセス
    Windows のブラウザからローカルホストでアクセスします。
    Flask は5000番ポートで公開しているので、URLはhttp://localhost:5000/となります。
    下記の画面が表示されれば成功です。
    スクリーンショット.png

最後に

いかがでしたでしょうか。
最初は対話型に Vue.js のプロジェクトを作成しましたが、2回目以降は Docker Compose を起動するだけで、Vue.js をプロダクションビルドし、Flask アプリケーションとして起動するところまでを自動化することができました。
プロジェクトメンバーが増えても、開発環境構築をスムーズに行うことが期待できますね。

0
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
0
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?