問題点
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