Dockerを使って任意のrubyバージョンのrpmを作成する

May 11, 2014 - docker

CentOSを使ってて不便なのがruby2系のインストール。

rbenvやruby-buildを使うかソースからインストールするのですが、この場合、環境を構築するたびにビルドすることになり時間もかかるし大変面倒です。

なのでDockerを使ってクリーンな環境でRubyの最新rpmをビルドしてみました。

Dockerを使えばビルド環境がすぐに立ち上げられるので、rpmビルドに必要なパッケージを確認したりするのに最適です。

今回のソースはgithubにpushしてあります。

環境

  • ゲストOS:Vagrantで起動したUbuntu-14.04
  • コンテナ:centos:6.4

ファイルの配置

以下ファイルを同一ディレクトリに入れておきます。

  • Vagrantfile
  • provision.sh
  • Dockerfile
  • rubybuild.sh
  • ruby-2.0.0-p481.spec

手順

  1. ゲストOSの起動(Vagrant)
  2. ゲストOSにsshログイン
  3. Dockerコンテナのビルド
  4. Dockerコンテナ内でrpmビルド

1. ゲストOSの起動

Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/trusty64"

  config.vm.synced_folder ".", "/vagrant"

  config.vm.provision "shell", path: 'provision.sh'

  # お好みで
  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--memory", "2048", "--cpus", "2", "--ioapic", "on"]
  end
end

provision.sh

sudo apt-get update
sudo apt-get install -y language-pack-ja

# Docker
sudo apt-get install -y docker.io
sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker

2. ゲストOSにsshログイン

$ vagrant up
$ vagrant ssh
$ cd /vagrant

3. Dockerコンテナのビルド

ビルド用specファイルを用意して、シェルスクリプトでビルドします。

すると、コンテナにマウントしたボリュームにビルド済みのrpmファイルがコピーされます。

ビルド用specシェルスクリプト

環境変数RUBY_VERSIONに”2.0.0-p481”や”2.0.0-p451”を設定すれば任意のバージョンをビルドします。

※デフォルトの2.0.0-p481以外はそれ用のspecファイルが必要になります。

rubybuild.sh

#!/bin/env bash
WORKDIR=/opt/rpmbuild

RUBY_VER=${RUBY_VER:-"2.0.0-p481"}
RUBY_MAJOUR_VER=$(echo $RUBY_VER|cut -d"-" -f1)
RUBY_MINOR_VER=$(echo $RUBY_VER|cut -d"-" -f2)
if [ -z "$RUBY_MINOR_VER" ]; then
  RUBY_TARBALL="ruby-$RUBY_MAJOUR_VER.tar.gz"
else
  RUBY_TARBALL="ruby-$RUBY_MAJOUR_VER-$RUBY_MINOR_VER.tar.gz"
fi
RUBY_REMOTE_FILE="http://cache.ruby-lang.org/pub/ruby/${RUBY_MAJOUR_VER:0:3}/$RUBY_TARBALL"

mkdir -p $WORKDIR/rpm/{BUILD,SRPMS,SPECS,SOURCES,RPMS}
echo "%_topdir $WORKDIR/rpm" > $WORKDIR/.rpmmacros
if [ ! -f $WORKDIR/rpm/SOURCES/$RUBY_TARBALL ]; then
  wget $RUBY_REMOTE_FILE -O $WORKDIR/rpm/SOURCES/$RUBY_TARBALL
fi
cp $WORKDIR/ruby-${RUBY_VER}.spec $WORKDIR/rpm/SPECS/ruby.spec
rpmbuild -bb $WORKDIR/rpm/SPECS/ruby.spec

cp $WORKDIR/rpm/RPMS/x86_64/* /shared/

4. Dockerコンテナ内でrpmビルド

Dockerfile

FROM centos:6.4

# setup
RUN yum update -y
RUN yum install -y rpm-build gcc

# epel
RUN rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
RUN rpm -ihv http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

# ruby-depends
RUN yum install —enablerepo=epel -y libyaml-devel
RUN yum install -y byacc readline-devel ncourses-devel tcl-devel openssl-devel gdbm-devel db4-devel

# build rpm
WORKDIR /opt/rpmbuild
ADD rubybuild.sh /opt/rpmbuild/rubybuild.sh
ADD ruby-2.0.0-p481.spec /opt/rpmbuild/ruby-2.0.0-p481.spec

コンテナ起動してrpmをビルド

コンテナを起動する際に、カレントディレクトリをマウントしておきます。

--rmオプションでrpm作成完了したらコンテナは破棄します

$ sudo docker build -t <USERNAME>/rpmbuild .
$ sudo docker run --rm -v $PWD:/shared:rw -it <CONTAINER_ID> /bin/sh ./rubybuild.sh

成功すれば、ゲストOSのカレントディレクトリにrpmができてます。

$ ls *.rpm
ruby-2.0.0p481-2.el6.x86_64.rpm

これで、rpmコマンド一発で最新のrubyをインストールできます。

rubyインストール済みコンテナを作るなら、Dockerfileに以下のように書けばruby実行環境のできあがりです。

FROM centos:6.4

# EPEL
RUN rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
RUN rpm -ihv http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

# Install ruby rpm
ADD ruby-2.0.0p481-2.el6.x86_64.rpm ruby-2.0.0p481-2.el6.x86_64.rpm
RUN yum install -y --enablerepo=epel libyaml-devel
RUN rpm -ihv ruby-2.0.0p481-2.el6.x86_64.rpm