問題点
Dockerfile に普通に RUN コマンドを書くと、/bin/sh で実行されてしまう。
これを /bin/bash で実行させようとして、/etc/passwd をいじってみたり /bin/sh を /bin/bash にリンクしてみたりしたが、ディストリビューションによってはうまくいかないケースもあった。
具体的には、 Alpine Linux をベースにしてDockerfileで anyenv のインストールをさせようとしたところ、 anyenv は /bin/sh だと動かないのであった。
解決法
~
# Install anyenv
# --------------
RUN git clone https://github.com/riywo/anyenv ~/.anyenv \
&& echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bashrc \
&& echo 'eval "$(anyenv init -)"' >> ~/.bashrc
ENV PATH /root/.anyenv/bin:$PATH
RUN exec $SHELL -l
# ↑ここでシェルがbashに切り替わる気がするが、切り替わらない。sourceでもダメ。
# Install Ruby by rbenv
# ---------------------
RUN anyenv install rbenv \
&& exec $SHELL -l \
&& rbenv install 2.2.0 \
&& rbenv global 2.2.0 \
&& rbenv rehash
# ↑anyenvがうまく実行できてない。
~
# Install anyenv
# --------------
RUN git clone https://github.com/riywo/anyenv ~/.anyenv \
&& echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bashrc \
&& echo 'eval "$(anyenv init -)"' >> ~/.bashrc
ENV PATH /root/.anyenv/bin:$PATH
# Install Ruby by rbenv
# ---------------------
RUN ["/bin/bash", "-c", " \
source ~/.bashrc \
&& anyenv install rbenv \
&& source ~/.bashrc \
&& rbenv install 2.2.0 \
&& rbenv global 2.2.0 \
&& rbenv rehash \
"]
というわけで上記のように、
RUN ["/bin/bash", "-c", "(bashで実行させたいコマンド)"]
とやるのが正解っぽい。
但し、サブシェル(コマンドが終わると環境が戻る)のようなので、毎 RUN ごとに source して .bashrc を読み込んでやる必要がある。
...スマートじゃない!
docker build コマンドのオプションから、ビルドに使用するシェルが指定できればいいのに・・。
確認したバージョン
- docker 1.9.1
- Alpine Linux 3.3