LoginSignup
3
1

More than 3 years have passed since last update.

privateなgemサーバの構築とgem作成から利用まで

Last updated at Posted at 2019-11-01

privateなgemサーバをローカルでDockerで起動し、オリジナルのgem作成からそれを利用するまでの流れを試しましたので、手順を残しておきます。この記事の一番下に載せたリンクを参考にしました。

3段階の手順です。手順ごとにディレクトリを作ります。

  • Dockerイメージ作成とgemサーバ起動 (Gem in a Box)
  • gemを作成してgemサーバに登録 (gem inabox)
  • そのgemを利用

Docker、Ruby、gem、bundleなどはすでに入っているものとします。

Dockerイメージ作成とgemサーバ起動

Gem in a Boxというプライベートなgemサーバを作るツールを使います。

$ mkdir docker
$ cd docker

このディレクトリに以下の3ファイルを作成します。

Dockerイメージ作成のためのファイル

Dockerfile
FROM ruby:2.6.4

RUN mkdir /geminabox-data
COPY . /geminabox-app

WORKDIR /geminabox-app
RUN bundle install

Dockerイメージの中にGem in a Boxをインストールするためのファイル

Gemfile
source "https://rubygems.org"

gem "geminabox"

Gem in a Boxの設定ファイル

config.ru
require "rubygems"
require "geminabox"

Geminabox.data = "/geminabox-data"

use Rack::Session::Pool, expire_after: 1000 # sec
use Rack::Protection

run Geminabox::Server

この3ファイルのあるディレクトリでDockerイメージを作成します。

$ ls
config.ru  Dockerfile  Gemfile
$ docker build -t geminabox .

以下のコマンドでDockerイメージを起動すると、Gem in a Boxが動きます。ターミナルにはそのログが吐き出されます。

$ docker run -it --rm -p 9292:9292  geminabox /usr/local/bundle/bin/rackup --port 9292 --host 0.0.0.0

Gem in a Boxで動く流れをつかむための一時的な環境です。このコマンドでDockerを起動してgemを登録しても、Dockerを止めたらgemは消えてしまいます。

このGem in a Boxを動かしたまま、次以降の手順に入りますので別のターミナルからもとのディレクトリ(dockerディレクトリの上の階層)に入ります。

gemを作成してgemサーバに登録

gemを作成

以下のコマンドでgem作成のテンプレートを作ることができます。パラメータはgemの名前です。単純にhelloworldだとすでに誰かがRubyGemsで公開しているgemと名前が被ってしまって試行錯誤するには混乱しやすいので、被らなそうなものにして試します。

$ bundle gem helloworld-suzuki
$ cd helloworld-suzuki

helloworld-suzuki.gemspecというファイルが生成されているのでそれを編集します。TODOという記述が含まれているといけないらしいので、その個所を以下のように書き換えます。

helloworld-suzuki.gemspec
  spec.summary       = %q{Hello, world!}
  spec.description   = %q{Hello, world!}
  spec.homepage      = "http://www.example.com/"

spec.metadataの設定にもTODOが含まれますが、それらの記述4行をまるごと消してしまいました。

パッケージのソースの本体となるファイルにサンプルのメソッドを書きます。以下のようにしました。

lib/helloworld/suzuki.rb
require "helloworld/suzuki/version"

module Helloworld
  module Suzuki
    class Error < StandardError; end
    def self.say
      print "Hello, World!\n"
    end
  end
end

以下のコマンドを実行するとパッケージが生成されます。

$ rake build

pkg/helloworld-suzuki-0.1.0.gemにファイルが生成されます。

gemサーバに登録

できあがったパッケージファイルをさきほどのDockerで動いているGem in a Boxに登録したいと思います。ブラウザでhttp://localhost:9292/にアクセスしてもいいらしいのですが、ここではコマンドでやってみます。

gem inaboxというコマンドでパッケージファイルをGem in a Boxに登録できるのですが、このコマンドは普通のgemをインストールしただけの環境にはなくて、geminaboxをインストールしないといけないようです。なので、ローカルにインストールします。

$ gem install geminabox

繰り返しですが、あくまでgem inaboxコマンドを使えるようにするためのインストールで、Gem in a Box自体はさきほどのDockerの中でGemfileをもとにインストールした環境ですでに動作中です。

次にgem inaboxコマンドでパッケージファイルをGem in a Boxに登録します。

$ gem inabox --host http://localhost:9292/  pkg/helloworld-suzuki-0.1.0.gem

これを実行すると、Dockerを実行しているターミナルにアクセスログが出力されます。

次の手順に入るためにいったん上の階層に戻ります。

$ cd ..

そのgemを利用

別のディレクトリを作成します。

$ mkdir sample
$ cd sample

先ほど作成したgemを利用するためのGemfileを作成します。

Gemfile
source "https://rubygems.org"

gem "helloworld-suzuki"

helloworld-suzukiという名前のgemは一般のRubyGemsにはないはずですので、このままですとエラーになるはずです。

$ bundle install
Fetching gem metadata from https://rubygems.org/.
Fetching gem metadata from https://rubygems.org/.
Could not find gem 'helloworld-suzuki' in any of the gem sources listed in your Gemfile.

はい、エラーになりました。

$ gem sources -a http://localhost:9292/

これを実行するとgemの取得元サーバが追加されます。以下のコマンドで設定状況を確認できます。

$ gem sources
*** CURRENT SOURCES ***

https://rubygems.org/
http://localhost:9292/

~/.gemrcというファイルにこの設定が書かれています。

このファイルにではなく、今回のsampleプロジェクトのみに適用したい場合はGemfileに以下のように書きます。

Gemfile
source "https://rubygems.org"

source "http://localhost:9292" do
  gem "helloworld-suzuki"
end

またはこのように書いてもよいです。

Gemfile
source "https://rubygems.org"

gem "helloworld-suzuki", :source => "http://localhost:9292"

helloworld-suzukiというgemだけhttp://localhost:9292からダウンロードすることを指定する設定です。複数のgemをhttp://localhost:9292からダウンロードする場合には1つ目のブロックでの書き方が便利です。

これをもとに再度bundle installを実行します。

$ bundle install
Fetching gem metadata from http://localhost:9292/..
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using bundler 2.0.2
Fetching helloworld-suzuki 0.1.0
Installing helloworld-suzuki 0.1.0
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

ちなみに以下のように書いてもとりあえずは動きますが、Gemfileに書いたすべてのgemをいちいち2つのサーバに見に行ってしまいます。

Gemfile
source "https://rubygems.org"
source "http://localhost:9292"

gem "helloworld-suzuki"

この環境でRubyを動かしてみます。

$ bundle exec ruby -rhelloworld/suzuki -e 'Helloworld::Suzuki.say'
Hello, World!

無事動きました。

参考

DockerでGem in a Boxを起動するのは次の記事を参考にしました。
Gem in a BoxでプライベートなRubyGemsをDockerで簡単に構築する - YOMON8.NET

今回の私の記事ではDockerでその場で動かしましたがちゃんとdaemon化するには次の記事が参考になります。
privateなgemサーバー構築のお話 - Qiita

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1