Alpineベースのimageにruby2.2.3を入れる

本当はalpine-rubyをベースにするべきなんだろうけど諸事情でJava系のベースにする必要があったので、rbenvを自力で入れて構築することにしました。

出来上がったDockerfileはこちら。

```Dockerfile
FROM openjdk:8-jdk-alpine

RUN apk update && \
    apk upgrade && \
    apk add --update --no-cache \
    bash \
    vim \
    curl \
    tzdata \
    openssl-dev=1.0.2u-r0

RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN echo "http://dl-cdn.alpinelinux.org/alpine/v3.8/main" >> /etc/apk/repositories
RUN apk update && \
    apk upgrade && \
    apk add --update --no-cache --virtual=.build-dependencies \
    build-base \
    git \
    gcc \
    readline-dev \
    zlib-dev \
    libffi-dev

ENV PATH /usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH
ENV RBENV_ROOT /usr/local/rbenv
ENV CONFIGURE_OPTS "--disable-install-doc"

RUN git clone https://github.com/sstephenson/rbenv.git ${RBENV_ROOT} && \
    git clone https://github.com/sstephenson/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
    ${RBENV_ROOT}/plugins/ruby-build/install.sh
RUN echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> /etc/profile.d/rbenv.sh && \
    echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh

RUN rbenv install 2.2.3 && \
    rbenv global 2.2.3

COPY Gemfile .
COPY Gemfile.lock .

RUN gem install -N bundler -v 1.16.2
RUN bundle install -j4 && \
    rm -rf /usr/local/bundle/cache/*.gem

RUN apk del .build-dependencies
```
大きな障害はは以下のようにopensslの1.0を取得することでした。

# v3.8から1.0系のopensslを取得する

素直にapk add opensslでライブラリを入れるとrbenv install時に以下のようなエラーが発生する。

```
BUILD FAILED (Alpine Linux 3.9.4 using ruby-build 20200115-8-g73b926b)

Inspect or clean up the working tree at /tmp/ruby-build.20200123165940.26.gjbJCo
Results logged to /tmp/ruby-build.20200123165940.26.log

Last 10 log lines:
                              power_assert-0.2.2.gem
                              minitest-5.4.3.gem
installing rdoc:              /usr/local/rbenv/versions/2.2.3/share/ri/2.2.0/system
installing capi-docs:         /usr/local/rbenv/versions/2.2.3/share/doc/ruby
The Ruby openssl extension was not compiled.
ERROR: Ruby install aborted due to missing extensions
Configure options used:
  --prefix=/usr/local/rbenv/versions/2.2.3
  LDFLAGS=-L/usr/local/rbenv/versions/2.2.3/lib 
  CPPFLAGS=-I/usr/local/rbenv/versions/2.2.3/include 
```
エラーの原因としては、ruby2.4以下の場合はopenssl1.1系に対応していないため、openssl1.0を入れる必要があるからでした。
[rbenv/ruby-build] (https://github.com/rbenv/ruby-build/wiki#openssl-usrincludeopensslasn1_mach102-error-error-this-file-is-obsolete-please-update-your-software)
> The openssl extension of Ruby version before 2.4 is not compatible with OpenSSL 1.1.x.

ubuntuベースのimageで構築するなら[こちら](https://qiita.com/gano/items/ea6560c287324148c68d)の記事で言及されているように有志が開発したパッチを当てれば動きますが、alpineの場合は自力で1.0系を入れる必要があります。

現在openjdk:8-jdk-alpineではデフォルトでv3.9のリポジトリを参照しているが、v3.9ではopensslは1.1系の提供になっています。
こちらで調べると1.0系の取得には１つ前のv3.8のリポジトリから取得が必要のようです。
https://pkgs.alpinelinux.org/packages?name=openssl&branch=v3.8&repo=main

そこでapkから取得する前に参照先にv3.8のリポジトリを追加して上げる必要があります。

```dockerfile
RUN echo "http://dl-cdn.alpinelinux.org/alpine/v3.8/main" >> /etc/apk/repositories
```
追加後に`openssl-dev=1.0.2u-r0`とバージョンを指定することで1.0系のopensslを取得することができます。

また当初はgem install時に`The Ruby openssl extension was not compiled. Missing the OpenSSL lib?`エラーが発生していたが、修正前のDockerfikeで`libssl1.0`を入れていたことが原因でした。
おそらくssl系のライブラリ同士でバッティングしていたっぽい？

rbenvの前はruby-installを使用して軽量化を図っていましたが、上と同じOpenSSLのエラーがどうしても解消できなかったので諦めることに…
ruby-installで上手く行けば多分もう少し軽くできそう。

```dockerfile
RUN wget -O - https://github.com/postmodern/ruby-install/archive/v0.7.0.tar.gz | tar xzvf - && \
    ( cd ruby-install-0.7.0 && \
      make install ) && \
    rm -rf ruby-install-*
RUN ruby-install --system --cleanup ruby 2.2.3
```

# その他細かいポイントなど
docker軽量化系の記事では散々言及されているようなことですが、軽くまとめると
- ビルドに必要のないパッケージは残したくないので.build-dependenciesでまとめて最後の行で一括で削除しています。
- `ENV CONFIGURE_OPTS "--disable-install-doc"`を指定することで不要なドキュメントをインストールしないようにしています
- bundle install時に`rm -rf /usr/local/bundle/cache/*.gem`でgemのキャッシュを消すようにしています

今どき2.2.3を使うことはあまりないと思いますが、備忘録として残しておこうと思います。