1
1

svelteKit & FastAPI の連携(Docker上)

Last updated at Posted at 2024-08-02

今回はローカルのDocker環境でsvelteKitとfastAPIを使用し、
Webアプリをデプロイするまでの手順を投稿します。
この方法以外にもやり方は、いろいろあると思いますが、
検証済みの方法なので参考にして下さい。

前回の投稿でFE(フロントエンド)のsvelteKitをDocker環境で構築しました。

今回はBE(バックエンド)との連携編です。
Docker環境でFastAPIのアプリケーションが動作していることが前提とします。
世の中にFastAPIの入門記事が溢れているので、BEの中身の学習は、他の記事を参考にしてください。
svelteKit側を注目して見ていきます。
※私がお世話になった記事はこちらになります。(迷ったら公式をまず見よう)

目標

  1. FastAPI部分の軽く説明
  2. FEのDockerの設定
  3. FEからBEへfetchして値を取得する

FastAPI部分の軽く説明

Dockerfileのポイント

  • パッケージ管理ツールとしてpoetryを使用しています。
  • poetryからuvicornを起動しています。
#python3.9のイメージをダウンロード
FROM python:3.9-buster
ENV PYTHONUNBUFFERED=1

WORKDIR /src

#pipを使ってpoetryをインストール
RUN pip install poetry

#poetryでライブラリをインストール(pyproject.tomlが既にある場合)
RUN poetry config virtualenvs.in-project true
RUN if [ -f pyproject.toml ]; then poetry install --no-root; fi

#uvicornのサーバーを立ち上げる
ENTRYPOINT ["poetry", "run", "uvicorn", "api.main:app", "--host", "0.0.0.0", "--reload"] 

docker-compose.ymlのポイント

  • networks
  • FEとBEは別々のdocker-compose.ymlによって作成されるため、 デフォルトでは、別のnetworkとなります。 そのため、BEでnetwork(be_external)を作成し、FE側で作成したnetworkを使用することとなります。
docker-compose.yml
version: '3'
services:
  demo-app:
    build: .
    volumes:
      - .dockervenv:/src/.venv
      - .:/src
    networks:
      - external
    ports:
      - 8000:8000 #ホストマシンのポート8000をdocker内のポート8000に接続する
  db:
    image: mysql:8.0
    platform: linux/x86_64
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' #rootアカウントをパスワードなしで作成
      MYSQL_DATABASE: 'demo' #初期データベースとしてdemoを設定
      TZ: 'Asia/Tokyo' #タイムゾーンを日本時間に設定
    volumes:
      - mysql_data:/var/lib/mysql
    command: --default-authentication-plugin=mysql_native_password # MYSQL8.0ではデフォルトが"caching_sha2_password"でドライバが非対応のため、変更
    networks:
      - external
    ports:
      - 33306:3306 #ホストマシンのポート33306をdocker内のポート3306に接続する
networks:
  # internal: #DBを外部から接続できなくしたい場合は、networksをinternalに変更する
  #   driver: bridge
  #   internal: false
  external:
    driver: bridge
    internal: false
    name: be_external
volumes:
  mysql_data:

↓ポイントとなる設定の詳細説明↓

driver:bridge 同じ Docker デーモン ホスト上で実行されているコンテナーに適用される。 同じホスト上の他のコンテナーと通信する必要があるコンテナーでアプリケーションを実行する場合によく使用される。 公式↓

https://docs.docker.com/network/drivers/bridge/

internal: false 内部ネットワーク上のコンテナーは相互に通信できますが、、他のネットワークとは通信できません。internal: trueを設定することで外部から分離されたnetworkを作成可能です。 ここでは明示的にfalseとしています。 公式↓

https://docs.docker.com/reference/cli/docker/network/create/

name: be_external Linux ブリッジを作成するときに使用するブリッジ名を"be_external"と指定しました。 FEではこの名前を使って、ここで作成したnetworkを使用することとなります。 公式↓

https://docs.docker.com/reference/cli/docker/network/create/

FastAPIその他のポイント

今回は、FEからBEへfetchして取得した値を画面に表示するというところまで行います。
BEで注目していただきたいのは、main.pyでoriginsとadd_middlewareの設定をしていることです。
※Getリクエストをするだけなら、この設定は必要ないかも

main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from api.routers import users,task

import uvicorn

app = FastAPI(swagger_ui_parameters={"docExpansion":"none"})

origins = [
    "http://localhost:8000",
    "http://127.0.0.1:5173",
    "http://my-app:5173"
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(users.router, tags=["users"])
app.include_router(task.router, tags=["task"])

@app.get("/")
async def hello():
    return {"message": "hello world!"}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8001)

FEのDockerの設定

いよいよ本題のFE側の設定に入ります。
※BE側でわからないことがあれば、他の記事を参考にして下さい。いつか見やすく更新します。
前回の作成したFEのDockerの設定を追加変更していきます。

先ほど、BE側で作成したnetworkを使用するように変更します。

version: '3.8'

services:
  my-app:
    image: svelte-app
    build:
      context: .
      dockerfile: ./Dockerfile
    environment:
      - NODE_ENV=development
      - PORT=5173
+    networks:
+      - external
    ports:
      - 5173:5173
    volumes:
      - ./src:/app/src
      - ./static:/app/static
      - ./vite.config.js:/app/vite.config.js
      - ./tsconfig.json:/app/tsconfig.json
      - ./svelte.config.js:/app/svelte.config.js
+networks:
+  external:
+    name: be_external
+    external: true

Dockerの設定でいじるこれだけです!

FEからBEへfetchして値を取得する

それでは、SvelteKitのソースを修正していきましょう。
src直下に+page.server.tsを作成し、fetchして値を取得する処理を追加します。

+page.server.ts
import { error } from "@sveltejs/kit";

interface Message {
    message: string;
}

export async function load({fetch}){
    const res = await fetch('http://demo-app:8000');
    if(res.ok){
        return await res.json() as Message;
    } else {
        throw error(404)
    }
}

Dockerコンテナ同士のやりとりは、URLをコンテナ名にすることで可能です。
load({fetch})として、SvelteKitが持つサーバーサイドのfetchを使用しています。
(今回はあんまり効果を発揮しません)
※interfaceは外だしにしたほうがいいかもね

次にサーバーサイドで取得した値を+page.svelteで画面に表示します。

<script lang="ts">
    export let data;
    let message = data.message;
</script>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
<p>message:{message}</p>

export let data;でサーバーサイドの値を受け取っています。

成功イメージ

image.png
BEから取得した、"hello world!"をFEで画面に表示することができました。

終わりに

今回も非常に簡単いですが、SvelteKitとFastAPIをDocker上でどうするようにしました。
詳細の解説は気が向いたら順次していきたいと思います。

よかったら、いいねと保存して下さい。

次回は、BEから取得したデータ一覧をSvelteでSkeletonのデータテーブルを使用して、画面に表示しようと思います。

1
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
1
1