[備忘録] Docker上の Ubuntu 18.04 に rbenv を導入する


# はじめに

2021年6月だったと思うが、
突然 rbenv でエラーが発生して動かないという問題があり調査をした.[^1]

このとき物理ホストを汚すわけにはいかないので、
Docker 上の Ubuntu 18.04 に rbenv を導入してデバッグをした.

通常、**Docker 上に rbenv をインストールするような面倒なことはしないはず** [^2]
なので、参考記録として書き出しておく.

今回は rbenv を使って「2.7.3」「3.0.1」の 2つを導入する.

なお、Dockerfile での「rbenv install バージョン」に導入したいバージョンを書けば
異なるバージョンも導入できるはずである.


# 参考サイト

|URL|
|:--|
|https://ccbaxy.xyz/blog/2020/02/06/docker3/|
|https://github.com/rbenv/ruby-build/wiki|
|https://takatoshiono.hatenablog.com/entry/2015/01/09/012040|
|https://github.com/rbenv/ruby-build/issues/1211|

　

# 手順

## 1. Dockerfile を作成する

```dockerfile
# 参考にしたサイト
# [Ref.1] https://ccbaxy.xyz/blog/2020/02/06/docker3/
# [Ref.2] https://github.com/rbenv/ruby-build/wiki
# [Ref.3] https://takatoshiono.hatenablog.com/entry/2015/01/09/012040
# [Ref.4] https://github.com/rbenv/ruby-build/issues/1211
# [Ref.5] https://takeshit.info/how_to_develop_rails_only_with_docker/
FROM ubuntu:18.04

# パッケージリスト更新
RUN apt-get update

# (1) rubyビルドに必要なパッケージを取得. 上記 [Ref.2] のサイトの手順を参考にした.
#     ただし Ubuntu 18.04 の場合は libgdbm5 を指定すること (libgdbm6 だとインストール失敗する)
RUN apt-get install -y autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev \
                        zlib1g-dev libncurses5-dev libffi-dev libgdbm5 libgdbm-dev libdb-dev

# (2) rubyビルドに必要なパッケージを取得:rubyの古いものはssl1.0を使いたいので別途インストール
# 上記 (1)で libssl-dev と libssl1.0-dev を両方書くことはできるが、競合したので別で実行する。
RUN apt-get -y install libssl1.0-dev

# rbenvの導入
RUN apt-get install -y git curl

RUN cd ~/ && \
    git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

# 環境変数の登録
ENV PATH /root/.rbenv/shims:/root/.rbenv/bin:/usr/local/sbin::$PATH

# ruby-build の導入と ruby のインストール
RUN cd ~/ && \
    git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build && \
    rbenv install -l && \
    LDFLAGS=-L/root/.rbenv/versions/2.3.0/lib CPPFLAGS=-I/root/.rbenv/versions/2.3.0/include rbenv install 2.3.0 && \
    rbenv install 2.7.3 && \
    rbenv install 3.0.1 && \
    rbenv versions

# 作業場 == 永続化ポイントとする [Ref.5]
WORKDIR /rb/src

# コンテナが終了しないように bash を実行しておく [Ref.5]
# が、次の docker-compose の command で処理を書いたので意味が無いはず
CMD ["/bin/bash"]
```


## 2. docker-compose.yml を作成する

```yaml
version: '3'

services:
    rb:
        container_name: rbr001
        build:
            context: .
            dockerfile: Dockerfile
        volumes:
            - ./rb/src:/rb/src
        tty: true 
        command: bash -c "rbenv global 3.0.1 && bash"

```

　

## 3. 永続化ポイントを作成する

```bash
$ mkdir rb/src -p
```

　

## 4. ビルド&起動する

```bash
$ docker-compose build --no-cache
$ docker-compose up -d
```

　

# 動作確認

## 1. Ruby バージョンが 3.0.1 であることを確認する

```bash
$ docker-compose exec app bash -c 'ruby -v'
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-linux]

$ docker-compose exec app bash -c '/usr/bin/env ruby -v'
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-linux]
```
　

## 2. 「Hello Ruby」コードを作成して実行する

物理ホスト側で hello.rb を作成する

### ./rb/src/hello.rb

```ruby
#!/usr/bin/env ruby

puts "Hello Ruby"
```


　

## 3. 実行する

```bash
$ docker-compose exec rb bash -c '/rb/src/hello.rb '
Hello Ruby
```


# トラブルとその対策

## 「rbenv: ruby: command not found」と表示される場合

```bash
$ docker exec -it ruby001 ruby version
rbenv: ruby: command not found
 
The `ruby' command exists in these Ruby versions:
  2.3.0
  2.7.3
  3.0.1
```

**対策** rbenv global を使ってバージョンを選択すること

```bash
# 3.0.1 を使用するように指定する
$ docker exec -it ruby001 bash -c 'rbenv global 3.0.1'
 
# 3.0.1 が選択されたことを確認する
$ docker exec -it ruby001 bash -c 'rbenv versions'
  2.3.0
  2.7.3
* 3.0.1 (set by /root/.rbenv/version)
```



[^1]: $PATH に設定されていたパスが登録されなくなったことが原因だった気がする

[^2]: 素直に所望の Rubyバージョンの Docker イメージを使うため