ヒミツのgemを利用するアプリをHerokuにデプロイする2025年版
Herokuなどのプラットフォームでは、依存ライブラリを公開されているレポジトリからダウンロードして利用するのが一般的ですが、お仕事のRubyアプリには社内用のヒミツのgemに依存するものもあります。社内用のgemをrubygems.orgに公開するには社内の手続きに手間がかかり、rubygems.orgの名前空間を汚してしまうこともあり、できれば公開せずに済ませたいところです。
試行錯誤したところ、ヒミツのgemを手元のワーキングコピーから保管した後にGemfile
を編集して保管先のパスを参照するようにすることで、ヒミツのgemを公開せずHerokuで利用できることがわかりました。この記事では、Rubyはバージョン3.4.1を利用します。HerokuのRuby Buildpackで起動されるBundlerのバージョンは2.6.2でした。
ヒミツのgemをつくる
例示用のgemを作っておきます。
$ bundle gem hello
$ cd hello
$ vi lib/hello.rb
$ vi hello.gemspec
lib/hello.rb
は下記のようにしました。
# frozen_string_literal: true
require_relative "hello/version"
module Hello
class Error < StandardError; end
def self.greet
"Hello, World!"
end
end
bundle gem hello
コマンドで生成されるhello.gemspec
ではファイルの列挙にgit
コマンドを利用しますが、Herokuのビルドプロセスでは利用できないので、あらかじめspec.files
にファイルを列挙しておきます。
# frozen_string_literal: true
require_relative "lib/hello/version"
Gem::Specification.new do |spec|
spec.name = "hello"
spec.version = Hello::VERSION
spec.authors = ["zunda"]
spec.summary = "Hello, World!"
spec.license = "MIT"
spec.files = %w[LICENSE.txt README.md Rakefile hello.gemspec lib/hello.rb lib/hello/version.rb sig/hello.rbs]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
ローカルなワーキングコピーにコミットしておきます。
$ git add hello.gemspec lib/hello.rb
$ git commit -m 'First local release'
ヒミツのgemをつかうアプリをつくる
例示用のアプリを作ります。ヒミツのgemと同じ階層のディレクトリを利用します。
$ git init
$ rbenv local 3.4.1
$ bundle init
$ bundle add rackup puma sinatra
$ bundle add hello --git=`dirname $(pwd)`/hello
$ vi Gemfile
$ vi web.rb
$ bundle install
Gemfile
は下記のようにしました。
# frozen_string_literal: true
source "https://rubygems.org"
ruby file: '.ruby-version'
gem "rackup", "~> 2.2"
gem "puma", "~> 6.6"
gem "sinatra", "~> 4.1"
gem "hello", "~> 0.1.0", :git => "/home/zunda/c/src/local/hello"
web.rb
で/
へのGET
リクエストにヒミツのgemから挨拶を返します。
require 'sinatra'
require 'hello'
get '/' do
Hello.greet + "\n"
end
Herokuにデプロイする (失敗編)
Herokuにデプロイするため、Procfile
を用意します。
web: bundle exec ruby web.rb -p $PORT
ローカルなワーキングコピーはpushされないので、デプロイは失敗します。
$ git add .
$ git commit -m 'First commit'
$ heroku create
$ git push heroku master
:
remote: fatal: repository '/home/zunda/c/src/local/hello' does not exist
remote:
remote: !
remote: ! Failed to install gems via Bundler.
remote: !
:
Herokuにデプロイできるようにする
必要なgemをvendor/cache
に保管します。--all
オプションでヒミツのgemも保管されます。
$ bundle package --all
$ ls -d vendor/cache/hello*
vendor/cache/hello-cf18744fd01d
Gemfile
を編集してヒミツのgemをvendor/cache
以下から参照するようにします。
# frozen_string_literal: true
source "https://rubygems.org"
ruby file: '.ruby-version'
gem "rackup", "~> 2.2"
gem "puma", "~> 6.6"
gem "sinatra", "~> 4.1"
#gem "hello", "~> 0.1.0", :git => "/home/zunda/c/src/local/hello"
gem "hello", "~> 0.1.0", path: "vendor/cache/hello-cf18744fd01d/"
Gemfile.lock
の内容をGemfile
に合わせて更新します。
$ bundle install
これで、ヒミツのgemも含めてHerokuアプリとしてデプロイできるようになりました。
$ git add Gemfile Gemfile.lock vendor/cache
$ git commit -m 'Use path'
$ git push heroku master
Discussion