なぜDockerを使うのか
- IaCの文脈ではデファクトスタンダードなDockerを使うことが多い
- 以下のようなケースが多くあるので使うことを推奨(やるやらないは別として知っておくに越したことはない)
- 「検証環境で動いたコードが商用環境の端末で動かそうとしたら動かなくなった」といった環境依存関係をなくしたい
- gitからcloneしたが動かなかったコードをくようにしたものをチームで共有したい
概要と確認コマンド
- 以下がわかりやすい
Docker初学者がやるべきこと3選 - Qiita
手順
以下の3ステップでDockerを動かせる状態にする
- Dockerfileを作る
- Docker imageをbuildする
- Docker containerをrunする
(Docker初学者がやるべきこと3選 - Qiitaより拝借)
Dockerfileを配置するディレクトリ構成例
- Dockerを導入する上でのファイル配置は以下を参考にすると良い(機械学習のプロジェクトを想定)
-
サンプル:
my_ml_project/ │ ├── data/ # データセットや中間データを格納 │ ├── raw/ │ └── processed/ │ ├── model/ # トレーニング済みのモデルやモデルのチェックポイントを格納 │ ├── notebooks/ # Jupyter ノートブック │ ├── src/ # ソースコード │ ├── __init__.py │ ├── data_preparation/ │ ├── model_definition/ │ └── training_scripts/ │ ├── tests/ # テストコード │ ├── Dockerfile # Dockerfile │ ├── requirements.txt # 必要なPythonパッケージのリスト │ └── README.md # プロジェクトの説明やセットアップ方法など
-
Dockerfileの書き方
- Dockerfileの作り方は2通りある
-
自作する:色々と自分でいじれてコピペして使う時に便利
-
サンプル:
# 1. ベースイメージ(以下追加する元となるイメージ)を指定(イメージ:バージョン) FROM ubuntu:20.04 # 2. あとはベースイメージに追加したい内容を記載する # docker imageをbuildする際に自動実行されて、docker runする際にはすでに実行済みの状態となる # RUNで普段ターミナルで打っているコマンドを記載できる RUN apt-get update && apt-get install -y --no-install-recommends \ # 日本語表示で文字化けを防ぐ language-pack-ja-base language-pack-ja \ libglib2.0-0 \ libsm6 \ libxrender1 \ libxext6 \ build-essential \ libssl-dev \ libffi-dev \ python3-dev \ python3 \ python3-pip && \ rm -rf /var/lib/apt/lists/* # 日本語表示で文字化けを防ぐ RUN echo 'export LANG=ja_JP.UTF-8' >> ~/.bashrc RUN echo 'export LANGUAGE="ja_JP:ja"' >> ~/.bashrc # source ~/.bashrc と同じ処理 RUN . ~/.bashrc # pip install RUN pip3 install --upgrade pip setuptools COPY ./requirements.txt /tmp RUN pip3 install -r /tmp/requirements.txt # Required for nvidia-docker v1 RUN echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf && \ echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf # PATHの指定 ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH} ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64 # nvidia-container-runtime ENV NVIDIA_VISIBLE_DEVICES all ENV NVIDIA_DRIVER_CAPABILITIES compute,utility ENV NVIDIA_REQUIRE_CUDA "cuda>=11.0 brand=tesla,driver>=418,driver<419 brand=tesla,driver>=440,driver<441 brand=tesla,driver>=450,driver<451"
-
-
Docker Hubからpullする:cudaのバージョン対応するベースイメージは自作すると大変なのでDocker Hubから探すことが多い
-
Docker buildコマンド
-
何度も使う場合があったり、buildしているdocker imageの実行元コマンドを忘れる場合があるのでシェルスクリプトとしてファイルを作成しておくと良い(シェルスクリプトもgitリポジトリに上がると見栄えが悪いのでREADMEなどでサンプルを書く程度にとどめておき、pushされないように.gitignoreに*.shなどと記載しておくと良い)
-
サンプル:
#!/bin/bash # docker build -t [イメージ名]:[タグ] . docker build -t my_ml_project:latest .
build時のコマンド:
-
[イメージ名]
は作成するDockerイメージの名前 -
[タグ]
はイメージのバージョンやラベルを示すもので、例えばlatest
などを指定することが多い -
.
はDockerfileが存在する現在のディレクトリを指す -
※
-fオプション
を使用する場合-
プロジェクトのディレクトリ内で、複数のDockerfileがある場合(例:
Dockerfile.dev
、Dockerfile.prod
など)、f
オプションを使ってどのDockerfileを使ってビルドするか指定することができる#!/bin/bash # docker build -f [Dockerfileのパス] -t [イメージ名]:[タグ] [ビルドコンテキストのパス] docker build -f path/to/Dockerfile -t my_ml_project:latest .
-
[Dockerfileのパス]
: 使用するDockerfileへのパス。 -
[イメージ名]
: 作成するDockerイメージの名前。 -
[タグ]
: イメージのバージョンやラベル。 -
[ビルドコンテキストのパス]
: Dockerイメージをビルドする際のコンテキスト(通常、Dockerfileがあるディレクトリやその親ディレクトリ)。
-
-
-
作成したイメージは以下のコマンドで確認できる
docker images
-
Docker runコマンド
-
何度も使う場合があったり、runしているdocker containerの実行元コマンドを忘れる場合があるのでシェルスクリプトとしてファイルを作成しておくと良い(シェルスクリプトもgitリポジトリに上がると見栄えが悪いのでREADMEなどでサンプルを書く程度にとどめておき、pushされないように.gitignoreに*.shなどと記載しておくと良い)
-
サンプル:
-
シンプルなバージョン
#!/bin/bash # docker run [オプション] [イメージ名]:[タグ] [コマンド] [コマンドの引数...] docker run \ --user root \ # ユーザを指定 --name sample \ # runして立ち上げるコンテナ名を指定 -it \ # -i -tオプションをまとめて書く書き方 # -iはinteractive(対話型)という意味でコンテナ内で実行するシェルと標準出力をつなぐというオプション(このオプションをつけないとコンテナの中のシェルにコマンドを実行してもらうことができない状態になる) # -tはtty (端末デバイス)という意味でコンテナ内にコンテナ用の疑似的なターミナルを用意するというオプション(このオプションをつけないとコンテナ内のターミナルでユーザー名やカレントディレクトリも出ていないし、タブによる入力補完なども機能しない状態になる) my_ml_project:latest \ # runするコンテナの名前:タグを指定 /bin/bash # こちらのオプションをつけるとコンテナ内でターミナル操作可能(バックグラウンドでスクリプト実行したい場合はつけなくて良い)
-
便利オプションを追加したバージョン
#!/bin/bash # docker run [オプション] [イメージ名]:[タグ] [コマンド] [コマンドの引数...] docker run \ --rm \ # コンテナを停止した際に削除するオプション --p 8080:8080 # ポートを指定(ホストポート:コンテナポート) \ --user root \ # ユーザを指定 --gpus all \ # 使用するGPU群を指定 --name sample \ # runして立ち上げるコンテナ名を指定 -it \ # -i -tオプションをまとめて書く書き方 # -iはinteractive(対話型)という意味でコンテナ内で実行するシェルと標準出力をつなぐというオプション(このオプションをつけないとコンテナの中のシェルにコマンドを実行してもらうことができない状態になる) # -tはtty (端末デバイス)という意味でコンテナ内にコンテナ用の疑似的なターミナルを用意するというオプション(このオプションをつけないとコンテナ内のターミナルでユーザー名やカレントディレクトリも出ていないし、タブによる入力補完なども機能しない状態になる) -v /workspace/:/workspace/ \ # ボリュームマウント(ホストPCとコンテナで共有したいディレクトをフルパスで記載) -w /workspace/src/ \ # コンテナのターミナルを開く際、初期位置となるディレクトリをコンテナの方のフルパスで指定 my_ml_project:latest \ # runするコンテナの名前:タグを指定 /bin/bash # こちらのオプションをつけるとコンテナ内でターミナル操作可能(バックグラウンドでスクリプト実行したい場合はつけなくて良い)
run時のコマンド:
-
[イメージ名]
: 実行したいDockerイメージの名前。 -
[タグ]
: イメージのバージョンやラベル。指定しない場合、デフォルトでlatest
タグが使用されます。 -
[コマンド]
および[コマンドの引数...]
: イメージ内で実行するコマンドとその引数。これを省略すると、DockerfileのCMD
命令で指定されたコマンドが実行されます。
一般的なオプション:
-
-d
: デタッチモード。コンテナをバックグラウンドで実行します。 -
--name [コンテナ名]
: コンテナに名前を付けます。 -
-p [ホストのポート]:[コンテナのポート]
: ポートマッピング。ホストとコンテナのポートをマッピングします。 -
-v [ホストのディレクトリ]:[コンテナのディレクトリ]
: ボリュームマッピング。ホストとコンテナのディレクトリをマッピングします。 -
-e [変数名]=[値]**
: 環境変数をセットします。 -
--rm
: コンテナが停止した後に自動的に削除します。
-
その他
-
その他
- Docker Desktop有償化について:
- Win, MacでDockerを使おうとする場合、Docker Desktopが必要となり、従業員250以上で年間売り上げ1000万ドル以上の組織で商用利用するケースに該当するので有償化する必要があるので注意
- vscodeの拡張機能 remote containerを使いmacからlinuxマシンにリモート接続する場合もおそらくDocker Desktopが必要になる
- しかし以下のケースではDocker DesktopなしにDockerが使用できるので問題ない
- WSL経由でdockerを利用する場合
- linuxマシンでdockerを利用する場合
- Docker Desktop有償化について: