You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker-compose二次启动触发ActiveRecord::ProtectedEnvironmentError求助

问题描述

首次执行docker-compose up时应用可正常运行,但后续启动容器时出现如下报错:

Database 'time_distribution_production' already exists.
ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database.
If you are sure you want to continue, run the same command with the environment variable:
DISABLE_DATABASE_ENVIRONMENT_CHECK=1

执行docker compose down -volumes重置卷后报错消失,但仅重启容器无法解决问题。

相关配置文件

Dockerfile

FROM ruby:3.1.2

ENV BUNDLER_VERSION=2.3.24

RUN apt update -qq && apt install -y libmsgpack-dev postgresql-client

RUN gem install bundler -v 2.3.24

RUN mkdir /time-distribution
WORKDIR /time-distribution

ENV RAILS_ENV production

COPY Gemfile .
COPY Gemfile.lock .

RUN bundle install

COPY . .

EXPOSE 3000

RUN chmod +x docker.sh
CMD ./docker.sh

docker.sh

#!/bin/bash
set -e

rm -f tmp/pids/server.pid

bundle exec rails db:setup
bundle exec rails db:migrate
bundle exec rails assets:precompile

bundle exec rails server -p 3000 -b '0.0.0.0'

docker-compose.production.yml

version: '3'

services:
  app:
    image: $IMAGE_NAME
    restart: always

  database:
    restart: always

生产环境database.yml

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


production:
  <<: *default
  database: <%= Rails.application.credentials.dig(:production, :postgres_name) %>
  username: <%= Rails.application.credentials.dig(:production, :postgres_username) %>
  password: <%= Rails.application.credentials.dig(:production, :postgres_password) %>
  host: database

解决方案

问题根源是每次容器启动时都会执行bundle exec rails db:setup,而db:setup包含db:create(创建数据库)操作,当数据库已存在时,该操作就会触发保护性报错。

方法一:使用安全的数据库创建命令

修改docker.sh,将bundle exec rails db:setup替换为bundle exec rails db:create --skip-if-exists,该命令仅在数据库不存在时执行创建操作:

# 替换前
bundle exec rails db:setup
# 替换后
bundle exec rails db:create --skip-if-exists

后续启动容器时,只会检查数据库是否存在,不存在才创建,不会触发报错。

方法二:仅首次初始化时执行完整setup

如果需要保留db:setup的完整逻辑(比如加载seed数据),可以通过判断数据库状态来分支执行:
修改docker.sh中的数据库操作部分:

rm -f tmp/pids/server.pid

# 检查数据库是否已存在
bundle exec rails db:exists
if [ $? -ne 0 ]; then
  bundle exec rails db:setup
else
  bundle exec rails db:migrate
fi

bundle exec rails assets:precompile
bundle exec rails server -p 3000 -b '0.0.0.0'

首次启动时数据库不存在,执行db:setup完成初始化;后续启动时直接执行db:migrate处理新的迁移脚本即可。

内容的提问来源于stack exchange,提问作者Irina Egorova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:15:33