🍉

nginx × docker でフロントエンドとバックエンドの振り分けをしました!(リバースプロキシ)

2024/10/26に公開

環境

  • フロントエンド: nuxt
  • バックエンド: rails
  • Docker Desktop for Mac

やりたいこと

  • http://localhost/でフロントエンドにもバックエンドにもアクセスする

  • パスによってフロントエンドとバックエンドへの振り分けをしたい

    • /api -> バックエンドへ
    • それ以外 -> フロントエンドへ
  • 現状

    • バックエンド: railsが動いている
      compose.yaml
      services:
          rails:
            build: .
            command: bundle exec puma
            volumes:
              - .:/app
            ports:
              - 3000:3000
            tty: true
      
    • フロントエンド: nuxtが動いている
      compose.yaml
      services:
        nuxt:
          build: .
          volumes:
            - .:/app
          ports:
            - 3030:3000
          command: npm run dev
          tty: true
      

nginxの役割

nginx ("engine x") is an HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server.
引用: https://nginx.org/en/

  • webサーバーであり、リバースプロキシであり、キャッシュもできて、ロードバランサーにもなり、TCP/UDP proxy serverやmail proxy serverにもなる優れもののようです。

  • 今回はリバースプロキシとして利用します。

    リバース プロキシとは、外部ネットワーク(インターネット)からの接続を受け、何らかの処理を行った上で内部のサーバーに引き渡す、中継機能を果たす機器のことです
    引用: https://www.f5.com/ja_jp/glossary/reverse-proxy#:~:text=リバース プロキシとは、外部,のようにふるまいます。

    こんな感じ↓↓

nginxのイメージ

  • nginxのdockerの公式イメージがあったので、それを利用します

nginxの設定

  • 設定ファイル: /etc/nginx/nginx.conf
    nginx.conf
    # 必須っぽいので入れました
    events {
      # イベント処理に関する設定
      worker_connections 1024;  # 最大同時接続数
    }
    
    http {
      # upstream: プロキシ先の定義
      # backendコンテナへ
      upstream backend {
        server rails:3000;
      }asd
      # frontendコンテナへ
      upstream frontend {
        server nuxt:3000;
      }
    
      # server: サーバー設定
      server {
        # listenするポート番号
        listen 80;
        # サーバー名
        server_name localhost;
    
        # リバースプロキシ関連の設定
        ## location: リクエストのパスによって振り分ける
        ## /api/ へのリクエストはbackendへ
        location /api/ {
          # `http://backend`でアクセスするとrails側でホスト名関連のエラーになったので、`localhost`を渡してあげます
          proxy_set_header Host               $http_host;
          proxy_pass http://backend;
        }
        # その他へのリクエストはfrontendへ
        location / {
          proxy_pass http://frontend;
        }
      }
    }
    

docker composeにnginxを追加

  • nginxのサービスを追加します

    • 作成した設定ファイルをコンテナ内にマウントするようにします
    • バックエンド/フロントエンドへのアクセスはnginxを経由するので、rails/nuxtサービスのポートマッピングは削除します。代わりにnginxで80番ポートでアクセスできるように設定します
    compose.yaml
    services:
      rails:
        build: .
        command: bundle exec puma
        volumes:
          - .:/app
        tty: true
      # nginxのサービス追加↓
      nginx:
        image: nginx:1.13
        volumes:
          # 設定ファイルのマウント
          - ./nginx/nginx.conf:/etc/nginx/nginx.conf
        # 起動時のコマンド
        command: nginx -g 'daemon off;'
        ports:
          # localhostでアクセスするためにポートをマッピングします
          - 80:80
        # nginxがbackend/frontendを参照するため、先にrailsコンテナが起動する必要がある
        # フロントエンドは別compose.yamlなので、先に立ち上げておく必要がある(ちょっとめんどくさいから微妙かも、、、)
        depends_on:
          - rails
    
  • networkの追加

    • nginxとバックエンドとフロントエンドそれぞれのコンテナが同じネットワーク内に入れるようにします
    compose.yaml
    # バックエンド/フロントエンドそれぞれのcompose.yamlに追加しました
    networks:
      default:
        name: my_network
    
  • 最終的なcompose.yaml

    • バックエンド
      compose.yaml
          services:
            rails:
              ......
            nginx:
              image: nginx:1.13
              volumes:
                - ./nginx/nginx.conf:/etc/nginx/nginx.conf
              ports:
                - 80:80
              command: nginx -g 'daemon off;'
              depends_on:
                - rails
      
          networks:
            default:
              name: my_network
      
    • フロントエンド
      compose.yaml
      services:
          nuxt:
            build: .
            volumes:
              - .:/app
            command: npm run dev
            tty: true
        
        networks:
          default:
            name: my_network
      

動作確認

  • フロントエンド -> バックエンドの順に、docker compose up -dでコンテナを起動します

    • 起動順が決まっているのが面倒なので、なんとかしたい。。
  • localhostにアクセスした時

    • nuxtにアクセスできました
  • localhost/apiにアクセスした時

    • railsにアクセスできました
    • routeを作成していないので、エラーは出ています。これからAPIを作成すればOK

参考サイト

Discussion