我应该如何在生产中管理我的宝石的二进制依赖项?

时间:2022-05-09 21:02:17

Bundler does an awesome job of making sure all the right gems are installed when I deploy.

Bundler在部署时确保安装了所有正确的gem,这是一项非常棒的工作。

However, some gems depend on binaries (eg Paperclip depends on ImageMagick, PDFKit depends on wkhtmltopdf) that may or may not be installed on the system being deployed to.

但是,有些宝石依赖于二进制文件(例如Paperclip依赖于ImageMagick,PDFKit依赖于wkhtmltopdf),这些宝石可能会或可能不会安装在正在部署的系统上。

I've been bitten by this twice recently and need to figure out the best way to prevent it from happening again.

我最近被这两次咬过,需要找出防止它再次发生的最佳方法。

Is there a good way to ensure these external binaries and libraries are installed? Does bundler have any support for it? Should I just modify my capistrano deploy script? Should I include the binaries in my repository and make sure the gems look for them in the right place?

有没有一种好方法可以确保安装这些外部二进制文件和库?捆绑商是否有任何支持?我应该修改我的capistrano部署脚本吗?我应该在我的存储库中包含二进制文件并确保宝石在正确的位置查找它们吗?

I can think of a few ways to approach this problem but want to know what you think works best, and why.

我可以想办法解决这个问题,但想知道你认为哪种方法效果最好,以及为什么。

3 个解决方案

#1


6  

Not sure if this is applicable for you, but we use puppet for this purpose. Another (similar) alternative is chef.

不确定这是否适合您,但我们为此目的使用木偶。另一个(类似的)替代品是厨师。

So what we do is 'script' the setup of our machines, but independently of our capistrano recipes. It is not completely ideal, but it also allows a cleaner seperation: our systems guys/devops use puppet, and the rails developers use capistrano.

所以我们所做的就是“编写”我们机器的设置,但独立于我们的capistrano配方。它并不完全理想,但它也允许更清晰的分离:我们的系统人员/ devops使用puppet,rails开发人员使用capistrano。

#2


12  

From my experience same issue with you where my servers are difference platforms (OpenSuSe, CentOS, and OSX).

根据我的经验,我的服务器是差异平台(OpenSuSe,CentOS和OSX)。

I put script to install binary (yum, zypper, apt-get, etc) on capistrano script, use ruby's system() method to verify the command work. in your example of ImageMagick. It something like this

我把脚本安装在capistrano脚本上的二进制文件(yum,zypper,apt-get等),使用ruby的system()方法来验证命令的工作。在你的ImageMagick示例中。它是这样的

  desc "ImageMagick from source"
  task :ImageMagick => :prepare do
    d_url = "ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz"
    file = "ImageMagick.tar.gz"
    sh("#{os_installer} install -y ghostscript-devel ghostscript-library libpng-devel libjpg-devel")
    Dir.chdir('downloads') do
      sh("wget -O #{file} #{d_url}")

      raise "ERROR: Unable to download ImageMagick" unless File.exist?(file)

      sh("tar -xzvf #{file}")
      unzip_dir = Dir.glob("ImageMagick-*").first

      Dir.chdir(unzip_dir) do
        sh("./configure --prefix=/usr --with-x=no --disable-static --with-modules --without-perl --without-magick-plus-plus --with-quantum-depth=8")
        sh("make")
        sh("make install")
        sh("ldconfig")
      end 

      raise "Unable to find ImageMagick" unless system("convert --version")
    end 
  end 

#3


2  

With Puppet, you could say something like this in your manifest:

使用Puppet,您可以在清单中说出类似的内容:

package{'foo': ensure => installed, } # native (like RPM) package providing one of your binaries, installed from a repo

#then explicitly declare the dependency like this. This will be installed using 'gem install' from the default place used by gem
package{'my_gem':
  ensure  => installed,
  require => Package['foo'],
  provider => 'gem',
}

#1


6  

Not sure if this is applicable for you, but we use puppet for this purpose. Another (similar) alternative is chef.

不确定这是否适合您,但我们为此目的使用木偶。另一个(类似的)替代品是厨师。

So what we do is 'script' the setup of our machines, but independently of our capistrano recipes. It is not completely ideal, but it also allows a cleaner seperation: our systems guys/devops use puppet, and the rails developers use capistrano.

所以我们所做的就是“编写”我们机器的设置,但独立于我们的capistrano配方。它并不完全理想,但它也允许更清晰的分离:我们的系统人员/ devops使用puppet,rails开发人员使用capistrano。

#2


12  

From my experience same issue with you where my servers are difference platforms (OpenSuSe, CentOS, and OSX).

根据我的经验,我的服务器是差异平台(OpenSuSe,CentOS和OSX)。

I put script to install binary (yum, zypper, apt-get, etc) on capistrano script, use ruby's system() method to verify the command work. in your example of ImageMagick. It something like this

我把脚本安装在capistrano脚本上的二进制文件(yum,zypper,apt-get等),使用ruby的system()方法来验证命令的工作。在你的ImageMagick示例中。它是这样的

  desc "ImageMagick from source"
  task :ImageMagick => :prepare do
    d_url = "ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz"
    file = "ImageMagick.tar.gz"
    sh("#{os_installer} install -y ghostscript-devel ghostscript-library libpng-devel libjpg-devel")
    Dir.chdir('downloads') do
      sh("wget -O #{file} #{d_url}")

      raise "ERROR: Unable to download ImageMagick" unless File.exist?(file)

      sh("tar -xzvf #{file}")
      unzip_dir = Dir.glob("ImageMagick-*").first

      Dir.chdir(unzip_dir) do
        sh("./configure --prefix=/usr --with-x=no --disable-static --with-modules --without-perl --without-magick-plus-plus --with-quantum-depth=8")
        sh("make")
        sh("make install")
        sh("ldconfig")
      end 

      raise "Unable to find ImageMagick" unless system("convert --version")
    end 
  end 

#3


2  

With Puppet, you could say something like this in your manifest:

使用Puppet,您可以在清单中说出类似的内容:

package{'foo': ensure => installed, } # native (like RPM) package providing one of your binaries, installed from a repo

#then explicitly declare the dependency like this. This will be installed using 'gem install' from the default place used by gem
package{'my_gem':
  ensure  => installed,
  require => Package['foo'],
  provider => 'gem',
}