1. 記事一覧 >
  2. ブログ記事
category logo

Python FastAPI React PostgreSQLのプロジェクトを動かして紐解いてみた

(更新) (公開)

はじめに

バックエンド:Python FastAPI
フロントエンド:TypeScript React
DB:PostgreSQL
の組み合わせで簡単に開発を始められるもの(スターター、プロジェクトジェネレーター)を GitHub で見つけました。

https://github.com/Buuntu/fastapi-react


FastAPI 公式のものは、
https://github.com/tiangolo/full-stack-fastapi-postgresql
で、フロントエンドが Vue です。これの React 版のようです。


...が、しかし、しばらく更新されていないせいなのか、TypeScript error が発生したのと、少々大げさに見えたので、別のものを見つけました。

https://github.com/gaganpreet/fastapi-starter


今回、これを動かしてみましたので、動かし方、動作内容を勝手に紹介していきたいと思います。
このプロジェクトの全体像は、以下です。Docker で起動します。

fastapi-starter 構成図


【 FastAPI 】

FastAPI は、Pythonの標準である型ヒントに基づいてPython 3.6 以降でAPI を構築するための、モダンで、高速(高パフォーマンス)な、Web フレームワークです。

【 React 】

React は、Meta社とコミュニティによって開発されているユーザインタフェース構築のためのJavaScriptライブラリです。コンポーネントと呼ばれる部品(UI・画面の一部分)ごとに開発ができます。画面更新の際、差分を検出して差分だけ更新するため、動作が速いという特徴があります。

【 PostgreSQL 】

拡張性とSQL準拠を強調するフリーでオープンソースの関係データベース管理システムです。


環境構築は、前回記事「Alpine Linux をインストールして VS Code Remote SSH してみた」の環境の続きからとします。OS は、Alpine Linux で、Python3 と pip3 がインストール済みです。

【検証環境】

Windows10 PRO x64

 VS Code 1.68.1

 VMware Workstation 16 Pro

  alpine-virt-3.16.0-x86_64

   Python 3.10.5


Docker インストール

docker-compose up を使うため、Docker のインストールが必要です。

前回記事に書きましたので、実施済み前提で進めますが、/etc/apk/repositories の変更が必要です。

# apk update
# apk add docker docker-compose
# docker -v
Docker version 20.10.17, build 100c70180fde3601def79a59cc3e996aa553c9b9
# docker-compose -v
docker-compose version 1.29.2, build unknown
# /etc/init.d/docker start

OS を再起動しても Docker デーモンが起動するように自動起動サービスに追加します。

# rc-update add docker

プロジェクト構築

cookiecutter を使ってプロジェクトを作成します。

【 cookiecutter 】

