🐳

Dockerで構築する機械学習環境【2024年版】

2024/03/11に公開

Dockerを使った機械学習環境の構築方法

株式会社松尾研究所で働いているからあげ(@karaage0703)です。松尾研究所では、機械学習(ここでは、予測モデル、画像認識からLLMまで幅広く扱います)を使う多数のプロジェクトが走っています。プロジェクトの特性は多種多様なので、環境構築方法は様々なのですが、松尾研究所では、環境構築方法の1つとしてDockerを推奨していています。今回はDockerを使った機械学習環境の構築方法を紹介します。

松尾研究所の特にインターン生を想定した記事にはなりますが、他の組織、個人の方にも参考になる部分があるかと思いWebに広く公開させていただきます。

なぜDockerで機械学習環境を構築するのか?

具体的な手法に入る前に、まずはDockerで機械学習環境を構築する理由から説明したいと思います。説明が不要な方はここはスキップしてもOKです。

そのために、Dockerとは何かという説明が必要となります。Dockerは一言でいうと仮想環境のプラットフォームです。ただ、実態は非常に奥深く、詳細な説明をすると本記事の主題である環境構築までたどり着けないため、Docker自体の説明は、さくらインターネットさんの非常に分かりやすい記事にゆずります。まずはこちらを読んでいただけましたら幸いです。

これ以降は、Docker、Dockerコンテナ、Dockerイメージの概念は理解しているという前提で記事を書かさせていただきます。

Dockerを使うメリット

仮想環境に関しては、他にも多数の手法があるのですが、ここでは、簡単に私が実感しているDockerを機械学習の環境として使うメリットを挙げてみます。

  • 今ある環境を壊さずに使い捨てのテスト環境を一瞬で構築・破壊できる
  • 異なる環境(OS, CPUアーキテクチャ)でもサーバー上のマシンでも同じ環境を手軽に構築できる
  • GPUを動かす環境を手軽に構築できる
  • 様々な環境に対応したDockerイメージが豊富にあり、自分でカスタムも可能

特に最新の機械学習は、バージョンの依存関係が厳しく、様々なバージョンの組み合わせの環境を準備する必要があります。そんなときにDockerを使えば、手軽に環境を使い捨て感覚で構築したり切り替えたりできるので非常に便利です。

また、Docker上でGPUを動かせるのもメリットです。CUDA、cuDNN、PyTorchのバージョンの組み合わせに悩んだことある人は多いと思いますが、この組み合わせもDockerイメージを切り替えることで手軽に試行錯誤することが可能です。

ローカルでもサーバー上でも、同じ環境を手軽に構築できるのもメリットです。機械学習のプロジェクトでは、まず手元で少ないデータで試行してから、サーバーで大規模な計算をするということがありますが、Dockerで環境を構築すれば、手元のマシンで構築した環境を、サーバ上で手軽に構築することが可能です。

異なるOSでも同じ環境を構築することも可能です。ただし、CPUアーキテクチャの違いの影響で同じイメージを使うことはできないので、Apple SiliconのMacだとうまくイメージをビルドできないといったケースがあることには注意してください。

Dockerが苦手なケース

逆にDockerが苦手なケースを最初に紹介しておきます。特に初心者の場合は、自分の使いたい用途にDockerが適しているかは注意してください。

  • GUIを使うケース
  • 特殊なデバイスをPCに接続して使用するケース
  • 性能(速度)を追求したいケース

上記がDockerを使うと全くできないというわけではないのですが、初心者の方は、このような特性があることを知っておいた方が良いかと思います。

Dockerのセットアップ

いよいよDockerのセットアップに入っていきます。本記事の対象のOSは、Mac/Windows/Linuxとします。インストール方法自体はOSごとに異なりますが、インストール後のコマンドはどのOSでも基本的に共通となります。

MacへのDockerインストール方法

Docker Desktopを使うのが主流となりますが、Docker Desktopは企業で使用する場合は基本的に有料となります(詳細な条件は公式の料金プランを参照ください)ので注意してください。

