【Ruby on Rails】在使用docker-compose运行Rails时的最小配置
前言
这篇文章是DMM WEBCAMP 2023年圣诞礼物日历的第二天文章。
请务必查看我们的其他文章,因为DWC导师和毕业生以Ruby on Rails为中心撰写了这些文章!
首先
你好,我是DMM WEBCAMP的导师@ukwhatn。
我在工作和私人生活中都使用Rails编写代码,尤其是在针对Rails 7的配置方面,我尝试在Docker(docker compose)中运行却找不到太多相关的资料,让我感到困惑了好几次。
虽然有像Ryan Williams的rails7-on-docker这样的模板仓库,但其中包含的内容有点过多,有些部分使用起来有些困难。
因此,本次我将介绍我个人构建的用于在Docker上运行Rails 7的模板存储库,并解释其内容。
得出結論
这是我做的。
在本文中,我们将简要解释这个模板仓库的重要部分。
说明
Docker相关
首先,我们来看一下关于”Docker运行”的部分。
编写.yml
服务:
网络:
构建:
上下文:。
Dockerfile:./deployment/dockerfiles/web/Dockerfile
参数:
RUBY_VERSION:3.2.2
镜像:web-dev
入口点:[“bin/docker-entrypoint.sh”]
命令:bash -c “rm -f tmp/pids/server.pid && bin/rails s -p 3000 -b ‘0.0.0.0’”
挂载卷:
– .:/usr/src/app
– bundle:/usr/local/bundle
端口:
– “127.0.0.1:59998:3000”
环境变量:
– HISTFILE=/usr/src/app/log/.bash_history
– RAILS_ENV=development
– DB_HOST=${DEV_DB_HOST}
– DB_PORT=${DEV_DB_PORT}
– DB_USER=${DEV_DB_USER}
– DB_PASSWORD=${DEV_DB_PASSWORD}
依赖:
db:
条件:service_healthy
redis:
条件:service_healthy数据库:
镜像:postgres:15.4
环境变量:
– POSTGRES_USER=${DEV_DB_USER}
– POSTGRES_PASSWORD=${DEV_DB_PASSWORD}
挂载卷:
– pg_data:/var/lib/postgresql/data
重启:始终
健康检查:
测试:pg_isready -U postgres
间隔:2秒
超时:5秒
重试:30次
Redis:
镜像:redis:7.2.0
挂载卷:
– redis_data:/data
健康检查:
测试:redis-cli ping
间隔:2秒
超时:5秒
重试:30次
挂载卷:
pg_data:
redis_data:
bundle:
↑可以准确地说是compose.dev.yml的内容。
虽然还有compose.stg.yml和compose.prod.yml,但只是环境变量的前缀不同,所以略过不提。
在这个compose.yml中,以下容器将会运行。
web
railsアプリ本体が動作するコンテナです
Dockerfileは後述
ポイント
build引数としてRUBY_VERSIONを定義し、Dockerfileから参照することでベースイメージのバージョンを切り替えられるようにしています
environmentでRAILS_ENVやDB接続情報を渡しており、これを切り替えることでdev/stg/prodを分けています
depends_onでpostgresやredisの立ち上がり(service_healthy)を待ってからwebコンテナを上げています
db
みんな大好きpostgresのオフィシャルイメージです
ポイント
environmentで渡しているPOSTGRES_USERとPOSTGRES_PASSWORDはrailsに渡しているものと共通です
pg_isready -U postgresでhealthcheckを行うことで、service_healthyコンディションによるdepends_onを有効化しています
redis
セッションストアとして利用するためのredisコンテナです
ポイント
redis-cli pingでhealthcheckを行うことで、service_healthyコンディションによるdepends_onを有効化しています
Dockerfile(网络版)
在 deployment/dockerfiles/web/Dockerfile 文件中可以找到。
ARG RUBY_VERSIONFROM ruby:${RUBY_VERSION}-slim
# OS级别的依赖
RUN –mount=type=cache,target=/var/cache/apt \
–mount=type=cache,target=/var/lib/apt,sharing=locked \
–mount=type=tmpfs,target=/var/log \
rm -f /etc/apt/apt.conf.d/docker-clean; \
echo ‘Binary::apt::APT::Keep-Downloaded-Packages “true”;’ > /etc/apt/apt.conf.d/keep-cache; \
apt-get update -qq \
&& apt-get install -yq –no-install-recommends \
build-essential \
gnupg2 \
less \
git \
libpq-dev \
postgresql-client \
libvips \
curl
ENV LANG=C.UTF-8 \
BUNDLE_JOBS=4 \
BUNDLE_RETRY=3
RUN gem update –system && gem install bundler
WORKDIR /usr/src/app
ENTRYPOINT [“./bin/docker-entrypoint.sh”]
EXPOSE 3000
我没有做太复杂的事情。
如果想要将数据库更改为MySQL之类的,请在此处安装适当的库,而不是libpq-dev或postgresql-client。
docker入口点脚本
这个位于bin/docker-entrypoint.sh的文件。
这是在compose.yml中设置的入口点。
#!/bin/bash
set -eecho -e “———————-\n初始化Rails应用程序\n模式:$RAILS_ENV\n———————-\n”
# 删除可能已存在的Rails服务器进程文件
rm -f /usr/src/app/tmp/pids/server.pid
echo “rails: 安装gems…”
bundle check || bundle install –jobs 4
echo “rails: 创建数据库…”
bundle exec rake db:create
echo “rails: 迁移数据库…”
bundle exec rake db:migrate
# 如果是生产模式,则编译assets
if [ “$RAILS_ENV” = ‘production’ ]; then
echo “rails: 预编译assets…”
bundle exec rake assets:precompile
fi
# 然后执行容器的主进程(即Dockerfile中设置的CMD命令)
exec “$@”
只需要一种选项:
我所做的事情很简单,
-
- 删除server.pid
-
- 安装bundle
-
- 进行数据库迁移
- 编译资产预编译(仅在生产模式下)
只需要以下一个选项:
如果在创建容器时有想要执行的任务,请在此处进行补充。
关于Docker,重要的事情大致就是这样。
总的来说,并不涉及太多复杂的事情,所以请根据需要进行修改和使用。
Ruby on Rails相关
我们将从这里开始查看在程序内部运行的Rails配置文件等。
Gemfile: 珠宝文件
代码
# 冻结字符串文字
# frozen_string_literal: true
source “https://rubygems.org”
git_source(:github) { |repo| “https://github.com/#{repo}.git” }
ruby “3.2.2”
# Rails 7
gem “rails”, “~> 7.0.7”, “>= 7.0.7.2”
# 用于资源管道
gem “sprockets-rails”
# Postgresql 驱动
gem “pg”, “~> 1.1”
# Web 服务器
gem “puma”, “~> 6.3”
# 使用import maps
gem “importmap-rails”
# 使用 Turbo
gem “turbo-rails”
# Stimulus 框架
gem “stimulus-rails”
# JSON 构建器
gem “jbuilder”
# Redis
gem “redis”, “~> 4.8.1”, “< 5” gem “redis-rails” # 创建密码哈希 # gem “bcrypt”, “~> 3.1.7”
# 用于 Windows 的时区
gem “tzinfo-data”, platforms: %i[mingw mswin x64_mingw jruby]
# 通过缓存减少启动时间
gem “bootsnap”, require: false
# 使用 Sass 处理 CSS
gem “dartsass-rails”
gem “sassc-rails”
# 使用 Active Storage 变体
gem “image_processing”, “~> 1.2”
# 用于本地化
gem “i18n_generators”
gem “rails-i18n”
# 用于读取 .env 文件
# gem “dotenv-rails”
# 用于 Discord OAuth2
# gem “omniauth-discord”
# 用于 Google OAuth2
# gem “omniauth-google-oauth2”
# 用于 GitHub OAuth2
# gem “omniauth-github”
# 用于 omniauth 的 CSRF 保护
# gem “omniauth-rails_csrf_protection”
group :development, :test do
# 查看 https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem “brakeman”
gem “bundler-audit”
gem “debug”, “1.8.0”, platforms: %i[mri mingw x64_mingw]
gem “rspec-rails”
gem “rubocop”
gem “rubocop-performance”
gem “rubocop-rails”
gem “rubocop-rspec”
end
group :development do
# 在异常页面上使用控制台 [https://github.com/rails/web-console]
gem “web-console”
# 添加速度徽章 [https://github.com/MiniProfiler/rack-mini-profiler]
gem “rack-mini-profiler”
# 对于运行缓慢的机器/大型应用程序加速命令 [https://github.com/rails/spring]
# gem “spring”
end
group :test do
# 使用系统测试 [https://guides.rubyonrails.org/testing.html#system-testing]
gem “capybara”
gem “selenium-webdriver”
gem “webdrivers”
end
“`
Note: This reply has been adjusted, and no longer reflects the answer to the original question.
如果想要使用OAuth2,请取消注释omniauth系列的Gem。在这里并没有太多偏离模板的地方。
.rubocop.yml的中文简 paragr 和忠。
require:
– rubocop-rails
– rubocop-rspec
– rubocop-capybara
– rubocop-performanceAllCops:
TargetRubyVersion: 3.2.2
TargetRailsVersion: 7.0.1
DisabledByDefault: true
DisplayCopNames: true
NewCops: enable
Exclude:
– “bin/**/*”
– “vendor/**/*”
– “public/**/*”
– “node_modules/**/*”
– “db/schema.rb”
# —– bundler —–
Bundler:
Enabled: true
# —– layout —–
Layout:
Enabled: true
# —– lint —–
Lint:
Enabled: true
Lint/EmptyBlock:
Enabled: false
Exclude:
– “config/routes.rb”
# —– naming —–
Naming:
Enabled: true
# —– security —–
Security:
Enabled: true
# —– performance —–
Performance:
Enabled: true
# —– style —–
# ブロックの終了部分が適切にスタイル指定されているか
Style/EndBlock:
Enabled: true
# ハッシュの構文が適切か
Style/HashSyntax:
Enabled: true
# 文字列リテラルが適切にスタイル指定されているか
Style/StringLiterals:
Enabled: true
EnforcedStyle: “double_quotes”
Exclude:
– “config/**/*.rb”
– Rakefile
# caseの等価性が適切にチェックされているか
Style/CaseEquality:
Enabled: true
# クラスメソッドが適切に定義されているか
Style/ClassMethods:
Enabled: true
# クラス変数が適切に使用されているか
Style/ClassVars:
Enabled: true
# collectionメソッドが適切に使用されているか
Style/CollectionMethods:
Enabled: true
PreferredMethods:
collect: “map”
collect!: “map!”
inject: “reduce”
detect: “find”
find_all: “select”
因为这是一个模板仓库,所以我将rubocop只设为true必要的部分。特别是Style/*部分,请根据需要进行增删。
session_store.rb是一个Ruby文件。
这可以在config/initializers/session_store.rb文件中找到。
secure = Rails.env.production?
key = Rails.env.production? ? “_app_session” : “_app_session_#{Rails.env}”
domain = ENV.fetch(“APP_DOMAIN”, “localhost”)Rails.application.config.session_store :redis_store,
servers: %w(redis://redis:6379/0/session),
expire_after: 90.minutes,
key: key,
domain: domain,
secure: secure,
httponly: true,
threadsafe: true
请查看redis-rails官方README文件以获取设置值。
我认为只有expire_after可能需要更改。
可以根据需要进行自定义,Rails的部分如下。
其他
Makefile -> 文件
因为键入docker命令太麻烦了,所以我把它们整理到了Makefile中。
.PHONY:测试构建DIR_NAME:= $(shell basename $(CURDIR))
初始化:
cp .env.example .env
开发:
构建开发
上升开发
记录开发
构建开发:
集装箱构建-dev.ym文件
上升开发:
集装箱构成开发.yml文件 -d
下降开发:
集装箱开发文件 -d
清洁开发:
集装箱构成开发.yml文件 -d –rmi all –volumes –remove-orphans
记录开发:
集装箱构成开发.yml文件-日志 -f
产品:
构建产品
上升产品
记录产品
构建产品:
集装箱构建prod.yml文件
上升产品:
集装箱构成prod.yml文件 -d
下降产品:
集装箱产品文件 -d
记录产品:
集装箱构成prod.yml文件-日志 -f
Redis-cli:
集装箱构成开发.yml文件 -执行Redis redis-cli
例子环境变量文件
我们使得在开发/测试/生产环境中能够进行选择。
DEV_DB_HOST=”db”
DEV_DB_PORT=”5432″
DEV_DB_USER=”postgres”
DEV_DB_PASSWORD=”changeme”# — 部署 —
STG_DB_HOST=”db”
STG_DB_PORT=”5432″
STG_DB_USER=”postgres”
STG_DB_PASSWORD=”changeme”
# — 测试 —
TEST_DB_HOST=”db”
TEST_DB_PORT=”5432″
TEST_DB_USER=”postgres”
TEST_DB_PASSWORD=”changeme”
# — 生产 —
PROD_DB_HOST=”db”
PROD_DB_PORT=”5432″
PROD_DB_USER=”postgres”
PROD_DB_PASSWORD=”changeme”
dependabot.yml 可信赖的机器人配置文件
在 .github/depandabot.yml 文件中可以找到
版本:2
更新:
– 包-生态系统:docker
目录: “/”
计划:
时间间隔:每日
– 包-生态系统:bundler
目录: “/”
计划:
时间间隔:每日
忽略:
– 依赖名称:”rails”
更新类型:[“版本更新:语义化主要版本”, “版本更新:语义化次要版本”]
– 包-生态系统:github-actions
目录: “/”
计划:
时间间隔:每日
当我们阅读Gemfile时,如果有更新,就会为我们创建一个PR。考虑到其便利性,建议我们将其启用。
就是这样。
由于这个模板是比较随意地制作的,所以如果您有任何疑问或建议,请在评论或PR中提出。
由于我们将在明天继续发布,因此请期待我们的圣诞倒数日历!