Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I manage binary dependencies for my gems in production?

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

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.

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?

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

like image 563
nfm Avatar asked May 27 '11 02:05

nfm


People also ask

What do I do with a Gemfile?

Your gemfile is a list of all gems that you want to include in the project. It is used with bundler (also a gem) to install, update, remove and otherwise manage your used gems. These gems belong to development environment and the test environment since they are for testing the application.

Why bundle install is installing gems in vendor bundle?

In deployment, isolation is a more important default. In addition, the user deploying the application may not have permission to install gems to the system, or the web server may not have permission to read them. As a result, bundle install --deployment installs gems to the vendor/bundle directory in the application.

What is RubyGems How does it work?

The RubyGems software allows you to easily download, install, and use ruby software packages on your system. The software package is called a “gem” which contains a packaged Ruby application or library. Gems can be used to extend or modify functionality in Ruby applications.

What is dependencies in Ruby?

Dependencies can be downloaded when your function is deployed, or packaged locally alongside your function. Each function must provide a Gemfile that specifies the functions_framework gem, along with any additional gems needed by the function. Gemfile must be in the same directory as the app.


2 Answers

From my experience same issue with you where my servers are difference platforms (OpenSuSe, CentOS, and 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

  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 
like image 94
Jirapong Avatar answered Oct 22 '22 10:10

Jirapong


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.

like image 39
nathanvda Avatar answered Oct 22 '22 10:10

nathanvda