Macで無料で使えるDockerのクライアントとしてRancher Desktopがあります。特にApple Silicon MacへのRancher Desktopのインストールに関してはクラスメソッド様の記事が参考になりました。

また、機械学習関係はメモリを多く使うことが多いので、Dockerでのメモリの割当は下図のようにMaxにしておくのがおすすめです。

WindowsへのDockerインストール方法

Docker Desktop/Rancher Desktopを使う方法とWSL2上にインストールする方法があります。

WSL2上であればLinuxにインストールする公式のDockerと同じ要領でインストールできるのでおすすめです。この記事ではWSL2上にインストールすることを想定しています。WSL2とDockerのインストールに関してはこちらの記事を参考にしてみてください。

機械学習環境は、メモリ不足が問題なることがあるので、メモリ関係はこちらの記事を参考に設定しておくことをおすすめします。

LinuxへのDockerインストール方法

LinuxにDockerをインストールするケースは、松尾研究所では多くはクラウド上になると思いますので、その場合情シスにお願いすることになります。申請フォームにて依頼しましょう。Dockerのインストールに関しても情シスに連絡してください。

自分でPCを準備して環境構築するという方は、こちらの記事を参考にしてください。

Dockerの基本的な使用方法

ここからは、Dockerの基本操作を説明していきます。各OSで操作は共通です。本記事では、最初のとっかかりとして、機械学習での用途に絞り、最低限必要なコマンドとその説明、ユースケースに応じた使い方の紹介をしたいと思います。

イメージと合わせて理解したい人はDocker ハンズオン / docker-hands-onの資料もおすすめです。

また、より詳細について知りたい人は、実践 Docker - ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本というZennの無料書籍に網羅的に情報がまとまっていますので参考ににしてみてください。

Dockerの動作確認

Dockerの動作確認です。hello-worldというイメージを動かしてみましょう。

$ docker run hello-world
新旧のdockerコマンドに関して(docker run vs docker container run)

docker runの代わりにdocker container runでも同じことができます。

実はdockerコマンドは2017年のv1.13以降からコマンド体系が変更されています。公式では分かりやすさから新体系のコマンドを推奨していますが、古いコマンド体系にも互換性があります(公式リファレンスにもエイリアスという形で記載されています)。

本記事では簡便性と多くの書籍やWebサイトで使われていることから、古い体系のコマンドを使用します。新旧のコマンド比較はこちらの記事が参考になりました

以下のように表示されたらOKです。

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
478afc919002: Pull complete 
Digest: sha256:d000bc569937abbe195e20322a0bde6b2922d805332fd6d8a68b19f524b7d21d
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

(以下省略)
Cannot connect to the Docker daemonエラーがでるとき

Dockerコマンド実行したとき、以下のようにエラーがでてしまうケースがよくあります。

docker: Cannot connect to the Docker daemon at unix:///Users/th/.rd/docker.sock. Is the docker daemon running?.
See 'docker run --help'.

原因としては、Dockerが立ち上がってないことが多いので、起動しているか確認しましょう。以下のコマンドでバージョン確認してみましょう。

$ docker -v
Docker version 24.0.2-rd, build e63f5fa

以下で動作しているコンテナも確認すると確実です。

$ docker ps

これで動かない場合は、Dockerを再起動するとなおることが多いです。Macの場合は、Rancher Desktopを再起動しましょう。LinuxやWindowsの場合は、以下コマンドで再起動ができます。

$ sudo service docker stop
$ sudo service docker start

Dockerイメージをダウンロード

Dockerコンテナを起動したとき、初回は以下のようなDockerイメージがないという表示が出て、その後ダウンロードが始まったかと思います。

Unable to find image 'hello-world:latest' locally

Dockerコンテナが起動する際、指定したイメージがない場合は、以下のような流れで、WebからDockerイメージをダウンロードしてコンテナの起動までをしてくれます。

  • Dockerイメージをダウンロード(Docker Pull)
  • ダウンロードしたDockerイメージからコンテナを起動させる

