1
1

Rails + Nginxの本番環境をDockerで構築した話

Posted at

はじめに

以前Railsの本番環境をunicornで立てる実装をしました。

ただ、サーバーをVPSから自宅サーバーに移行する際、サーバーをすべてdockerで立てようとした時にnginx周りとかで色々と詰まったことがあったので記事に記録を残しました。

ディレクトリ構成

- root
  - app
  - bin
  - ...(rails関連のファイル)
  - public
  - .env
  - Dockerfile
  - docker-compose.yml
  - nginx
    - Dockerfile
    - nginx.conf

Docker関連

Dockerfile.
FROM ruby:3.1.2-alpine as builder

RUN apk update && \
  apk add --no-cache \
  build-base \
  postgresql-dev

RUN gem install bundler
COPY Gemfile Gemfile.lock ./
ENV RAILS_ENV=production
RUN RAILS_ENV=${RAILS_ENV} bundle install

FROM ruby:3.1.2-alpine as app

RUN apk update && \
  apk add --no-cache \
  tzdata \
  postgresql-client

WORKDIR /app

COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY . .

CMD ["sh", "entrypoint.sh"]

マルチステージビルド(https://docs.docker.jp/develop/develop-images/multistage-build.html )を使うことで作られるdocker imageのサイズを小さくする工夫をしてあります。

参考: https://qiita.com/sasamuku/items/6aea2b4dffb43de161e3

docker-compose.yml
services:
  rails:
    build:
      context: .
      dockerfile: Dockerfile
    image: rails-app
    container_name: rails-app-rails
    depends_on:
      - db
    env_file:
      - .env
    environment:
      - RAILS_ENV=production
    volumes:
      - public:/app/public
  db:
    image: postgres:15-alpine
    restart: always
    container_name: rails-app-postgres
    volumes:
      - database:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: rails_app_production
  
  nginx:
    container_name: rails-app-nginx
    build:
      context: ./nginx
      dockerfile: Dockerfile
    ports:
      - 54010:80
    depends_on:
      - rails
    volumes:
      - public:/app/public

volumes:
  database:
  public:
  • Railsのpublicディレクトリをvolumeとしてnginxと共有し、nginx上で公開できるようにしています。公開するポートについては、dockerのコンテナ内ネットワークを使ってrailsサーバーのポートへnginxがプロキシするようにしています。
  • env_file.envを指定することで、.envの内容がコンテナ内の環境変数に入るようにしています。
  • nginxについてはnginx/Dockerfileを元にビルドをするようにしています
nginx/Dockerfile.
FROM nginx:alpine

RUN rm -f /etc/nginx/conf.d/*

ADD nginx.conf /etc/nginx/conf.d/nginx.conf

CMD /usr/sbin/nginx -g 'daemon off;'

nginxのDockerfileです。設定ファイル(.conf)をコピーしてnginxサーバーを起動しています。

Rails関係

.env
POSTGRES_USER=...
POSTGRES_PASSWORD=...

.envにはPOSTGRES_USERPOSTGRES_PASSWORDを指定します。

config/database.yml
production:
  <<: *default
  database: rails_app_production
  username: <%= ENV["POSTGRES_USER"] %>
  password: <%= ENV["POSTGRES_PASSWORD"] %>
  host: db

Railsのデータベースの設定を記述します。hostはdockerコンテナ内ネットワークを使用してpostgresサーバーと接続できるようにします。

entrypoint.sh
bin/rails db:migrate
bin/rails assets:precompile
bin/rails server -b 0.0.0.0 -p 3000

サーバー起動時に実行されるコマンドを設定します。起動時にdb:migrateを実行することで起動時にデータベースのスキーマを反映させることができます。assets:precompileは多分Dockerfileの中で行なっても大丈夫だと思う(要検証)。

Nginx関係

nginx/nginx.conf
server {
  listen 80;
  server_name www.example.com;
	root /app/public;

  location @app {
    proxy_pass http://rails:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
	try_files $uri/index.html $uri @app;
	error_page 500 502 503 504 /500.html;
}

Railsのpublicディレクトリを直接公開するよう設定をし、それ以外のURLに対してはRailsサーバーにリクエストを送るようにしています。

おわりに

今回はRails + Nginxサーバーをdockerを用いて公開するよう設定をしました。次回はRailsサーバーとフロントエンドのNextサーバーを組み合わせてdockerで本番環境を構築していこうと思います。

参考資料

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