Help us understand the problem. What is going on with this article?

Anaconda の公式 Docker イメージがアクティベーションしないと使えなくなった件

Anaconda の公式 Docker イメージ をベースにしてイメージをビルドするときにハマった話。

[追記]

現在では PATH が戻っているようですね・・・。
https://github.com/ContinuumIO/docker-images/pull/148

イメージのビルドが失敗するようになった

今まで Anaconda の公式イメージをベースにしてデータ分析用のイメージを作ったりしていたのだけど、Anaconda のバージョンを 2019.07 に上げたところ condapip コマンドが使えなくなった。

Dockerfile
FROM continuumio/anaconda3:2019.07

RUN conda install -y cudatoolkit
ビルド結果
$ docker build .
/bin/sh: 1: conda: not found

ちなみに bash でログインした場合は問題なく使える。(Anaconda イメージのデフォルト起動コマンドは bash)

$ docker run --rm -it continuumio/anaconda3:2019.07
(base) # which conda
/opt/conda/bin/conda

これはログインシェルとして bash を起動した場合は conda activate が実行されるように設定されているため。

$ docker run --rm -it continuumio/anaconda3:2019.07 cat /root/.bashrc
(略)
. /opt/conda/etc/profile.d/conda.sh
conda activate base

しかし Dockerfile のビルド時は /bin/sh -c (debian の場合 /bin/shdash のエイリアス) で実行されるため自動で conda activate が実行されず、 condapip コマンドは使えない。

$ docker run --rm -it continuumio/anaconda3:2019.07 sh -c 'conda info -e'
sh: 1: conda: not found

ここで気になるのは「 2019.07 以前は使えていたじゃん」という点だが、これは何故かというと、以前は Anaconda イメージの Dockerfile に ENV PATH /opt/conda/bin:$PATH がベタ書きされていたので conda activate しなくても /opt/conda/bin 配下にある condapip コマンドにパスが通っていたため。 2019.07 ではこれが削除されてしまった。

Anaconda として正しい挙動は何か

Anaconda 公式的には「明示的に conda activate する」が正しく、アクティベートせずに使えていた以前の方が誤りらしい。1

個人的な意見としては、Docker コンテナ内でさらに conda 仮想環境を切り替える用途なんてそうそうないだろうし(そういう使い方をしたければ Docker コンテナを複数作ればよい)、最初から base がアクティベートされた状態にしれくれてもいいのになー、と思う。(ダメ元で Pull Request 投げてみたけどやはりダメだった)

ただまぁ、以前の状態は「sh -c のときもアクティベートされていた」わけではなく「たまたま /opt/conda/bin にパスが通っていたので使えていただけ (アクティベートされていない)」だったので、そのまま使い続けるのがお行儀が悪いというのは理解できる。

対処方法

おそらく最もお行儀の良いのは「 condapip など Anaconda 環境下にあるコマンドを使う場合は毎回アクティベートするコマンドを差し込む」方法だろう。

Dockerfile
FROM continuumio/anaconda3:2019.07

RUN . /opt/conda/bin/activate \
  && conda install -y cudatoolkit

ADD . /app
WORKDIR /app

RUN . /opt/conda/bin/activate \
  && pip install -r requirements.txt

しかしこの方法では RUN が終了するたびにリセットされてしまう為 RUN のたびにアクティベートする必要があってとても面倒臭い。

もう一つの方法としては「ビルド時の RUN の実行コマンドを bash -l -c に変更する」が考えられる。 -l オプションをつけることでログインシェルとして扱われるので毎回 ~/.bashrc が読み込まれる。

Dockerfile
FROM continuumio/anaconda3:2019.07

SHELL ["/bin/bash", "-l", "-c"]

RUN conda install -y cudatoolkit

ADD . /app
WORKDIR /app

RUN pip install -r requirements.txt

これなら RUN のたびに ~/.bashrc を読み込んで自動でアクティベートしてくれるので、毎回アクティベートをするコマンドを差し込む必要がなくなり、Dockerfile がスッキリする。

この方法は多少行儀は悪いものの「/opt/conda/binPATH に追加する (アクティベートせずに無理やり使う)」方法よりかはだいぶマシだと思う。

懸念点としては 「 sh -c から bash -l -c に変えたことで何か悪影響が出る可能性」だが、今のところ悪影響が出るケースが思いつかない。
何か思い当たる人はコメントしてもらえるとありがたい。

ビルドしたイメージからコンテナを起動するとき

ビルドしたイメージからコンテナを起動するときもまたアクティベートする必要がある。

Dockerfile
RUN echo 'exec "$@"' > /entrypoint.sh
ENTRYPOINT ["/bin/bash", "-l", "/entrypoint.sh"]

今のところ、こんな感じで ENTRYPOINT を用意して bashrc を読み込んでもらう方法くらいしか思いつかない・・・。

hoto17296
ゆとりデータ分析マン
https://hoto.me/
churadata
沖縄で データ分析 / 機械学習 / Deep Learning をやっている会社です
https://churadata.okinawa/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした