使用Docker构建Rails + Nginx的生产环境的故事
首先
我以前曾经在Rails的生产环境中使用unicorn进行部署实施。
然而,当我将服务器从VPS迁移到家用服务器时,我尝试使用Docker来搭建所有的服务器时遇到了一些问题,特别是在nginx方面,因此我写下了这篇文章来记录下来。
目录结构
- root
- app
- bin
- ...(rails関連のファイル)
- public
- .env
- Dockerfile
- docker-compose.yml
- nginx
- Dockerfile
- nginx.conf
Docker相关
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镜像的大小。
参考: https://qiita.com/sasamuku/items/6aea2b4dffb43de161e3
参考链接: https://qiita.com/sasamuku/items/6aea2b4dffb43de161e3
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を元にビルドをするようにしています
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服务器。
铁轨相关
POSTGRES_USER=...
POSTGRES_PASSWORD=...
在.env文件中指定POSTGRES_USER和POSTGRES_PASSWORD。
production:
<<: *default
database: rails_app_production
username: <%= ENV["POSTGRES_USER"] %>
password: <%= ENV["POSTGRES_PASSWORD"] %>
host: db
我們要記錄Rails的數據庫設置。我們會使用Docker容器內的網絡來連接到PostgreSQL服務器。
bin/rails db:migrate
bin/rails assets:precompile
bin/rails server -b 0.0.0.0 -p 3000
在服务器启动时设置要执行的命令。通过在启动时执行db:migrate命令,可以在启动时反映数据库模式。我认为可以在Dockerfile中执行assets:precompile(需要验证)。
Nginx相关
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服务器。
最后
这次我们使用Docker来配置Rails + Nginx服务器进行公开。下一步,我们计划使用Docker来搭建将Rails服务器和前端Next服务器组合起来的生产环境。
请先参考相关资料。