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

【画像で説明】DockerでAnaconda環境をつくり、コンテナの中でVSCodeを使う

やること

  1. 公式のAnacondaイメージをベースに自前のイメージをつくります。
  2. コンテナを立ち上げ、Jupyter Labを起動します。
  3. ブラウザから、コンテナ内で立ち上げたJupyter Labを操作します。
  4. VSCodeでコンテナに接続します。
  5. VSCodeからもコンテナ内部を編集できることを確認します。

なにがうれしいの??

  • Anacondaをホストマシンにインストールすることのリスク回避(Homebrewやpipとの衝突)
  • 複数人で開発環境を共有できる

環境

  • MacOS X 10.14.5 (Mojave)
  • VSCode 1.35.1
  • Docker 18.09.2

Dockerイメージをつくる

Dockerfile

Anaconda公式イメージをベースにします。
https://hub.docker.com/r/continuumio/anaconda3

# ベースイメージ名:タグ名
FROM continuumio/anaconda3:2019.03

# pipをアップグレードし必要なパッケージをインストール
RUN pip install --upgrade pip && \
    pip install autopep8 && \
    pip install Keras && \
    pip install tensorflow 

# コンテナ側のルート直下にworkdir/(任意)という名前の作業ディレクトリを作り移動する
WORKDIR /workdir

# コンテナ側のリッスンポート番号
EXPOSE 8888

# ENTRYPOINT命令はコンテナ起動時に実行するコマンドを指定(基本docker runの時に上書きしないもの)
# "jupyter-lab" => jupyter-lab立ち上げコマンド
# "--ip=0.0.0.0" => ip制限なし
# "--port=8888" => EXPOSE命令で書いたポート番号と合わせる
# ”--no-browser” => ブラウザを立ち上げない。コンテナ側にはブラウザがないので 。
# "--allow-root" => rootユーザーの許可。セキュリティ的には良くないので、自分で使うときだけ。
# "--NotebookApp.token=''" => トークンなしで起動許可。これもセキュリティ的には良くない。
ENTRYPOINT ["jupyter-lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.token=''"]

# CMD命令はコンテナ起動時に実行するコマンドを指定(docker runの時に上書きする可能性のあるもの)
# "--notebook-dir=/workdir" => Jupyter Labのルートとなるディレクトリを指定
CMD ["--notebook-dir=/workdir"]

イメージビルド

Dockerfileが置いてあるディレクトリで以下を実行

docker build -t ANATA_NO_IMAGE_NAME .

-t

ビルドしたイメージに名前(:タグ名)をつけるオプションです。

. (最後のドット)

ビルドコンテキストの指定。
Dockerfileのあるディレクトリを指定します。
ここでは.なのでカレントディレクトリを指定しています。

コンテナ起動

① docker runコマンドで起動する場合

docker run -it \
-p 8888:8888 \
--rm \
--name ANATA_NO_CONTAINER_NAME(任意) \ 
--mount type=bind,src=`pwd`,dst=/workdir  \
ANATA_NO_IMAGE_NAME(上でビルドしたもの)

このコマンド何してるの??

docker run

docker pulldocker createdocker start を1発で行うやつ。
イメージがホストマシン上になければDocker Hubからpullしてきて、コンテナつくって、コンテナを起動します。

-it

-i-tをまとめて書いてるものです。

  • -i or --interactive
    => ホスト側のシェルからコンテナ内を操作できるようにする。

  • -t or --tty
    => 仮想ttyの割当て。キーバインドを使用したり、色を出力したりシェル操作を便利に行うために指定。

こちらが非常にわかりやすいです。
https://teratail.com/questions/121780
https://teratail.com/questions/19477
https://teratail.com/questions/100044

-p 8888:8888

ホスト側のポート番号:コンテナ側のポート番号 をひも付けます。
ローカルのブラウザからlocalhost:8888でコンテナ内で立ち上げたjupyterをひらけるように。

--rm

コンテナを停止したときに自動で削除もしてくれます。

--name ANATA_NO_CONTAINER_NAME

任意のコンテナ名をつける。

--mount type=bind,src=`pwd`,dst=/workdir