プロジェクトテンプレートからプロジェクトを作成するコマンドラインユーティリティです。(https://github.com/gaganpreet/fastapi-starter にあるのは、プロジェクトテンプレート。)

# pip3 install cookiecutter
# cd /home/admin/
# cookiecutter https://github.com/gaganpreet/fastapi-starter
project_name [Sample project]:(エンター)
project_slug [sample-project]:(エンター)
backend_port [8000]:(エンター)
frontend_port [3000]:(エンター)
# cd sample-project
# cat .env
.env
# POSTGRES_DB and POSTGRES_PASSWORD are used by the postgres docker image to initialse the db
POSTGRES_PASSWORD=WhhKGoAfTQpIAFbULLQIEwHqdkDAdrlG
POSTGRES_DB=app
DATABASE_URL=postgresql://postgres:WhhKGoAfTQpIAFbULLQIEwHqdkDAdrlG@postgres/app
TEST_DATABASE_URL=postgresql://postgres:WhhKGoAfTQpIAFbULLQIEwHqdkDAdrlG@postgres/apptest
SECRET_KEY=KhZFiewUoaBtMsfOyhdPGxfcjjPjkFOq

BACKEND_CORS_ORIGINS='["http://localhost:3000","http://127.0.0.1:3000"]'

PostgreSQL のパスワードが自動生成されます。

# docker-compose up -d

DB 作成 - migrate

docker-compose up だけかと思っていましたが、自力で DB 作成&マイグレーションが必要です。
よく見ると、出来上がったプロジェクトの README.md に書いてありました。


ちなみにですが、https://github.com/Buuntu/fastapi-react の方は、用意されている ./scripts/build.shdocker-compose up と DB マイグレーションと初期ユーザー登録が完了して、動作確認開始できました。


DB の app については、docker-compose.yml に以下のように書いてあるため、環境変数:POSTGRES_DB=app が反映されて、 docker-compose up により、自動的に作成されます。

docker-compose.yml
    env_file:
      - .env

# docker-compose exec backend alembic upgrade head
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 7e09fa75df7a, Add initial migration
INFO  [alembic.runtime.migration] Running upgrade 7e09fa75df7a -> 14bc3b4ecc3a, Add item migration
# docker-compose exec postgres createdb apptest -U postgres

docker-compose exec [docker-compose.yml に書かれたサービス名] [コマンド]
により、コンテナの中に入ってマイグレーションしています。
自動テスト用の apptest DB は、自動的に作成されないため、自力作成です。


【 alembic 】

Alembic(アランビック)=蒸留器

Python で SQLAlchemy を使用しているときに DB の管理をしてくれる migration ツールです。

マイグレーションとは、DBに保存されているデータを保持したまま、テーブルの作成やカラムの変更などを行うための機能です。

マイグレーション機能を使うことで特定のデータベースに依存せずにデータベースの操作ができます。

【 SQLAlchemy 】

Alchemy(アルケミィ)=錬金術

Pythonで利用されるORMの1つです。

SQLAlchemyではコマンドでの操作やAlter Tableなどは行えませんが、Alembicではコマンドを用いたスキーマの操作やAlter Tableを行うことができます。

【O/Rマッピング(ORM)】

O/Rマッピングとは、オブジェクトとリレーショナルデータベース(RDB)の間でデータ形式の相互変換を行うことです。

Pythonオブジェクトとリレーショナルデータベース上のデータを関連付け、SQLを書かなくても、データベース操作ができる仕組みです。


frontend アクセス

frontend の http://localhost:3000/ にアクセスします。...としたかったですが、検証環境の OS が Alpine Linux で GUI が無いため、別のPCから http://192.168.11.9:3000/ でアクセスしています。

http://192.168.11.9:3000/ アクセス


http://192.168.11.9:3000/register 画面でユーザー登録しようとすると、 https://192.168.11.9/api/v1/auth/register へアクセスが行って、エラーになりました。

http://192.168.11.9:3000/register アクセス


http://192.168.11.9:3000/register のエラー


frontend エラー対処

http://192.168.11.9:8000/api/v1/auth/register へアクセスしなくてはいけないと思うのですが、https:// へ行ってしまいます。


frontend/src/providers/env.ts の実装を見ると、NODE_ENV=production かつ、localhost 以外の時は、https://[元々のホスト名] が API だと思ってしまい、避けられませんでした。
(frontend/Dockerfile 中で yarn build しているため、NODE_ENV=production になり、NODE_ENV は、どうやっても上書きできませんでした。)

src/providers/env.ts
const readApiBaseFromEnv = (): string => {
  // Get API base URL from env
  // Priority is given to same host in the browser when environemnt is production
  if (
    process.env.NODE_ENV === "production" &&
    !document.location.host.startsWith("localhost")
  ) {
    return `https://${document.location.host}`;
  } else if (process.env.REACT_APP_API_BASE) {
    return process.env.REACT_APP_API_BASE;
  }
  return "http://localhost:8000";
};

今回あくまでもお試しなので、以下のように書き換えました。(return `https://${document.location.host}`を書き換え。)

frontend/src/providers/env.ts
const readApiBaseFromEnv = (): string => {
  // Get API base URL from env
  // Priority is given to same host in the browser when environemnt is production
  if (
    process.env.NODE_ENV === "production" &&
    !document.location.host.startsWith("localhost")
  ) {
    //return `https://${document.location.host}`;
    return `http://192.168.11.9:8000`;
  } else if (process.env.REACT_APP_API_BASE) {
    return process.env.REACT_APP_API_BASE;
  }
  return "http://localhost:8000";
};

frontend/.env.production

REACT_APP_API_BASE=http://192.168.11.9:8000
と書くと、process.env.REACT_APP_API_BASE がセットされますが、
今回の環境の場合、一番上の if で入ってきてしまうため、この対処になります。


# docker-compose up -d --build frontend

もう一度、http://192.168.11.9:3000/register でユーザー登録をトライします。

http://192.168.11.9:3000/register CORSエラー

ちゃんと API の http://192.168.11.9:8000/api/v1/auth/register へ行っていますが、またエラーです。


CORS エラー対処

エラー内容は、CORS エラーです。ポート番号違いでオリジンが異なるため、ブラウザ側エラー判断です。CORS エラーがどういったものなのかについての詳細は、別記事に詳しく書いています。「OpenResty(Nginx)Lua で CORS 用に条件付きでレスポンスヘッダーを書き換え

本当は、以下の構成にしたら良いような気がしますが、そうなっていません。(Buuntu/fastapi-react の方は、nginx.confproxy_pass で、そうなっていました。)

以下の構成 の図


このまま CORS エラーを解消します。


.env
BACKEND_CORS_ORIGINS='["http://localhost:3000","http://127.0.0.1:3000"]'
というのがあり、ここにフロントエンド側の URL(http://192.168.11.9:3000)をセットしたら、動きました。

# vi .env
#BACKEND_CORS_ORIGINS='["http://localhost:3000","http://127.0.0.1:3000"]'
BACKEND_CORS_ORIGINS='["http://192.168.11.9:3000","http://127.0.0.1:3000"]'
# docker-compose up -d --build backend

以下が BACKEND_CORS_ORIGINS を参照して、CORS 対策している箇所です。

backend/app/factory.py
def setup_cors_middleware(app):
    if settings.BACKEND_CORS_ORIGINS:
        app.add_middleware(
            CORSMiddleware,
            allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
            allow_credentials=True,
            allow_methods=["*"],
            expose_headers=["Content-Range", "Range"],
            allow_headers=["Authorization", "Range", "Content-Range"],
        )

動作確認

ユーザーの登録と Items の登録ができるようになりました!

画面は、React Admin のダッシュボードで、軽快に動作します。


POST http://192.168.11.9:8000/api/v1/auth/register
POST http://192.168.11.9:8000/api/v1/auth/register


POST http://192.168.11.9:8000/api/v1/items
POST http://192.168.11.9:8000/api/v1/items


DB にユーザー情報と items 情報が登録されています。

# docker exec -it sample-project_postgres_1 psql -U postgres -d app -c "select * from users;"
                  id                  |       email        |                       hashed_password                        | is_active | is_superuser | is_verified |            created
  |            updated
--------------------------------------+--------------------+--------------------------------------------------------------+-----------+--------------+-------------+-----------------------------
--+-------------------------------
 1466bd89-fda1-4885-9b70-cf60caf2546f | sample@example.com | $2b$12$j7cCIFbYCSuJ1PdSNtK3WurVf17t/vlfKgSmMHY5wjsW1azExMNtu | t         | f            | f           | 2022-06-24 13:47:08.306265+0
0 | 2022-06-24 13:47:08.306265+00
(1 row)
# docker exec -it sample-project_postgres_1 psql -U postgres -d app -c "select * from items;"
 id |               user_id                |            created            |            updated            | value
----+--------------------------------------+-------------------------------+-------------------------------+-------
  1 | 1466bd89-fda1-4885-9b70-cf60caf2546f | 2022-06-25 07:34:35.877863+00 | 2022-06-25 07:34:35.877863+00 | aaaaa
(1 row)

コンテナの中に入って見ると、app のテーブル構成は、以下でした。

app=# \d
               List of relations
 Schema |      Name       |   Type   |  Owner
--------+-----------------+----------+----------
 public | alembic_version | table    | postgres
 public | items           | table    | postgres
 public | items_id_seq    | sequence | postgres
 public | users           | table    | postgres
(4 rows)

pytest を使ったテストにも対応しています。

【 pytest 】

Pythonで書いたプログラムをテストするためのフレームワークです。

# docker-compose exec backend pytest
=========================================== test session starts ===========================================
platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0
rootdir: /app
plugins: anyio-3.5.0
collected 9 items

tests/api/test_items.py .......                                                                     [ 77%]
tests/api/test_utils.py .                                                                           [ 88%]
tests/models/test_user.py .                                                                         [100%]

============================================ 9 passed in 1.55s ============================================

当たり前ですが、無事通りました。


backend 利用パッケージ

backend は、Python で実装されています。


Python パッケージの管理に、Pipfile や requirements.txt ではなくて、Poetry の pyproject.toml が使われています。

backend/Dockerfile
RUN poetry install --no-root

で Python の依存パッケージをインストールしています。

--no-root は、自分自身(今回の場合、sample-project)をインストール対象としないという意味です。

【 Poetry 】

Poetryは、Pythonでの依存関係の管理とパッケージ化のためのツールです。プロジェクトが依存するライブラリを宣言することができ、それらを管理(インストール/更新)します。

pyproject.toml を読み取って、パッケージをインストールします。

Node.js でいう npm あるいは yarn コマンドのような、Ruby でいう bundle コマンドのようなツールです。

pyproject.toml は、npm、yarn で言う package.json のような存在です。

backend/pyproject.toml
[tool.poetry] # [...]部分を節という。tool.poetry 節は複数の節で構成されている。
name = "sample-project-backend"
version = "0.1.0"
description = ""
authors = []

[tool.poetry.dependencies] # 本番環境ライブラリ
python = "^3.7"
# python バージョン >=3.7.0 <4.0.0 という意味。
# ^ は、"キャレット要件"と言う。
# 一番左側にある、ゼロでないバージョニングは変えない
# helloworld = "^0.1.2"
# ならば「>=0.1.2 <0.2.0」という意味になる。
# (1がゼロでは無いため、1を維持。)
fastapi = "^0.75.2"
uvicorn = "^0.17.6"
pydantic = "^1.9.1"
requests = "^2.27.1"
alembic = "^1.8.0"
psycopg2-binary = "^2.9.3"
fastapi-users = {extras = ["sqlalchemy2"], version = "^9.3.1"} # extrasで追加オプションを指定。外部パッケージ sqlalchemy2 込み。
asyncpg = "^0.25.0"
SQLAlchemy = "^1.4.37"
databases = "^0.5.5"
gunicorn = "^20.1.0"

[tool.poetry.dev-dependencies] # 開発用ライブラリ poetry install --no-dev で取り除くことができる。
black = "^22.3.0"
pytest = "^7.1.2"
ipython = "^7.34.0"

[build-system] # ビルドシステム。build-backend を指定しなければ、setup.py が実行される。
requires = ["poetry-core>=1.0.0"] # poetry バージョン 1.0.0 以降をインストール
build-backend = "poetry.core.masonry.api" # poetry.masonry.api を実行

[tool.cruft]
skip = [".env"]
# poetry run cruft .
# のように実行可能

【 uvicorn 】

Uvicorn(ユーブイアイコーン)は、Python用の ASGI Web サーバー実装です。

【 ASGI 】

Asynchronous Server Gateway Interfaceの略です。WSGIの後継仕様で、非同期で動作するように設計されています。WebSocketなど複数のプロトコルをサポートしています。

【 WSGI 】

Web Server Gateway Interface(WSGI:ウィスキー)は、WebサーバとWebアプリケーションを接続するための、標準化されたインタフェース定義です。

WSGIで動くプログラムは、WebサーバーがWSGIに対応していれば、無改修で動くという理屈になります。

【 pydantic 】

Python の型アノテーションを用いて実行時にデータのバリデーションを行えるようにするライブラリです。

コード実行時に型の不整合や不正値の場合、例外送出してくれます。(通常は、致命的なエラーにならなければ、例外送出されない。)

【 requests 】

HTTP通信用のPythonのライブラリです。

HTTP通信の実装をPythonの標準ライブラリurllibよりシンプルに書けます。

【 alembic 】

Alembic(アランビック)=蒸留器

Python で SQLAlchemy を使用しているときに DB の管理をしてくれる migration ツールです。

マイグレーションとは、DBに保存されているデータを保持したまま、テーブルの作成やカラムの変更などを行うための機能です。

マイグレーション機能を使うことで特定のデータベースに依存せずにデータベースの操作ができます。

【 psycopg2-binary 】

Psycopgは、Pythonプログラミング言語用のPostgreSQLデータベースアダプターです。

その主な機能は、Python DB API 2.0仕様の完全な実装とスレッドセーフです(複数のスレッドが同じ接続を共有できます)。

(pysopg2とpsycopg2-binaryの違い:コンパイラや外部のライブラリ等を必要としないのが-binaryの方です。libpqを内包しています。)

【 fastapi-users 】

FastAPIプロジェクトに登録および認証システムをすばやく追加します。

FastAPIにJWT認証、Cookie認証の機能を提供します。(Python3.7以降が必要。)

(サポートしているORM:SQLAlchemy, MongoDB, Tortorise ORM)

【 asyncpg 】

PythonからPostgreSQLにアクセスするためのライブラリです。

asyncpgはasyncio(非同期 I/O。 async/await 構文を使い 並行処理の コードを書くためのライブラリ。)をベースに動きます。

非同期処理をベースにしているためか、パフォーマンスが良いです。

【 SQLAlchemy 】

Alchemy(アルケミィ)=錬金術

Pythonで利用されるORMの1つです。

SQLAlchemyではコマンドでの操作やAlter Tableなどは行えませんが、Alembicではコマンドを用いたスキーマの操作やAlter Tableを行うことができます。

【 databases 】

さまざまなデータベースのシンプルなasyncioサポートを提供します。

databasesは、Starlette、Sanic、Responder、Quart、aiohttp、Tornado、FastAPIなどの非同期Webフレームワークとの統合に適しています。

【 gunicorn 】

Gunicorn(グニコーン)​は、WSGI アプリケーション用の Python HTTP サーバーです。

Gunicornサーバーは、多数のWebフレームワークと広く互換性があり、実装がシンプルで、サーバーリソースが少なく、高速に動作します。

【 ipython 】

IPython(アイパイソン)はPythonを対話的に実行するためのシェルです。

Pythonの対話型インタプリタを拡張したものです。

コードのシンタックスハイライトおよびタブによる補完が行えます。

【 cruft 】

cruftを使用すると、意図的に記述したコードとは別に、プロジェクトのパッケージ化と構築に必要なすべての定型文を維持できます。

既存のCookiecutterテンプレートと互換性があります。

(Cookiecutterと違い、テンプレートが変更されたら、反映することができるもののようです。)


frontend 利用パッケージ

frontend は、node.js React TypeScript で実装されています。


frontend の方は、React & react-admin がメインで、これといって紐解くものが無いので、package.json の scripts の部分だけ少し言及します。

package.json
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "test:debug": "react-scripts --inspect-brk test --runInBand --no-cache",
    "eject": "react-scripts eject",
    "format": "prettier src --write",
    "run-e2e-tests": "cypress run",
    "open-e2e-test": "cypress open",
    "genapi": "openapi-generator-cli generate -i <(curl -s 'http://localhost:8000/api/v1/openapi.json') -g typescript-axios -o src/generated -p withSepa
  },

今回、実行環境を作らないといけないため、実行していませんが、cypress でのテスト用スクリプトも入っています。

【 Cypress 】

ブラウザでのテスト作業を自動化するテストフレームワークです。React の E2Eテストを自動化できます。

【 E2Eテスト 】

E2Eテストとは、「End To Endテスト」の略であり、ユーザが利用するのと同じようにシステム全体をテストします。

ユーザと同じようにブラウザを操作し、挙動が期待通りになっているか確認します。

また、openapi-generator-cli を使って、API の実装を自動化しています。(yarn run genapi と実行すると、API の実装が作成されます。)
java を使っているため、java をインストールしています。

# cd frontend
# apk add yarn curl openjdk11
# yarn install
# yarn run genapi
yarn run v1.22.19
$ openapi-generator-cli generate -i <(curl -s 'http://localhost:8000/api/v1/openapi.json') -g typescript-axios -o src/generated -p withSeparateModelsAndApi=true,apiPackage=api,modelPackage=models,useSingleRequestParameter=true
・・・
[main] INFO  o.o.codegen.TemplateManager - writing file /home/admin/sample-project/frontend/src/generated/models/bearer-response.ts
[main] INFO  o.o.codegen.TemplateManager - writing file /home/admin/sample-project/frontend/src/generated/models/error-model.ts
[main] INFO  o.o.codegen.TemplateManager - writing file /home/admin/sample-project/frontend/src/generated/models/httpvalidation-error.ts
[main] INFO  o.o.codegen.TemplateManager - writing file /home/admin/sample-project/frontend/src/generated/models/item.ts
[main] INFO  o.o.codegen.TemplateManager - writing file /home/admin/sample-project/frontend/src/generated/models/item-create.ts
[main] INFO  o.o.codegen.TemplateManager - writing file /home/admin/sample-project/frontend/src/generated/models/item-update.ts
[main] INFO  o.o.codegen.TemplateManager - writing file /home/admin/sample-project/frontend/src/generated/models/user.ts
・・・

OpenAPI 仕様(openapi.json)に合わせたコードが自動生成されました。

【 OpenAPI 】

OpenAPI Specification とは、REST APIの仕様を記述するためのフォーマットのことです。

YAML または JSON形式で定義します。

【 OpenAPI Generator 】

OpenAPI で書かれたドキュメントから、クライアントコードを自動で生成してくれるツールです。


構成紐解き

fastapi-starter 構成図

docker-compose up で、
docker-compose.ymldocker-compose.override.yml が使われます。(docker-compose の仕様で、自動で docker-compose.override.yml も読み込まれます。)

backend/Dockerfilefronend/Dockerfile にビルドと起動方法が書かれています。

docker-compose.yml
version: "3.9"

services:
  postgres:
    image: postgres:12
    restart: always
    env_file:
      - .env
    healthcheck:
      test: pg_isready -U postgres
# pg_isready : PostgreSQLデータベースサーバの接続状態を検査するためのユーティリティ
      interval: 3s
# 3秒に一回ヘルスチェック
      timeout: 2s
# 2秒応答が無かったら、タイムアウト判定
      retries: 3
# 3回連続 成功/失敗 で healthy/unhealthy に移行

  backend:
    build:
      context: backend
# ビルドコンテキスト(ビルド環境)=backend ディレクトリ。backend/Dockerfile を使用。
    ports:
      - "8000:8000"
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
# service_healthy : 依存サービスのヘルスチェックがパスするまで待つ

  frontend:
    build:
      context: frontend
# ビルドコンテキスト(ビルド環境)=frontend ディレクトリ。frontend/Dockerfile を使用。
    ports:
      - "3000:80"
    volumes:
      - ./frontend:/app:delegated
# delegated : 一貫性に対する保証が最も弱いが、最も高速。コンテナ上の更新がホスト上に反映するまで、遅延が発生するのを許容。
    environment:
      - NODE_ENV=production

volumes:
  app-db-data:
  root-home:
docker-compose.override.yml
version: "3.9"

services:
  postgres:
    ports:
      - "5432:5432"
    volumes:
      - app-db-data:/var/lib/postgresql/data:cached
# cached : ホストの表示が信頼できる。ホスト上の更新がコンテナ上に反映するまで、遅延が発生するのを許容

  backend:
    command: uvicorn --port 8000 --host 0.0.0.0 --reload main:app
# backend/Dockerfile の CMD より優先(同じコマンドが書かれている。)
    volumes:
      - ./backend:/app:delegated
      - root-home:/root:delegated
    depends_on:
      postgres:
        condition: service_healthy

docker-compose.ci.yml というのがありますが、 Github Actions 設定ファイルの一つ .github/workflows/test.yaml

docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d
docker-compose exec -T postgres createdb -U postgres apptest
docker-compose exec -T backend alembic upgrade head
docker-compose exec -T backend pytest -v

が書かれていて、テストに使われるようです。 (Github Actions は今回検証しませんでした。)

docker-compose.ci.yml
version: "3.9"

services:
  backend:
    image: "sample-project-backend:latest"

  frontend:
    image: "sample-project-frontend:latest"

frontend 側の Dockerfile、frontend/Dockerfile では、
Docker multi stage build の手法が使われていて、node:16 イメージでビルドした後、nginx:latest イメージにデプロイしています。
nginx の設定は、frontend/nginx.conf で、ビルド済みファイル配置先の /usr/share/nginx/html をドキュメントルートとしています。

frontend/Dockerfile
FROM node:16 as build

WORKDIR /app

COPY package.json yarn.lock /app/

RUN yarn

COPY . /app/

RUN CI=1 yarn test

RUN yarn build


FROM nginx:latest

COPY --from=build /app/build /usr/share/nginx/html

COPY --from=build /app/nginx.conf /etc/nginx/conf.d/default.conf

以上!

loading...