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.
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.
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With