ホスト側のディレクトリとコンテナ側のディレクトリを同期させる。

  • type=bind => マウントタイプにbindを指定(他にvolume,tmpfsの指定が可能)
  • src=`pwd` => ホスト側のディレクトリにカレントディレクトリを指定(任意のディレクトリでOK)
  • dst=/workdir => コンテナ側のディレクトリにルート直下のworkdir/を指定(任意のディレクトリでOK)

-v でも --mountと同じことができます。

  • -v => ホスト側に存在しないディレクトリをマウントしようとすると新規作成
  • --mount => ホスト側に存在しないディレクトリをマウントしようとするとエラー

誤って空のディレクトリをマウントしてしまう事故を防げるので --mount が推奨されている。

ANATA_NO_IMAGE_NAME

任意のDockerイメージを指定

② docker-composeで起動する場合

上記docker run 〜コマンドをコード化したようなものです。

docker-compose.yml

docker-compose.yml
version: '3' # docker-composeファイルの書式バージョン。最新の’3’を指定(2019/6/27現在)
services:
  dev: # 任意の名前(ディレクトリ名 + dev がコンテナ名となります)
    build:
      context: .
      dockerfile: Dockerfile
    image: ANATA_NO_IMAGE_NAME
    ports:
    - "8888:8888"
    volumes:
    - .:/workdir

コンテナ起動

docker-compose.ymlが置いてあるディレクトリで以下を実行

docker-compose up

Jupyter Labを開く

ブラウザのアドレスバーに localhost:8888 を入力しEnter。
=> Jupyter Labが開きます。マウントさせたディレクトリと同じものが入っていればOK。

同期されるか確認

ローカルのディレクトリで新しくファイルを作ってみます。

touch test.ipynb

再読込ボタンでJupyter Labのエクスプローラを更新して、test.ipynb が追加されていれば成功です。

コンテナ停止

docker runで起動した場合

docker stop ANATA_NO_CONTAINER_NAME

docker-compose up で起動した場合

docker-compose stop

コンテナ削除

docker runで起動した場合

docker rm ANATA_NO_CONTAINER_NAME

docker-compose up で起動した場合

docker-compose down

コンテナの中でもVSCodeつかいたい人

:raised_hand:

拡張機能のインストール

表示 > コマンドパレット > 拡張と打つ > ビュー:拡張機能を表示する
スクリーンショット 2019-06-24 10.34.41.png

サイドバーの入力欄にremote と打つ > Remote - Containersを選択 > インストール

スクリーンショット 2019-06-28 11.26.11.png

これが出てくればOK
スクリーンショット 2019-06-28 11.32.01.png

もう一回コンテナ起動

  • コンテナ名 => test_container
  • 使用イメージ => anaconda_test_image

として起動してみます。

docker run -it -p 8888:8888 --name test_container \ 
--mount type=bind,src=`pwd`,dst=/workdir anaconda_test_image

コンテナに接続

左下のボタンを押して、
Remote - Containers: Attach to Running Container…を選択

スクリーンショット 2019-06-28 12.26.18.png

起動中のコンテナ一覧が出てくるので、接続したいコンテナを選択します。

スクリーンショット 2019-06-28 13.00.03.png

新しいウィンドウが開きます。

左下のボタンがAttached Container ~となります。
スクリーンショット 2019-06-28 13.02.39.png

以下の手順で、マウント先(コンテナ側)のディレクトリを選択します。

スクリーンショット 2019-06-28 13.03.45.png

マウント元(ホスト側)のディレクトリと同じ内容が表示されればOK。

スクリーンショット 2019-06-28 13.55.58.png

Jupyterで新規ファイル作成してみます。
Untitled.ipynbがVSCode側にも即反映されるのが確認できるかと思います。

スクリーンショット 2019-06-28 13.51.52.png

コンテナ側に拡張機能インストール

ローカルでVSCodeにインストールされている拡張機能が、コンテナ側には入っていません。
必要に応じでインストールします。

スクリーンショット 2019-06-28 14.13.40.png

最後に

ここまで読んで頂きありがとうございました。
VSCodeでJupyterのように実行結果を表示させる方法も書いたので、もしよろしければ。
=> 【画像で説明】VSCodeをJupyter化する

参照

ありがとうございました!

komiya_____
■ twitter.com/rescued_cat ■ connpass: daremoku.connpass.com ■ Kaggle 銅 x 1 ■
data-learning-guild
データ分析人材のキャリア構築を支援するためのオンラインコミュニティです
https://data-learning.com/guild
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