LoginSignup
25
30

More than 1 year has passed since last update.

Vite+FastAPI+NGINX+Dockerの環境構築

Last updated at Posted at 2023-02-04

概要

前提

  • Docker, Docker Composeインストール済み
    実行環境はMac + Docker for Desktop(Mac) ですが、Windows(WSL)やLinuxでもできるはず。

FastAPIコンテナ(バックエンド)

以下のDockerfileを使います。
pythonのパッケージ管理はpoetryを使っています。
以下のパッケージをpyproject.tomlでインストールしています。

  • fastapi
  • uvicorn

(pyproject.toml)
https://github.com/gaitou2048/fastAPI-veutify-template/blob/main/back/app/pyproject.toml


FROM python:3.11-slim-bullseye

ENV TZ=Asia/Tokyo

# Debian日本語化
RUN apt-get update && apt-get install -y locales \
    && apt-get clean -y && rm -rf /var/lib/apt/lists/* \
    && sed -i -e 's/# \(ja_JP.UTF-8\)/\1/' /etc/locale.gen \
    && locale-gen \
    && update-locale LANG=ja_JP.UTF-8

# 必要なパッケージのインストール
RUN apt-get update && apt-get install -y \
    curl \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Poetryインストール
ENV POETRY_HOME=/opt/poetry
RUN curl -sSL https://install.python-poetry.org | python3 - \
    && cd /usr/local/bin \
    && ln -s /opt/poetry/bin/poetry \
    && poetry config virtualenvs.create false

# Pythonパッケージインストール
WORKDIR /app
COPY ./app/pyproject.toml* ./app/poetry.lock* ./
RUN poetry install

Vueコンテナ(フロント)

Dockerファイルは以下になります。
あらかじめpackage.jsonを導入済みのため、
COPY でpackage.json等をコピーし、yarn installしています。

以下のモジュールを入れています。

  • vuetify: UIとかの機能や見た目がたくさんある便利なフレームワーク
  • axios: APIを叩くときに使う

※ 完全に空の状態から作る場合は、COPYとyarn installをせずにコンテナを作成します。
その後、コンテナ内でviteのプロジェクト作成を実行していきます。
するとpackage.json等ができるので、もう一度コンテナをビルドする流れですね。

FROM node:19.6-slim

WORKDIR /app
ENV LANG=C.UTF-8 \
    TZ=Asia/Tokyo
COPY app/package.json app/yarn.lock ./
RUN yarn install

NGIXNコンテナ(サーバ)

フロントエンドコンテナで、yarn buildをすると、htmlとスクリプトがビルドされます。
(多分Webpackでソースコード等をバンドルしているだけ)

そのビルドされたhtmlを表示させるためのサーバとなるコンテナです。
NGINXを使うと負荷が少なかったり、高速だったりするらしい。
使った方が良さそうです。

Dockerfileは以下ですね。
NGINXイメージ使っているだけ。

FROM nginx:latest
ENV TZ=Asia/Tokyo

設定ファイルが重要です。
http://localhost:8000/ でフロントエンドコンテナでビルドされたものを表示してます。
/api でバックエンド側に繋がるようにしてます。

nginx.conf
worker_processes auto;

events {
    worker_connections 512;
    multi_accept on;
}

http {
    include /etc/nginx/conf.d/server.conf;
    server_tokens off;
    send_timeout 60; # タイムアウト60秒

    # mimetype
    include         /etc/nginx/mime.types;
    default_type    application/octet-stream;
}
confd/server.conf
server{
    listen 8000;

    location / {    
        root /www/dist;
        index index.html;
    }

    location /api {
        proxy_pass http://back:5001/;
    }
}

docker-compose.yml

3つのコンテナを取り仕切るdocker-compose.ymlがこちら。
フロントエンドコンテナでビルドすると、/front/app/distに出力されるので、
それをサーバコンテナでマウントしています。

docker-compose.yml
version: '3'
services:
  # バックエンド(docker FastAPI)
  back:
    build:
      context: ./back
      dockerfile: Dockerfile
    volumes:
      - ./back/app:/app/
    tty: true
    restart: on-failure
    working_dir: /app
    command: uvicorn src.main:app --reload --host 0.0.0.0 --port 5001

  front:
    build:
      context: ./front
      dockerfile: Dockerfile
    ports:
      - 3000:3000 # 本番で動かす際はコメントアウト
    volumes:
      - ./front/app:/app
      - front_node_modules:/app/node_modules
    tty: true
    restart: on-failure
    working_dir: /app

  server:
    build:
      context: ./server
      dockerfile: Dockerfile
    ports:
      - 8000:8000
    volumes:
      - ./server/nginx.conf:/etc/nginx/nginx.conf
      - ./server/conf.d:/etc/nginx/conf.d
      - ./server/log:/var/log/nginx
      - ./front/app/dist:/www/dist
    tty: true
    restart: on-failure

  
volumes:
  front_node_modules:

開発時

開発時はdocker compose exec front yarn devを実行して、
開発サーバを起動します。
http://localhost:3000で繋がります。

開発サーバを使うと、フロントの修正がすぐに反映されるのでお手軽です。楽々です。
使わないとこんな感じの流れに。ビルドして、コンテナを再起動するはめになります。

  1. docker compose exec front yarn build でビルド
  2. docker compose restart server

あと、VSCodeなどで開く場合は、補完が効きません。
何故ならパッケージやモジュールはコンテナ内にあるから。
RemoteContainerを使うと幸せになりそうです。
バックエンドとフロントエンドで、ウィンドウが二つ必要ですが。

ローカル(ホスト)環境が汚れても良い場合は、
nodeやらpythonのパッケージをインストールしてしまってもよいかも。
コンテナに追加した場合は、ローカルにも入れないといけないですけどね。

テンプレートの見た目

せっかく(?)なので、vuetifyのワイヤーフレームにあるページを表示しています。
https://vuetifyjs.com/ja/examples/wireframes/system-bar/

Hello Worldとなっている部分はAPIで取得しています。
Axiosとバックエンドと、サーバ(NGINX)が作動しているかのテストですね。
上手くいかないと「文字列」と表示されます。
デフォルトが const message: Ref<string> = ref("文字列"); なのです。

1.png

25
30
1

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
25
30