0
0

【FastAPI×React×Nginx×Docker】フロントエンドコンテナとAPIコンテナでやり取りができないときにしたこと

Last updated at Posted at 2024-05-22

追記(2024/5/23): 記事の内容だとAPIコンテナのホスト側のポート番号を指定しなくてもいいようです。つまり開けるポートがフロントエンドのものだけで良くなります。逆に下の追記のやり方だと、APIサーバのポートも開けないと動きません。また時間があるときに記事の内容を変更します。

追記(2024/5/22): こんな難しいことをせずにbaseUrl = http://localhost:8000でいけました。htmlファイルから見たAPIサーバの場所なのでホスト側のポート番号を打たないといけないっぽいです。

背景

フロントエンドはReactで開発し、本番環境はNginxで配信、バックエンドはFastAPIでWebアプリケーションを開発していました。
これを全てDocker上で動かしています。
コンテナは以下の4つです。

コンテナ名 ホスト側ポート番号 コンテナ側ポート番号 処理
db - 5432 PostgreSQLを動かしている
backend - - バックグラウンドで非同期で処理を走らせている
api 8000 8000 FastAPIを動かしている
frontend 3000 3000 Reactのビルドをした後にNginxでそのビルドファイルを配信している

image.png

実現したかったこと

jsファイルの中で、APIコンテナに対してaxiosを使ってデータを受け取りたかった。
具体的には、jsファイルの中で以下のような処理をしたかった。

const baseUrl = '<APIのURL>';
const response = await axios.get(`${baseUrl}`)

問題解決までにしたこと

Docker側で名前解決してくれる(参考↓)ことを知っていたので、まずは

baseUrl = `http://api:8000`

としてみたがFastAPI側にデータが届いていない。

urlを間違えたのではないかと考え、フロントエンドコンテナからping apiと打つとちゃんと通信ができていた。
※pingがないと言われたときは以下の記事が参考になりました。

また、フロントエンドコンテナからcurl http://api:8000と打ってもうまく通信できていた。

そもそもデータが届いていないので違うとは思うが、CORS関係のエラーかもしれないと思い、FastAPI側で以下のように設定したがもちろんうまくいかず。

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# CORSの設定
app.add_middleware(
    CORSMiddleware,
    allow_origins=[`*`],  # リクエストを許可するオリジンのリスト
    allow_credentials=True,  # 認証情報の共有を許可
    allow_methods=["*"],    # すべてのHTTPメソッドを許可
    allow_headers=["*"],    # すべてのHTTPヘッダーを許可
)

ここで、ChatGPTに聞いて、Nginxのリバースプロキシというものがあり、それを使ってみることにした。

以下にNginxの設定ファイルを記載する。

server {
    listen 3000;
    server_name localhost;

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

    location /api/ {
        proxy_pass http://api:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

リバースプロキシについては以下が参考になる。

これにより、例えばhttp://localhost:3000/apiに届いた通信をhttp://api:8000に渡してあげることができる。

また、jsファイルの方も

baseUrl = `http://localhost:3000/api`

と変更した。

これでもう一度コンテナを再起動すると、無事にAPI通信ができるようになった。

まとめ

フロントエンドコンテナとAPIコンテナでやり取りができないときにしたことをまとめた。
ReactでビルドしたファイルをNginxで配信しており、htmlファイルから見たときにhttp://api:8000がどこにあるかが分からないことが原因だった。
解決策として、Nginxのリバースプロキシの機能を使ってhttp://localhost:3000/api -> http://api:8000にプロキシし、htmlファイルからAPIコンテナの場所を参照できるようにした。

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