4
4

More than 1 year has passed since last update.

webサーバーにNginxを組み入れる【Docker環境】

Last updated at Posted at 2022-04-04

はじめに

以前に、railsとvueのアプリ構成でdocker環境を構築した。

しかし、Railsの開発用サーバーをpuma単独で動かしていたので、
役割分担して構成を変更した。

  • webサーバー: nginx  
  • applicationサーバー: puma

作業内容を備忘録として残す。

アプリ構成イメージ

スクリーンショット 2022-04-05 5.58.27.png

使用技術

  • Rails: 6.0.4.4
  • nginx: 1.21.6

前提

  • dockerでrailsの開発環境を構築済み

nginxの初期設定を理解する

実装前にnginxのデフォルト設定がどう動作しているのか確認しておく。

DockerHubからnginx:1.21.6-alpineイメージを選択し、同イメージでコンテナを生成すると、
コンテナ内の/etc/nginx/conf.d/にdefault.confが自動生成されていた。

/etc/nginx/conf.d/default.conf
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

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

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

そのまま起動されたコンテナにhttp://localhostでアクセスすると、welcomeページに表示されてnginxが正常起動していることが分かる。

スクリーンショット 2022-04-04 13.49.31.png

ひとまずデフォルトでは当ファイルをもとに動作していることが分かった。
(Nginxの初期設定の詳細は別の機会に学ぶことにする)

実装

今回はnginxからRailsにアクセスし、正常に動作するをゴールにする。

負荷分散やエラーログの整理などの詳細設定は、nginxの技術書を読んでブラッシュアップする。

では実装に移る。

ディレクトリ構成

frontendと.envは今回の実装に直接は関係しないが、全体像の為に載せておく。

  • frontend: Vueを構成
  • .env: 環境変数を管理
ターミナル

% tree root -a
root
├── docker-compose.yml
├── .env
├── backend
・       ・
・       ・
・       ・
│   ├── Dockerfile
│   └── config
│       └── puma.rb
├── frontend
・       ・
・       ・
・       ・
│   └── Dockerfile
└── web
    ├── Dockerfile
    └── nginx.cnf

作業

各ファイルにコメントで補足している。

なお、nginxとpumaを繋ぐソケットは
以下の順で使われていることを留意しておく。

  1. Dockerfile(Rails)のCMDでpumaを起動する
  2. puma.rbでbindを実行し、puma.sockというソケットを作成する
  3. docker-compose.ymlのvolumesで同ソケットをnginxコンテナにも共有する
  4. Dockerfile(Nginx)のCOPYでホスト側のnginx.confをnginxコンテナに複製する
  5. そのnginx.confのupstreamで共有されたソケットで繋ぐ
docker-compose.yml

### 環境変数は.envファイルで管理 ###
version: '3.8'

services:

  # DBコンテナ
  db:
    image: mysql:8.0.28
    command: --default-authentication-plugin=mysql_native_password
    volumes: 
      - "./db:/var/lib/mysql"
      - "./db/personal_config/my.cnf:/etc/mysql/conf.d/my.cnf"
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
      TZ: Asia/Tokyo

  # Railsコンテナ
  backend:
    build:
      context: ./backend
      args:
        WORKDIR: $WORKDIR
    volumes:
      - "./backend:/$WORKDIR"
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
    ports:
      - "8000:3000"
    depends_on:
      - db

  # Nginxコンテナ
  web:
    build:
      # Dockerfileのパスを指定する
      context: ./web
    volumes:
      # 独自のNginx設定ファイルをコンテナに同期させる
      - ./web:/app/public
      # Railsのpuma起動時に生成されるpuma.sockをNginxコンテナにも共有する
      - ./backend/tmp/sockets:/app/tmp/sockets
    ports:
      - 80:80
    # 先にRailsが動くように依存関係を作る
    depends_on:
      - backend

  # Vueコンテナ
  frontend:
    build:
      context: ./frontend
      args:
        WORKDIR: $WORKDIR
    volumes:
      - "./frontend:/$WORKDIR"
    ports:
      - "3000:3000"
    depends_on:
      - backend
backend/Dockerfile
FROM ruby:2.7.5-alpine

ARG WORKDIR

ARG RUNTIME_PACKAGES="bash imagemagick nodejs yarn tzdata mysql-dev mysql-client git"
ARG DEV_PACKAGES="build-base curl-dev"

ENV HOME=/${WORKDIR} \
    TZ=Asia/Tokyo

WORKDIR ${HOME}

COPY Gemfile* ./

RUN apk update && \
    apk upgrade && \
    apk add --no-cache ${RUNTIME_PACKAGES} && \
    apk add --virtual build-dependencies --no-cache ${DEV_PACKAGES} && \
    bundle install -j4 && \
    apk del build-dependencies

COPY . ./

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

# pumaを起動させる
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
backend/config/puma.rb
--省略--

# puma起動時にソケットであるpuma.sockを作成する
bind "unix:///app/tmp/sockets/puma.sock"

web/nginx/Dockerfile
# ベースイメージ
FROM nginx:1.21.6-alpine

# Nginxに関わる設定ファイルを全削除
RUN rm -f /etc/nginx/conf.d/*

# 独自の設定ファイルを機能する場所に配置する
COPY nginx.conf /etc/nginx/conf.d/custum.conf

web/nginx/nginx.conf

# Railsのpumaが生成したソケットにnginxを繋ぐ
upstream app {
  server unix:///app/tmp/sockets/puma.sock;
}

server {
  # クライアントからのリクエストを80番ポートで待ち受ける
  listen 80;
  # サーバー名称をlocalhostに設定
  server_name localhost;

  # ドキュメントルートを/app/publicに設定
  root /app/public;
  # 静的ファイルが存在しなければ、@app(=Rails)にリクエストを渡す
  try_files  $uri/index.html $uri @app;

  location @app {
    # プロキシのヘッダー情報をクライアント情報に書き換えする
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    # プロキシの受け渡し先(upstreamで定義したappに合わせる)
    proxy_pass http://app;
  }
}

動作検証

ブラウザでhttp://localhostを入力すれば、Railsの起動画面が表示される。

スクリーンショット 2022-04-04 18.14.34.png

ちなみにVueからaxiosでHTTP通信を図るときは、Nginxの80番ポートに向けて送信すれば通信できる。

参考記事

終わりに

可用性やセキュリティ面を考えると今の設定は不十分だろうな…

時間に余裕があれば、nginxの技術書を完読した上でしっかりしたものを実装したかった。

最後までお読みいただき、ありがとうございました!

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