Files
docker_practice/11_compose/11.7_rails.md
T
yeasy ef2625531d style: 含中文的括号统一为全角(336 处 / 110 文件)
全书此前是真·五五开:含中文的括号 336 处半角 : 336 处全角,而且**在同一文件
内混用**——`18_security/18.1_kernel_ns.md` 第 11/17/20 行写 `(如 runC)`,
第 31 行写 `(用户命名空间映射)`。这不是体例问题,是它自己跟自己不一致。

集群里其余 13 本都一边倒(llm_internals 5 : 1049、oc_guide 2 : 713、
forward_deployed_engineering_guide 0 : 108),blockchain_guide 已在 2026-08-05
按同一方向统一过 97 处,故取全角,而非另立新规。全角括号前后不留空格,
原先 `概念 (镜像、容器、仓库) 和` 两侧的空格一并收掉。

**纯拉丁内容的半角括号一个没动**——`新建一个层 (Layer)`、`项目 (project)`
保持原样:改动前后「半角且内容纯拉丁」的数量都是 **1163**,而「半角且含中文」
从 **336 变成 0**。

其余验证:改动前后各自抹掉全部空白与圆括号后**逐字节相同**(两侧均 19559 字符);
左右括号总数改动前后都是 399 : 399,证明没有吞括号也没有配错对。
`check_project_rules` 202/202、`check_emphasis` 202/202、37 tests OK、
根 `format_checker` 与 `validate_codeblocks` 干净、`git diff --check` 干净。
2026-08-24 13:13:23 -07:00

6.9 KiB
Raw Blame History

11.7 实战 Rails

本小节内容适合 Ruby 开发人员阅读。

版本说明:本示例使用以下镜像版本:

  • Ruby:3.2(可替换为其他 3.x 版本)
  • PostgreSQL:16(可替换为其他 16.x、15.x 等版本)
  • Rails:~> 7.1(可根据项目需求调整)

本节使用 Docker Compose 配置并运行一个 Rails + PostgreSQL 应用。

11.7.1 架构概览

如图 11-2 所示,Rails 与 PostgreSQL 在同一 Compose 网络中协同工作。

flowchart TD
    subgraph Network ["Docker Compose 网络"]
        direction LR
        subgraph Web ["web 服务"]
            direction TB
            Rails["Rails<br/>应用"]
            Port3000[":3000"]
            Rails ~~~ Port3000
        end

        subgraph DB ["db 服务"]
            direction TB
            Postgres["PostgreSQL<br/>数据库"]
        end

        Rails -- ":5432" --> Postgres
    end

    Browser["localhost:3000"]
    Port3000 --> Browser

图 11-2:Rails + PostgreSQL 的 Compose 架构

11.7.2 准备工作

创建项目目录:

$ mkdir rails-docker && cd rails-docker

需要创建三个文件:Dockerfile、Gemfile 和 compose.yaml。

11.7.3 步骤 1:创建 Dockerfile

FROM ruby:3.2

## 安装系统依赖

RUN apt-get update -qq && \
    apt-get install -y build-essential libpq-dev nodejs && \
    rm -rf /var/lib/apt/lists/*

## 设置工作目录

WORKDIR /myapp

## 先复制 Gemfile,利用缓存加速构建

COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install

## 复制应用代码

COPY . /myapp

配置说明:

指令 作用
build-essential 编译原生扩展所需
libpq-dev PostgreSQL 客户端库
nodejs Rails Asset Pipeline 需要
先复制 Gemfile 只有依赖变化时才重新 bundle install

11.7.4 步骤 2:创建 Gemfile

创建一个初始的 Gemfile,稍后会被 rails new 覆盖:

source 'https://rubygems.org'
gem 'rails', '~> 7.1'

创建空的 Gemfile.lock:

$ touch Gemfile.lock

11.7.5 步骤 3:创建 compose.yaml

配置如下。下面为了本地练习使用环境变量占位;不要把真实数据库密码写进 compose.yaml、.env 或 Git,生产环境应使用 Compose secrets、Rails credentials 或平台密钥管理。

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy
    environment:
      DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@db:5432/myapp_development

volumes:
  postgres_data:

配置详解:

配置项 说明
rm -f tmp/pids/server.pid 清理上次异常退出留下的 PID 文件
volumes: .:/myapp 挂载代码目录,支持热更新
depends_on + condition 等待数据库健康检查通过后再启动
DATABASE_URL Rails 12-factor 风格的数据库配置

11.7.6 步骤 4:生成 Rails 项目

使用 docker compose run 生成项目骨架:

$ docker compose run --rm web rails new . --force --database=postgresql --skip-bundle

命令解释:

  • --rm:执行后删除临时容器
  • --force:覆盖已存在的文件
  • --database=postgresql:配置使用 PostgreSQL
  • --skip-bundle:暂不安装依赖(稍后统一安装)

生成的目录结构:

$ ls
Dockerfile       Gemfile          Rakefile         config           lib              tmp
Gemfile.lock     README.md        app              config.ru        log              vendor
compose.yaml     bin              db               public

⚠️ Linux 用户:如遇权限问题,执行 sudo chown -R $USER:$USER .

11.7.7 步骤 5:重新构建镜像

由于生成了新的 Gemfile,需要重新构建镜像以安装完整依赖:

$ docker compose build

11.7.8 步骤 6:配置数据库连接

修改 config/database.yml:

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  url: <%= ENV['DATABASE_URL'] %>

development:
  <<: *default

test:
  <<: *default
  database: myapp_test

production:
  <<: *default

💡 使用 DATABASE_URL 环境变量配置数据库,符合 12-factor 应用原则,便于在不同环境间切换。

11.7.9 步骤 7:启动应用

$ docker compose up

输出示例:

db-1   | PostgreSQL init process complete; ready for start up.
db-1   | LOG:  database system is ready to accept connections
web-1  | => Booting Puma
web-1  | => Rails 7.1.0 application starting in development
web-1  | => Run `bin/rails server --help` for more startup options
web-1  | Puma starting in single mode...
web-1  | * Listening on http://0.0.0.0:3000

11.7.10 步骤 8:创建数据库

在另一个终端执行:

$ docker compose exec web rails db:create
Created database 'myapp_development'
Created database 'myapp_test'

访问 http://localhost:3000 查看 Rails 欢迎页面。

11.7.11 常用开发命令

## 数据库迁移

$ docker compose exec web rails db:migrate

## Rails 控制台

$ docker compose exec web rails console

## 运行测试

$ docker compose exec web rails test

## 生成脚手架

$ docker compose exec web rails generate scaffold Post title:string body:text

## 进入容器 Shell

$ docker compose exec web bash

11.7.12 常见问题

Q:数据库连接失败

检查 DATABASE_URL 环境变量格式是否正确,确保 db 服务已启动:

$ docker compose ps
$ docker compose logs db

Q:server.pid 文件导致启动失败

错误信息:A server is already running

已在 command 中添加 rm -f tmp/pids/server.pid 处理。如仍有问题:

$ docker compose exec web rm -f tmp/pids/server.pid

Q:Gem 安装失败

可能需要更新 bundler 或清理缓存:

$ docker compose run --rm web bundle update

11.7.13 开发 vs 生产

配置项 开发环境 生产环境
Rails 服务器 Puma(开发模式) Puma + Nginx
代码挂载 使用 volumes 代码打包进镜像
静态资源 动态编译 预编译 (rails assets:precompile)
数据库密码 明文配置 使用 Secrets 管理

11.7.14 延伸阅读