理解を深めるため、1つずつ実行してみましょう。まずは最初のDockerイメージのダウンロードです。ダウンロードするDockerイメージですが、Web上に多数あります。例えば、以下の様にubuntu:22.04のDockerイメージをpullすると、一瞬でUbuntu(Linux OS)の環境が手に入ります。

:22.04の部分はtagです。指定しないと、最新のtagである:latestがダウンロードされます。タグを指定しないと、ダウンロードする内容がタイミングによって変わってしまうため、安定した動作のためにはtagを指定するのが推奨です。

$ docker pull ubuntu:22.04

イメージを探したいときは、docker searchコマンドで探すことができます。以下はubuntuで検索する例です。ライブラリ名、フレームワーク名等で検索すると多くのイメージが出てきます。

$ docker search 'ubuntu'

ダウンロードしたイメージを確認したいときは以下です。

$ docker images

以下のようにダウンロードしたイメージが表示されます。

REPOSITORY   TAG        IMAGE ID       CREATED         SIZE
ubuntu       22.04      a50ab9f16797   2 weeks ago     69.2MB

コンテナを起動する

次に以下コマンドで、先ほどダウンロードしたUbuntuのDockerイメージを用いてコンテナと呼ばれるDockerでの仮想環境を立ち上げます。以下はコマンドの例です。

$ docker run -it --rm --name test ubuntu:22.04

いくつかオプションがついているので少し長いコマンドとなります。オプションの意味は以下です。

-it:ターミナルを使うためのオプション
--rm:コンテナから抜けるとコンテナを自動で削除する
--name: コンテナの名前を指定する

オプションの詳細や、他のコマンド等に関しては、Dockerの公式リファレンスを参照しましょう。

コンテナを起動すると、以下の様な画面が出て、自動的にターミナルにログインします。

root@e50b9fce6812:/#

試しに好きなLinuxコマンドを打ち込みましょう。例えばlsコマンドだと結果は以下です。

root@e50b9fce6812:/# ls
bin  boot  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

ここで重要なのは、この環境はあくまでDockerコンテナ上に構築されている点です。なので、この上で何をしても再度コンテナを立ち上げ直すと、また元の環境に戻る点です。つまり、好きなだけ環境を変更、壊すことができます。

例えばtouchコマンドでtest.txtというファイルを作成してファイルを確認してみましょう。

root@e50b9fce6812:/# touch test.txt
root@e50b9fce6812:/# ls
bin  boot  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  test.txt  tmp  usr  var

シェルを終了します。exitを実行するかCtrl+dで終了できます。再度dockerを起動して、ファイルを確認するとtest.txtが消えていることが分かります。

root@89744fadd986:/# ls
bin  boot  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

このように、Dockerを使うと使い捨ての環境をいくらでも構築、破棄することができます。

Dockerコマンドのオプションについて

コマンドのオプションを何故つけるのか分からない方もいるかと思います。そのためにも、オプションを指定せずに実行したらどうなるか試してみましょう。以下のコマンドを実行します。

$ docker run ubuntu:22.04

この場合コンテナは何もしないで終了し、停止したコンテナが残り続け、実行するたびに、新しい名前のコンテナが再現なく増えていくこととなります。docker runを2回以上実行してからdocker psコマンドでコンテナを確認してみましょう。

$ docker ps -a
CONTAINER ID   IMAGE                        COMMAND                   CREATED              STATUS                          PORTS     NAMES
7d6fa7db2a64   ubuntu:22.04                 "/bin/bash"               2 seconds ago        Exited (0) 1 second ago                   busy_bouman
83f2623eeb7f   ubuntu:22.04                 "/bin/bash"               About a minute ago   Exited (0) About a minute ago             hungry_pasteur

実行するたびに新しい名前NAMESのコンテナが増えていきます。

コンテナはdocker rmコマンドで削除できます。一気に削除したい場合は、以下のようなコマンドを使うと便利です。

