使用 React 前端应用程序将 Ruby on Rails 容器化可以显著改善您的开发工作流程和部署过程。通过为您的应用程序创建标准化环境,您可以确保在开发、测试、生产的不同阶段,甚至不同系统之间保持一致的行为。事实上,它旨在最大限度地减少与系统差异相关的问题。本指南将引导您完成让您的 Rails 和 React 应用程序在 Docker 容器中顺利运行的基本步骤。 为什么要对应用程序进行 Docker 化? : 跨环境的一致性 Docker 确保应用程序无论部署在何处(无论是在开发人员的机器、测试环境还是生产服务器上)都以相同的方式运行。这种一致性是通过容器化所有依赖项和配置来实现的。 : 依赖管理 Docker 容器包含应用程序运行所需的所有依赖项。这意味着系统库的变化或不同系统上缺少的依赖项不会影响应用程序的功能。 : 隔离 Docker 容器彼此独立运行,并且与主机系统隔离。这种隔离可防止同一系统上不同应用程序及其依赖项之间发生冲突。 : 可移植性 Docker 容器可以轻松移动并运行在任何支持 Docker 的系统上,无论是本地机器、云服务还是专用服务器。这使得应用程序在部署方面具有高度的可移植性和灵活性。 注意: 需要了解 Docker 语法 Docker 化涉及两个关键概念:镜像和容器。镜像是容器的蓝图,包含创建容器所需的所有信息,包括依赖项和部署配置。容器是镜像的运行时实例,由镜像本身、执行环境和运行时指令组成。总体而言,Docker 为软件的运输建立了标准。 用一个简单的类比来解释 Docker:将容器想象成院子里的集装箱,将图像想象成放置在这些集装箱内的物品,将运输船想象成运行容器的系统。 无论何时设置和构建应用程序,某些环境配置都是必需的。例如,如果系统上没有安装 Ruby 环境,则无法运行 Rails 应用程序。同样,如果没有 ,则无法运行 React 应用程序,如果没有 或 等 Node 包管理器,则无法安装 React 包。 Node.js npm Yarn 由于容器与用户系统隔离运行,我们将使所有这些包在我们的容器中可用,就像我们直接在我们的系统上构建它一样,因此,容器将作为一个独立的系统,就像虚拟机一样。docker 和虚拟机之间存在差异,但这个例子只是为了进一步解释。 现在,让我们继续将 Rails 应用程序 docker 化。为此,我们将需要 Rails 应用程序中的三个文件: 、 和 。让我们详细检查每个文件。 Dockerfile docker-compose.yml bin/docker-entrypoint 注意: 需要了解 Docker 语法 Dockerfile 是创建 Docker 容器的蓝图。它包含 Docker 用于构建映像的一系列指令,然后可以使用这些指令运行容器。让我们分解 Ruby on Rails 和 React 应用程序的 : Dockerfile Dockerfile . 基础镜像 ARG RUBY_VERSION=3.1.4 FROM ruby:$RUBY_VERSION :定义一个名为 的构建参数,默认值为 。这可以在构建时被覆盖。 ARG RUBY_VERSION=3.1.4 RUBY_VERSION 3.1.4 :使用由 指定的版本的 基础镜像。这将使用 Ruby 运行时设置容器。正如我之前提到的,要运行 Rails 应用程序,您需要安装 Ruby。 FROM ruby:$RUBY_VERSION RUBY_VERSION ruby 2.安装依赖项 RUN apt-get update -qq && \ apt-get install -y build-essential libvips bash bash-completion libffi-dev tzdata postgresql curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man :从存储库更新软件包列表,使用 进行静默输出。 apt-get update -qq -qq :安装各种软件包: apt-get install -y ... :构建软件的基本软件包(如 GCC)。 build-essential :图像处理库。 libvips , :Bash shell 及其自动完成功能。 bash bash-completion :外部函数接口库。 libffi-dev :时区数据。 tzdata :PostgreSQL 数据库客户端。 postgresql :从 URL 传输数据的工具。 curl :清理检索到的包文件的本地存储库。 apt-get clean :删除软件包列表和文档以减小图像大小。 rm -rf /var/lib/apt/lists/ /usr/share/doc /usr/share/man 3.安装Node.js和Yarn RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && \ apt-get install -y nodejs && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && \ apt-get install -y yarn :下载并运行 NodeSource 安装脚本来安装 Node.js。 curl -fsSL https://deb.nodesource.com/setup_current.x | bash - :安装 Node.js。 apt-get install -y nodejs :添加 Yarn GPG 密钥来验证其软件包。 curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - :将 Yarn 的存储库添加到源列表中。 echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list :更新包列表并安装 Yarn。 apt-get update && apt-get install -y yarn 4.环境变量 ENV NODE_OPTIONS=--openssl-legacy-provider :设置环境变量以启用对 Node.js 的旧版 OpenSSL 支持。 ENV NODE_OPTIONS=--openssl-legacy-provider 5.设置工作目录 WORKDIR /rails :将后续指令的工作目录设置为 。 WORKDIR /rails /rails 6. 建立参数和环境变量 ARG RAILS_ENV ENV RAILS_ENV=$RAILS_ENV :定义一个名为 的构建参数,用于指定 Rails 环境(如 、 、 )。 ARG RAILS_ENV RAILS_ENV development test production :将环境变量 设置为构建参数的值。 ENV RAILS_ENV=$RAILS_ENV RAILS_ENV 7. 安装应用程序 Gems COPY Gemfile Gemfile.lock ./ RUN bundle install :将 和 复制到工作目录。 COPY Gemfile Gemfile.lock ./ Gemfile Gemfile.lock :安装 中指定的 Ruby 宝石。 RUN bundle install Gemfile 8. 安装前端依赖项 COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile :将 和 复制到工作目录。 COPY package.json yarn.lock ./ package.json yarn.lock :使用 Yarn 安装前端依赖项,确保它使用 中的精确版本。 RUN yarn install --frozen-lockfile yarn.lock 9.复制应用程序代码 COPY . . :将所有应用程序代码复制到工作目录。 COPY . . 10.预编译Bootsnap代码 RUN bundle exec bootsnap precompile --gemfile app/ lib/ :预编译 Bootsnap 缓存,以加快 Rails 应用程序的启动时间。Bootsnap 是一个通过缓存昂贵的计算来加快 Ruby 和 Rails 启动时间的 gem。 RUN bundle exec bootsnap precompile --gemfile app/ lib/ 11. 预编译生产资源 RUN if [ "$RAILS_ENV" = "production" ]; then \ SECRET_KEY_BASE=1 bin/rails assets:precompile; \ fi :仅当 设置为 时才有条件地运行资产预编译。此步骤对于为生产环境准备资产至关重要。 RUN if [ "$RAILS_ENV" = "production" ]; then ... RAILS_ENV production 12.入口点脚本 COPY bin/docker-entrypoint /rails/bin/ RUN chmod +x /rails/bin/docker-entrypoint :将自定义入口点脚本复制到容器。 COPY bin/docker-entrypoint /rails/bin/ :使入口点脚本可执行。 RUN chmod +x /rails/bin/docker-entrypoint 13. 定义入口点和命令 ENTRYPOINT ["/rails/bin/docker-entrypoint"] EXPOSE 5000 // you can use any port of your choice CMD ["./bin/rails", "server"] :设置容器启动时将运行的入口点脚本。此脚本通常设置环境、准备数据库并启动应用程序。 ENTRYPOINT ["/rails/bin/docker-entrypoint"] :表示容器监听 5000 端口,这是一个文档功能,并不发布端口。 EXPOSE 5000 :指定容器启动时默认运行的命令,即启动Rails服务器。 CMD ["./bin/rails", "server"] docker-compose.yml 文件用于定义和运行多容器 Docker 应用程序。它允许您在单个文件中配置应用程序的服务、网络和卷。在本例中,我们将使用两个服务。以下是 Rails 应用程序的 文件: docker-compose.yml docker-compose.yml 1. ) 数据库服务( db codedb: image: postgres:14.2-alpine container_name: demo-postgres-14.2 volumes: - postgres_data:/var/lib/postgresql/data command: "postgres -c 'max_connections=500'" environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - "5432:5432" :指定用于此服务的 Docker 映像。在本例中,它是基于 Alpine Linux 发行版的 PostgreSQL 14.2 映像。Alpine 映像以体积小而闻名,这有助于降低整体映像大小。 image: postgres:14.2-alpine :将容器命名为 。此名称用于在命令和日志中引用容器。 container_name: demo-postgres-14.2 demo-postgres-14.2 volumes : 将命名卷 挂载到容器内的 。此目录是 PostgreSQL 存储其数据的地方,确保数据库数据在容器重启之间保持不变。 postgres_data:/var/lib/postgresql/data: postgres_data /var/lib/postgresql/data :覆盖 PostgreSQL 映像的默认命令。它使用配置选项启动 PostgreSQL,以将最大连接数增加到 500。 command: "postgres -c 'max_connections=500'" environment : :使用环境变量 设置要创建的默认数据库的名称。 POSTGRES_DB: ${POSTGRES_DB} POSTGRES_DB :使用 环境变量设置访问 PostgreSQL 数据库的默认用户名。 POSTGRES_USER: ${POSTGRES_USER} POSTGRES_USER :使用 环境变量设置默认用户的密码。 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_PASSWORD ports : :将主机上的端口 5432 映射到容器中的端口 5432。这允许通过端口 5432 访问主机上的 PostgreSQL。 "5432:5432" 2. ) Web 应用服务 ( demo-web codedemo-web: build: context: . args: - RAILS_ENV=${RAILS_ENV} command: "./bin/rails server -b 0.0.0.0" environment: - RAILS_ENV=${RAILS_ENV} - POSTGRES_HOST=${POSTGRES_HOST} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - RAILS_MASTER_KEY=${RAILS_MASTER_KEY} volumes: - .:/rails - app-storage:/rails/storage depends_on: - db ports: - "3000:3000" build: :指定 Docker 镜像的构建上下文。在本例中, 指的是当前目录。这意味着 Docker 将使用当前目录中的 Dockerfile 来构建镜像。 context: . . args : :将 构建参数传递给 Docker 构建过程,允许您指定 Rails 环境(如 、 或 )。 RAILS_ENV=${RAILS_ENV} RAILS_ENV development test production :覆盖 Docker 镜像的默认命令。启动 Rails 服务器并将其绑定到所有网络接口 ( ),这对于从容器外部访问服务是必需的。 command: "./bin/rails server -b 0.0.0.0" 0.0.0.0 environment: :使用 环境变量设置容器内的 Rails 环境。 RAILS_ENV=${RAILS_ENV} RAILS_ENV :设置 PostgreSQL 主机地址。 POSTGRES_HOST=${POSTGRES_HOST} :设置数据库名称。 POSTGRES_DB=${POSTGRES_DB} :设置 PostgreSQL 用户。 POSTGRES_USER=${POSTGRES_USER} :设置 PostgreSQL 用户密码。 POSTGRES_PASSWORD=${POSTGRES_PASSWORD} :设置 Rails 主密钥,用于加密凭证和其他机密。 RAILS_MASTER_KEY=${RAILS_MASTER_KEY} volumes : :将当前目录( 文件所在的目录)挂载到容器内的 。这样您就可以在主机上编辑文件,并将这些更改反映在容器内。 .:/rails docker-compose.yml /rails :将命名卷 挂载到容器内的 。这通常用于存储 Rails 特定文件,例如日志、上传和缓存文件。 app-storage:/rails/storage app-storage /rails/storage depends_on : :确保 服务在启动前等待 服务准备就绪。Docker Compose 根据此设置处理启动服务的顺序。 db demo-web db ports: :将主机上的端口 3000 映射到容器中的端口 3000。这样你就可以通过端口 3000 访问主机上的 Rails 应用程序。 "3000:3000" 卷 codevolumes: postgres_data: app-storage: :定义一个命名卷 ,由 服务用来保存 PostgreSQL 数据。 postgres_data postgres_data db :定义一个命名卷 ,由 服务用来保存特定于应用程序的数据,例如上传和日志。 app-storage app-storage demo-web bin/docker-entrypoint 脚本是 Docker 设置的关键部分。它在容器启动时执行,通常处理环境设置、数据库准备以及启动主应用程序之前所需的其他初始化任务。以下是 脚本示例以及每个部分的详细说明: bin/docker-entrypoint bin/docker-entrypoint 发生错误时退出 bashCopy code#!/bin/bash set -e :此行指定应使用 Bash shell 运行脚本。 #!/bin/bash :如果任何命令返回非零退出代码,则指示脚本立即退出。这有助于确保如果任何步骤失败,脚本将停止执行,从而可以防止后续步骤在无效状态下运行。 set -e 有条件的数据库创建或迁移 # If running the rails server then create or migrate existing database if [ "${*}" == "./bin/rails server" ]; then ./bin/rails db:create ./bin/rails db:prepare fi :此条件语句检查传递给脚本的命令 ( ) 是否为 。 是一个特殊参数,它保存传递给脚本的所有位置参数。 if [ "${*}" == "./bin/rails server" ]; then ... fi "${*}" ./bin/rails server * ./bin/rails 数据库 :如果满足条件,此命令将尝试创建数据库。它相当于运行 ,按照数据库配置文件 ( ) 中的定义设置数据库。 rails db:create config/database.yml ./bin/rails 数据库 :此命令将运行 ,以确保数据库已设置并迁移。如果数据库不存在,它将创建数据库;如果数据库已创建,它将运行迁移。这是 和 的组合。 rails db:prepare rails db:create rails db:migrate 执行主流程 bashCopy codeexec "${@}" :这会将当前 shell 进程替换为作为参数传递给脚本的命令。 符号包含传递给脚本的所有位置参数。例如,如果使用 调用脚本,则此行实际上会将 作为容器的主进程运行。 exec "${@}" @ ./bin/rails server ./bin/rails server 结论 精心编写的 对于为 Ruby on Rails 和 React 应用程序创建可靠且一致的环境至关重要。通过定义基础映像、设置环境变量和安装依赖项,您可以确保应用程序在各种环境中顺利运行。 Dockerfile Docker 不仅简化了您的开发流程,还提高了生产中应用程序的可靠性。虽然还有一些需要优化的地方,但这只是对如何将 Rails 应用程序 docker 化的一般概述。 生成的 、 和 的完整脚本 Dockerfile docker-compose.yml bin/docker-entrypoint ARG RUBY_VERSION=3.1.4 FROM ruby:$RUBY_VERSION # Install dependencies RUN apt-get update -qq && \ apt-get install -y build-essential libvips bash bash-completion libffi-dev tzdata postgresql curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man # Install Node.js and Yarn RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && \ apt-get install -y nodejs && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && \ apt-get install -y yarn # Set environment variable to enable legacy OpenSSL support ENV NODE_OPTIONS=--openssl-legacy-provider # Rails app lives here WORKDIR /rails # Set environment variable for the build ARG RAILS_ENV ENV RAILS_ENV=$RAILS_ENV # Install application gems COPY Gemfile Gemfile.lock ./ RUN bundle install # Install frontend dependencies COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile # Copy application code COPY . . # Precompile bootsnap code for faster boot times RUN bundle exec bootsnap precompile --gemfile app/ lib/ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY RUN if [ "$RAILS_ENV" = "production" ]; then \ SECRET_KEY_BASE=1 bin/rails assets:precompile; \ fi # Entrypoint prepares the database. COPY bin/docker-entrypoint /rails/bin/ RUN chmod +x /rails/bin/docker-entrypoint # Use an absolute path for the entry point script ENTRYPOINT ["/rails/bin/docker-entrypoint"] # Start the server by default, this can be overwritten at runtime EXPOSE 5000 CMD ["./bin/rails", "server"] services: db: image: postgres:14.2-alpine container_name: demo-postgres-14.2 volumes: - postgres_data:/var/lib/postgresql/data command: "postgres -c 'max_connections=500'" environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - "5432:5432" demo-web: build: context: . args: - RAILS_ENV=${RAILS_ENV} command: "./bin/rails server -b 0.0.0.0" environment: - RAILS_ENV=${RAILS_ENV} - POSTGRES_HOST=${POSTGRES_HOST} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - RAILS_MASTER_KEY=${RAILS_MASTER_KEY} volumes: - .:/rails - app-storage:/rails/storage depends_on: - db ports: - "3000:3000" volumes: postgres_data: app-storage: #!/bin/bash set -e # If running the rails server then create or migrate existing database if [ "${*}" == "./bin/rails server" ]; then ./bin/rails db:create ./bin/rails db:prepare fi exec "${@}"