【问题标题】:What is the correct way to seed a rails app in docker so it can be started repeatedly在docker中播种rails应用程序的正确方法是什么,以便它可以重复启动
【发布时间】:2020-09-25 18:02:26
【问题描述】:

我有一个使用 mysql 作为数据库的 Rails 应用程序,我正在尝试对其进行 docker 化,因此我最终可以使用 docker-machine 部署它。当我第一次运行docker-compose up 时,它会正确初始化并为数据库播种,就像它应该做的那样。但是,在我关闭它后,我第二次运行docker-compose up,它失败并出现以下错误,因为种子内容已经存在:

web_1     | ActiveRecord::RecordNotUnique: Mysql2::Error: Duplicate entry 'antun@example.com' for key 'index_users_on_email'

在我的 docker-compose.yml 文件中,我在 web 服务下执行以下操作:

command: /bin/sh -c "bin/wait-for db:3306 -- rm -f /home/ubuntu/MY_APP/tmp/pids/server.pid && bundle exec rake db:create db:migrate db:seed && rails server puma -p 80"

我正在使用 ! db/seeds.rb 中的方法方法,因为我知道这被认为是最佳实践:

u = User.new(
  {email: "antun@example.com", encrypted_password: "XXXXX", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, first_name: "Antun", last_name: "LAST_NAME", provider: "facebook", uid: "12345", username: "antun"}
) 
u.save!(validate: false)

我知道我可以跳过 !在u.save!() 但正如我所说,我知道在种子文件中使用它是一种最佳实践,因此它会失败。 我的问题是:仅在使用 docker-compose 首次运行时创建和播种数据库的正确、最佳实践方法是什么?一旦它上线,我想确保应用程序的后续更新(可能包括新数据类型的迁移/其他种子)运行顺畅,不会删除数据库中的数据。

这是完整的 docker-compose.yml 文件:

docker-compose.yml

    version: '3.1'
    services:
      db:
        image: mysql:5.6
        command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci --init-connect='SET NAMES UTF8;' --innodb-flush-log-at-trx-commit=0
        environment:
          MYSQL_ROOT_PASSWORD: XXXXX
          MYSQL_DATABASE: XXXXX
          MYSQL_USER: XXXXX
          MYSQL_PASSWORD: XXXXX
      web:
        build: .
        command: /bin/sh -c "bin/wait-for db:3306 -- rm -f /home/ubuntu/MY_APP/tmp/pids/server.pid && bundle exec rake db:create db:migrate db:seed && rails server puma -p 80"
        volumes: 
          - $PWD:/MY_APP
        ports:
          - "80:80"
        links:
          - "db:database" 
        env_file:
          - .env.production
        depends_on:
          - db
      worker:
        build: .
        command: /bin/sh -c "bundle exec bin/delayed_job -n 1 --log-dir=/home/ubuntu/MY_APP/shared/log/delayed_job.log --pool='notifications-poller:1' --pool='broadcast,default,elasticsearch,firebase:2' restart && bundle exec shoryuken --logfile '/home/ubuntu/MY_APP/shared/log/shoryuken.log' --config '/home/ubuntu/MY_APP/config/shoryuken_staging.yml' -R"
        links:
          - "db:database"
        volumes:
          - $PWD:/MY_APP
          - '/home/ubuntu/MY_APP/node_modules'
        env_file:
          - .env.production
        depends_on:
          - db

【问题讨论】:

  • 我绝对想维护数据。我是 Docker 新手,所以我正在寻找使用 Rails 播种/创建数据库的正确方法。我正在关注 docker-compose.yml 文件中包含 bundle exec rake db:create db:migrate 的指南。我只是将db:seed 添加到那个地方。您是否暗示我应该将所有这些从 docker-compose.yml 文件中移出,并可能移到 dockerfile 中?或者有没有办法在 docker-compose.yml 中放一些东西,所以它只在第一次运行?
  • 我感受到了你的痛苦,Docker 很难进入 IMO,有时对我来说似乎不值得。无论如何,这可能会对您有所帮助docs.docker.com/compose/rails
  • 在该文档中,他们提出的方法似乎不是自动创建数据库,而是让 用户 通过运行docker-compose run web rake db:create 手动创建它.真的是这样吗?对我来说,这似乎非常不像 Docker,因为它需要用户知道要运行哪些命令才能进行设置和部署。
  • 无论如何我都不是 docker 专家,但我就是这样做的。这里讨论了其他选项stackoverflow.com/questions/36407477/…

标签: ruby-on-rails docker docker-compose


【解决方案1】:

改用ActiveRecord::Relation#find_or_create_by

User.find_or_create_by(email: "antun@example.com", encrypted_password: "XXXXX", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, first_name: "Antun", last_name: "LAST_NAME", provider: "facebook", uid: "12345", username: "antun")

回答您的评论;恐怕存储库已经无人维护,但您可以使用我刚刚为此制作的branch

如果您看到更改,您可以:

SeedDump.dump(ModelName, method: :find_or_create_by)
# "ModelName.find_or_create_by([\n  {name: \"<name>\", status: nil},\n...)\n"

回答您的上一条评论和您的问题:

在 docker 中播种 Rails 应用程序以便可以重复启动的正确方法是什么

我不知道是不是正确,但很简单;当您使用 MySQL 时,只需使用它提供的工具。您可以从任何环境中转储和导入数据,这样可以保持数据的完整性,这样可能会更快,更不容易出错。

【讨论】:

  • 这可能会起作用,但我正在使用 seed_dump gem (github.com/rroblak/seed_dump) 来生成种子文件,它会根据我在开发时手动执行的一些初始设置自动生成它们。我当然可以修改它们,但是这有点破坏了使用种子转储的好处。
  • 我非常感谢这里的输入,我认为您的方法将在种子时间解决错误。然而,我在问题中从 Eyeslandic 的 cmets 构建的图片以及更多挖掘是:我应该直接在命令 docker-compose.yml` 中运行 rake db:create db:migrate db:seed
  • 嗯,这是真的@antun。您通常所做的只是在您可能产生的更改之后使用 Rails 任务迁移您的数据库。为了处理生产数据库中的数据,您可以仅通过许多 DBMS 提供的命令行将数据转储并导入到您的开发环境中。我看不出使用这个库有什么意义,当让 dbs 存储许多信息时,它比你的 DBMS 可能提供的选项要慢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
相关资源
最近更新 更多