$ docker rm $(docker ps -aq)

Dockerの便利な使い方

ここからはユースケースごとに、Dockerの便利な使い方を紹介していきます。

ホストとコンテナでファイル共有

先ほど書いた通り、環境を使い捨てできるのは便利ですが、コンテナ上で開発したソフトや結果も消えてしまうのは不便です。また、ホスト側で開発したプログラムをDockerコンテナ上で走らせることもできません。

ボリュームをマウントすることでそのような問題を解決できます。マウントするためには、以下のようなコマンドでDockerコンテナを起動します。

$ docker run -it -v $PWD:/share --rm --name test ubuntu:22.04

ポイントは-vというオプションです。-v <host directory>:<container directory> と指定することで、ホスト側とコンテナ側のディレクトリを共有できます。

$PWDは現在自分がいるディレクトリ(カレントディレクトリ)を意味するので、上記コマンドを実行すると、コマンドを実行したディレクトリのファイルが、コンテナの/shareというディレクトリにマウントされます。コンテナ側で# ls /share とすればカレントディレクトリのファイルが見えると思います。逆にコンテナ上で /shareディレクトリにファイルを入れると、ホスト側にも共有されます。

マウントされたファイルは、コンテナを終了しても残り続けます。このようにマウントを使うことで、コンテナで上で好きなファイルを編集することができます。

docker `-v`オプションと`--mount`オプション

Dockerの-vオプションの代わりに--mountオプションもあります。公式では、分かりやすさから--mountオプションを使うことが推奨されています。

ただ、今だ-vオプションは多く使われています。本記事でも-vオプションでの説明としました。-vオプションと-mountオプションの違いを知りたい人は以下記事を参照ください。

Dockerの -v や --volume オプションはわかりづらいから、 --mount を使おう

Dockerイメージの作成方法

必要な環境(インストール済のライブラリ、設定)にピッタリのDockerイメージが無い場合、Dockerコンテナ上でライブラリをインストールしたり、設定を変更することになります。ただ、前述したようにコンテナは一度再起動するとまた環境構築する前の状態に戻ってしまいます。

そんな場合は、自分の好きなDockerイメージを作成することになります。Dockerのイメージは、コンテナでの変更をdocker container commitコマンドで作成することもできますが、この記事では1からDockerfileを使ってイメージを作成する方法を紹介します。

まずは、以下のようなDockerfileというファイル名のテキストファイルを好きなエディタで作成して下さい。

FROM ubuntu:22.04

RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y git python3 python3-pip

次にDockerfileがあるディレクトリで以下のコマンドを実行すれば、Dockerfileを元にしたubunt-testという名前のイメージができあがります(コマンドの最後にコロン.があるので忘れないようにしましょう)。

$ docker build -t ubuntu-test .

エラーがなければ、Dockerイメージが生成されます。以下のdocker imagesコマンドを実行すると、ダウンロードしたdockerイメージとならんでubuntu-testが表示されます。

$ docker images

Dockerfileを使う良さは、作成したイメージがどのような環境なのか後で一目で分かることです。またFromでベースとなるイメージを指定することで、すでにあるイメージをベースに簡単に新しいイメージをつくれます。自分がやりたいことに必要な環境に近いDockerfileを探して、それをベースに作成するのが良いでしょう。

Dockerfileの書き方は、非常に奥が深いのでこの記事では詳細は解説しません。公式記事のDockerfileを書くベストプラクティスを参考にすると良いでしょう。

Dockerイメージを人に渡す

確実に同じ環境を共有するため、Dockerイメージをそのまま渡したい場合があるかと思います(例えばお客様に確実に同じ環境を提供したい場合)。

そんなときはイメージのセーブ(docker save)とロード(docker load)を使いましょう。

先ほどビルドして作成したubuntu-testDockerイメージをセーブ(保存)したいときは以下コマンドを使います。

$ docker save ubuntu-test | gzip > test.tar.gz

圧縮されたDockerイメージtest.tar.gzが生成されます。

次にこのイメージを違う環境でロード(読み込み)しましょう。違う環境が無い場合は、docker rmi ubuntu-testコマンドでイメージを消しておきましょう。

以下のコマンドでDockerイメージを読み込めます。

$ docker load < test.tar.gz

以下コマンドでubuntu-testイメージが読み込めていることが確認できます。

$ docker images

これを覚えておけば、セーブしたファイルをお客様に渡してロードしてもらうといったことが可能です。

VS CodeエディタでDockerを使う

VS CodeエディタとDockerを組み合わせると便利に開発できます。特にDev Containers拡張を使うとDockerコンテナ、VS Codeエディタ拡張機能の設定をdevcontainer.jsonにまとめて書けるのでチームで開発環境を揃えたいときに役立ちます。

私がZennで無料で公開しているVS Codeエディタ入門という電子書籍のVS CodeエディタでDockerを使うという章に設定方法や使い方をまとめていますので、興味がある方は参考にしてみてください。

Docker Composeで更に便利に

Dockerを使いこなし、複数のコンテナを切り替えたい、長いDockerコマンドのオプションをまとめたいといった要望が出てきたら、Docker Composeというアプリケーションを使うと解決できるかもしれません。本記事ではDocker Composeの詳細の説明は割愛します。以下の公式リファレンスを参照ください。

https://docs.docker.jp/compose/toc.html

また、より高度なソフトウェアとしてKubernetesがありますが、より大きなシステムの構築に必要なものとなるので、機械学習の環境構築にフォーカスした本記事では対象外としています。

DockerコンテナとDockerイメージを全部削除する

一旦コンテナもイメージも全部削除してやりなおしたいときは、以下コマンドを実行しましょう。当然ですが、削除して問題ないか確認した上で実施しましょう。

$ docker rm -f $(docker ps -a -q)
$ docker rmi $(docker images -q)

便利な使い方を紹介しているサイト

この記事では機械学習でGUIやGPUを多用するような例まで紹介できませんでしたが、参考になりそうなより応用的な記事をいくつか紹介したいと思います。

元松尾研究室の@namahogeさんの記事です。
サーバーで DeepLearning (+GUI) なDocker環境構築

DockerはGUIが苦手と書きましたが、GUIをWebブラウザ経由で手軽に使うための方法です。
ROS/ROS2のGUIをWebブラウザ経由でお手軽に試せるDockerfileを公開しました

この記事のLinuxセットアップ部分で書いた私の記事です。GPUを使うケースに関してマシンのセットアップから記載しています。
DockerでのディープラーニングGPU学習環境構築方法

GUIと日本語環境が使えるお手軽Docker環境です。AIエージェントを使うときなどに便利です。
https://zenn.dev/mkj/articles/292a70b4f4e5e8

まとめ

Dockerを用いて機械学習環境を構築する方法に関してまとめてみました。久しぶりにDockerに関してコマンドや使い方を確認してみましたが推奨のコマンド体系が変わっていたり、便利な使い方を発見できたりと色々学びがありました。

今回は比較的基本的な使い方に絞って説明しましたが、今後別記事でより高度な使い方も紹介できたらと考えています。

GitHubでDockerfiledevcontainer.jsonを管理したり、Docker Composeを使いこなすとチーム開発での環境構築が手軽かつ安定したものになるかと思いますので、Dockerを使ってない人は、是非本記事の内容を試して、Dockerを使った安定した機械学習環境構築にチャレンジしてみてください。

本記事が、機械学習環境構築で悩んでいる方の一助になれば幸いです。

参考情報

実践 Docker - ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本

Dockerと和解せよ!

1時間でさわって学ぶDocker

2024年版のDockerfileの考え方&書き方

入門Docker

変更履歴

  • 2024/04/16 便利な使い方を紹介しているサイトにリンクを追記しました
  • 2024/03/11 参考になるサイトを追記しました
松尾研究所テックブログ

Discussion