🐕

Nginxの導入方法

2023/07/09に公開

dockerを使用したrails(apiモード)とnuxt.jsの超簡易的なアプリに、Nginxを導入できたので備忘録と勉強になったポイントのメモです。
誤りのある箇所が多々あるかもしれません。ご了承いただけますと幸いです。

作業ディレクトリ

nginxディレクトリを作成しその中にDockerfile、nginx.confを作成。
(rails用Dockerfileとは別にnginx用Dockerfileを新しく作成する。1コンテナ1プロセスの原則)

Dockerfile

Dockerfile
FROM nginx:alpine
# デフォルトで用意されている個別設定ファイルを削除
RUN rm -f /etc/nginx/conf.d/*
# Nginxの設定ファイルをコンテナにコピー
COPY nginx.conf /etc/nginx/nginx.conf
# Nginxをforeground起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
EXPOSE 80

メモ
・ベースイメージは軽量化のためalpineを使用。
・COPYコマンド:COPY  ホスト内のコピー元 コンテナ内のコピー先
  コピー元はDockerfileと同じディレクトリ内に存在しないといけない。

nginx.conf

nginx.conf
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid       /var/run/nginx.pid;

events {
  worker_connections  1024;
}

http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;

  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

  access_log  /var/log/nginx/access.log  main;

  sendfile        on;
  #tcp_nopush     on;
  keepalive_timeout  65;
  #gzip  on;
  include /etc/nginx/conf.d/*.conf;

  upstream app {
    server unix:/app/tmp/sockets/puma.sock; #←コンテナ内のパス
  }

  server {
    listen       80;
    server_name  localhost;

    root /app/public;

    client_max_body_size 100m;

    location / {
      try_files $uri $uri/index.html @app;
    }

    location @app {
      # クライアントのリクエスト情報をpumaに伝える
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;
      # upstream ブロックで定義したサーバーグループを指定
      proxy_pass http://app;
    }

    error_page 404             /404.html;
    error_page 505 502 503 504 /50x.html;

    location = /50x.html {
      root /usr/share/nginx/html;
    }

    location = /404.html {
      return 404 "404 NOT FOUND ERROR";
    }

    location = /v1/healthcheck {
      return 200;
      break;
    }
  }
}

puma.rb

puma.rb
max_threads_count = Integer(ENV.fetch("RAILS_MAX_THREADS") { 5 })
min_threads_count = Integer(ENV.fetch("RAILS_MIN_THREADS") { max_threads_count })
threads min_threads_count, max_threads_count

# port ENV.fetch("PORT") { 3000 } 
environment ENV.fetch("RAILS_ENV") { "development" } 

# nginx ソケット通信設定追加
app_root = File.expand_path('..', __dir__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"
stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true

plugin :tmp_restart

メモ
・nginxにより3000ポートを使用しなくなるため、port ENV.fetch("PORT") { 3000 }はコメントアウト。
・ソケット通信のための設定を追加。
・app_root = File.expand_path('..', dir)
→app_rootに現在のファイルのディレクトリの親ディレクトリを代入。
・bind "unix://#{app_root}/tmp/sockets/puma.sock"
→ソケットファイルをbindしてソケット通信する。
(bind "unix://#{Rails.root}/tmp/sockets/puma.sock"と記載してもOKのよう。)
・stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true
→標準出力ログ、エラーログの出力先を指定。trueでログを追記、falseで上書き。

docker-compose.yml

docker-compose.yml(rootディレクトリ直下)
version: "3.8"
services:
  db:(割愛省略)
  api:
    build:
      context: ./api
      args:
        WORKDIR: $WORKDIR
    environment:
      POSTGRES_PASSWORD: $POSTGRES_PASSWORD
      API_DOMAIN: "localhost:$FRONT_PORT"
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec puma -C config/puma.rb"
    volumes:
      - "./api:/$WORKDIR"
      - public:/app/public #追加
      - tmp:/app/tmp #追加
    depends_on:
      - db

  front:
    build:
      context: ./front
      args:
        WORKDIR: $WORKDIR
        API_URL: "http://localhost"
    command: yarn run dev
    volumes:
      - "./front:/$WORKDIR"
    ports:
      - "$FRONT_PORT:3000"
    depends_on:
      - api

  nginx: #追加
    build:
      context: ./api/nginx
      dockerfile: Dockerfile
    volumes:
      - ./api/nginx/nginx.conf:/etc/nginx/nginx.conf
      - public:/app/public 
      - tmp:/app/tmp 
    ports:
      - "80:80"
    depends_on:
      - api

volumes: #追加
  tmp:
  public:

メモ
・nginxの記載を追加。
・apiのポート3000の記載を削除。
・apiのAPI_DOMAINでリクエスト送信元を、frontのAPI_URLでリクエスト送信先を設定しAPI通信を行う。
・apiとnginxのvolumesに以下を追加。また、最下部でtmp、publicを指定。これによりapiとnginx間でファイルを共有できる。

  • public:/app/public
  • tmp:/app/tmp

Nginx導入にあたり、これまで意味をしっかりと理解できていなかったDockerfile内のCOPYなどのコマンドや、ポート、volumesの理解が深まりました。

大変参考にさせていただいた記事
https://itoka.hatenadiary.com/entry/2022/03/04/004453
https://teratail.com/questions/j5hlwyx137nhis

Discussion