見出し画像

環境構築:Dockerの環境構築×MLモデルの実装(Windows)

1.概要

 下記条件におけるDockerの環境構築を実施して、自作した機械学習モデル(ML)をコンテナで実装するところまで学習します。

  • OS:Windows 64bit(Version指定あり)

  • 対象:「従業員250人以上かつ年間売上10M$以上」の会社内で使用かつ下記理由で有償製品がつかいにくい

    • 予算取り/更新がめちゃくちゃ手間(雑務が多い)

    • (そもそもDockerを使用しないといけない環境があるくせに、)予算権限者が「Dockerとは何か/何故必要か」を理解しておらず説明できない(説明にするにはそれなりの知識が必要なため)

  • PCスペック:それなり(2~3年前)のスペック(コンテナはメモリを喰う、OSが古いと環境構築で躓く)

  • 気質:そもそも会社に長く在籍する意思は無くポータブルスキルが欲しい

 なお上記に該当しない人は「Docker Desktop」の利用を推奨します。理由として①公式Docsがある、②ブログ、YoutubeやUdemyでDocker Desktopを使用した環境構築方法で多数の情報があるためです。

1-1.経緯

 一般的にPythonでは下記のことが実施できます。

  • Webアプリケーション開発:Webページの作成

  • データ分析:統計的な処理、可視化

  • AI:機械学習モデル

  • 趣味:ゲーム作り、電子工作

 私は製造業の開発~設計業務に従事していますが、個人開発や自分のPC内で完結(例:可視化したデータを報告書にまとめるなど)するのであればDockerは不要でした。
 しかし、社内事情で開発した機械学習モデルをDockerしか使えない環境下で実行させる必要が出ました。また色々ややこしい会社のため、なるべく自分だけで完結できる形で実装できるようにする必要がでたため、最低限の学習で実装したいと思います。

 なおDockerを使用する場合Linuxコマンドの学習は必須です。下記1冊で充分ですが索引含めて425ページあるため、Linuxの学習コストが高いと感じるのであれば他部署/できる人に任せるほうが良いと思います。
(私はスキル編重主義のため自力でやります)

【参考:代替案】
 やりたい目的は「イメージファイルの作成×ML実装」であり代替手段は手段はあります。例として仮想マシン(MwareやVirtualBox、Parallels、Hyper-Vなど)を使用する方法です。
 しかしプログラマーでもない私には鬼門×キャリアの方向性が違うので学習コストが高いと辛いためこの方法は避けました。参考までに用語一覧は記載しておきます。

Docker: Dockerはコンテナ型の仮想化を提供します。コンテナは独立した実行環境を提供しますが、ホストOSのカーネルを共有します。これにより、コンテナは軽量で高速になります。また、Dockerは"イメージ"というパッケージ形式を使用してアプリケーションとその依存関係を管理します。これにより、アプリケーションのデプロイが容易になります。

Hyper-V: Microsoftが開発したHyper-Vはハイパーバイザー型の仮想化を提供し、各仮想マシン(VM)が独自のゲストOSを持ちます。このため、VMは物理マシンとほぼ同じように動作しますがそれぞれが完全なOSを必要とするためリソース使用量が増えます。

VirtualPC: Microsoftが開発した仮想化ツールです。Windows 8の時点で使用できなっており、Hyper-Vに移行しております。

VMware Workstation: VMware WorkstationはVMwareが開発したハイパーバイザー型の仮想化ソフトウェアです。Workstationは商用ソフトウェアで、企業環境での仮想マシンのデプロイやテストに広く使用されます。

1-2.Dockerとは

 大前提としてDockerはWeb系エンジニア向けツールであり私には用語がほとんど理解できないため、かいつまんだ紹介となります。

 Dockerの大きな特徴は「開発環境をそのまま別の場所に移動・実装できる」ことです。
 私のPythonにおける経験の中でもプログラミングで1番難しく面白くないのは環境構築です。OSの違い、Versionの違いなどでエラーが発生することは当たり前であり、エラーが解決できないと最悪環境を一から構築しなおしとなります。

 Dockerは開発環境を一つの箱として扱えるため、その中で開発したら箱ごと別の場所に移動させることが出来ます。つまり同じ環境をそのまま移動できるためエラーの懸念が無く実装できます。

https://www.docker.com/resources/what-container/

 Docker構造のイメージは下図の通りです。

https://geekflare.com/docker-architecture/

2.Dockerサービスの概要

 Dockerには様々な製品があり名前だけではそれが何かが理解できません(Appleでいうiphone/ipad/icloud/ ituneみたいな感じ)。開発の歴史があり複数のサービスがあるため、まずはそれを整理します。

【サービス一覧】

  1. Docker Engine: Docker EngineはDockerの中心的な部分で実際にコンテナの作成や実行を行うソフトウェアです。Docker Engineはデーモンと呼ばれるプロセスを起動し、コンテナのライフサイクルを管理します。

  2. Docker CLI: Docker CLI(Command Line Interface)はユーザーがDocker Engineと対話するためのツールです。Docker CLIを使ってコンテナの作成、起動、停止、削除などの操作を行います。

  3. Docker CE: Docker CE(Community Edition)は一般的なユーザーや小規模チーム向けのDockerの無料版です。Docker CEにはDocker EngineとDocker CLIが含まれています。

  4. Docker EE: Docker EE(Enterprise Edition)は大規模な組織やビジネス向けのDockerの有料版です。Docker EEにはDocker CEに加えてセキュリティ強化、高度な管理機能、有料のサポートが含まれています。

  5. Docker Desktop: Docker DesktopはWindowsまたはMacで使用するためのDocker CEのバージョンです。Docker Desktopを通じてWindowsやMacユーザーはLinuxコンテナを直接実行することができます。

  6. Docker Toolbox: Docker Toolboxは古いバージョンのWindowsやMacでDockerを動作させるためのツールセットです。現在ではほとんどのユーザーはDocker Desktopを使用しますが、一部の旧式なシステムではDocker Toolboxが必要となることがあります。

  7. Docker Compose: 複数のコンテナを定義し実行する Docker アプリケーションのためのツールです。Compose は YAML ファイルを使い、アプリケーションのサービスを設定します。

  8. Docker Hub: Docker HubはDockerイメージを公開、共有、ダウンロードできる公開レジストリ(リポジトリの集合)です。Docker Hubを使用すると他の人が作成したイメージを利用したり自分が作成したイメージを他の人と共有することができます。

2-1.分類わけ:CLIのサービス

 CLI(Command Line Interface)のサービスは下記の通りです。

  • Docker CLI:コマンド操作

  • Docker CE:無償版のCLIツール(本記事ではこれを使用)

  • Docker EE:有償版のCLIツール

  • Docker Compose:CLI操作だが、複数コンテナを扱うためのdocker compose用ツール(無償)

https://docs.docker.jp/engine/installation/

2-2.分類わけ:Windows用のサービス

 Windows用のサービスは下記の通りです。Docker Toolboxはサポートが終了しているため、特に個人利用などにおいては、理由(OSが合わないなど)がない限りはDocker Desktopを選ぶ方がよいです。

  • Docker Toolbox(無償/レガシー)

    1. 2015年8月に導入開始/2020年7月にサポートと開発が終了

    2. 仕様:Windows 7 以上、OS:64 ビット(Windows 10 Homeでも使用可)

    3. 実行方法:Oracle VM VirtualBox上にDockerの実行環境を構築

    4. インターフェース:CLI(Command Line Interface)

  • Docker Desktop(※有償/最新)

    1. 2016年3月24日:Docker for Windows 1.12.0 リリース

    2. 2018年2月12日:Docker for Windows Desktop 18.02リリース

    3. 2019年5月6日: WSL2(後述)をMicrosoftがリリース

    4. 2019年7月18日: Docker Desktop for WSL 2をリリース

    5. 2021年9月1日:大企業に有償化をアナウンス

    6. 仕様:Windows 10 ProまたはEnterprise、Educationの64ビット版

    7. 実行方法:VirtualBoxは不使用

    8. インターフェース:GUI(Graphical User Interface)

 別記事ではDocker Desktopにも2種類あるとのことです(著者推奨はWSL2版でのDocker)。

https://penpen-dev.com/blog/windows-docker-tigai/

 2-2-1.Docker Desktopの有償化

 2021年9月1日よりDocker Desktopは大企業に対して有償化のアナウンスがされました(適用までの猶予期間は2022年1月31日まで)。参考までに2022年10月18日にプランの値上げも実施しております。それ以降で現在まで価格の変更はありません。
 なお「個人利用、スモールビジネス(従業員数250人未満かつ年間売上高1000万ドル未満(訳注:1ドル110円換算で11億円))、教育機関、非商用のオープンソースプロジェクト」では引き続き無料で使用できます。

 1人あたりの価格は安いため年収が高く用途が多いなら自腹でもよいとは思います。私はとにかくイメージファイルを作ってMLモデルを実装できればよい+低い年収のためとにかく自力で実装します。

https://www.docker.com/pricing/
https://www.docker.com/pricing/

2-3.分類わけ:クラウドのサービス

 クラウドサービスは「Docker Hub」となります。

3.Docker用語集

 簡単にDockerで使用される用語について紹介します。

  • ホストマシン(ホストOS):自身のPC(のOS)

  • ゲストマシン(ゲストOS):仮想環境下のPC(のOS)

  • Dockerfile:Dockerイメージの設計図

  • イメージ:テンプレートファイル

  • コンテナ:アプリケーションの実行環境

4.環境構築

 今までの流れを考慮して下記方針でWindows PCに環境構築します。メリットとしては無償で使えますが、デメリットとしてすべてCLI操作であり、かつLinuxコマンドが必須となります。

  • まずはWSL2でWindows上にLinux環境を構築

  • そのLinux上にDocker CEを追加

4-1.事前準備

 Dockerをインストールする前に事前準備で下記の環境構築を実施します。各環境構築方法は下記記事やブログなどをご確認ください。

  • VS CODE(Visual Studio Code):エディター(IDE)

  • Python:プログラミングソフト

  • Windows Terminal:複数のターミナルを一元管理

  • Git:バージョン管理システム

  • WSL2:WindowsPC内にLinux環境を構築

4-2.環境構築:Docker Desktopのアンインストール

 もしDocker Desktopをインストール済みであれば、まずはアンインストールします。インストールしていなければ不要です。

4-3.UbuntuのVersion確認

 WSL2でのUbuntu(Linux)のVersionを"22.04LTS"にしたいと思います。
※直近でUbuntuをダウンロードした人は最初から"22.04LTS"のため更新不要

 まず初めに現行のVersionを確認します。結果として”20.04.5 LTS”であることを確認しました。

[Terminal]
cat /etc/os-release
[OUT]
NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.5 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

 下記参考にUbuntuのVersionを22.04LTSへUpgradeします(2023年5月現在)。

  • sudo apt update && sudo apt upgrade:パッケージの依存解決

    • sudo(SuperUser DO):システム管理者としての権限でコマンド実行

    • apt(Advanced Package Tool):パッケージ管理ツール

    • Update:システムのパッケージリストを更新

    • Upgrade:インストール済みのソフトウェアを最新にアップグレード

  • sudo apt dist-upgrade && sudo apt install update-manager-core:ディストリビューションアップデートの確認

    • sudo apt dist-upgrade:より強力なバージョンアップグレード

    • update-manager-core:manager-coreパッケージをインストール

  • sudo vim /etc/update-manager/release-upgrades:relese-upgrade設定

    • vim:Vimエディタで指定のファイルを開く

    • vimの終了コマンド「:q <Enter>」の順に入力する

[Terminal]
sudo do-release-upgrade -d
sudo apt dist-upgrade && sudo apt install update-manager-core
sudo vim /etc/update-manager/release-upgrades

 準備ができ「Prompt=lts」も確認したためアップグレードを実行します。途中でいろいろ聞かれますが全て「yN」で実行しました。

[Terminal]
sudo do-release-upgrade -d

 実行完了後にVersionが変更されているか確認します。

[Terminal]
cat /etc/os-release
[OUT]
PRETTY_NAME="Ubuntu 22.04.2 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.2 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

4-4.Docker CEのインストール

 下記記事ベース(出典:Install Docker Engine on Ubuntu)に、以下のコマンドを順に実行してUbuntuに Docker CEと Docker Composeを順次インストールします。

[Terminal]
# パッケージインデックスの最新化
sudo apt-get update

# リポジトリに HTTPS接続するためのパッケージをインストール
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# Docker公式の GPGキーを取得&追加
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# リポジトリのセットアップ
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 再度パッケージインデックスを最新化後、Docker CEのパッケージ群をインストール
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

【処理内容の詳細説明】

  1. sudo apt-get update: システムのパッケージリストを更新します。つまり利用可能なソフトウェアの最新バージョンの情報をインターネット上のリポジトリから取得しローカルのリストを最新の状態に更新します。

  2. sudo apt-get install ca-certificates curl gnupg lsb-release: パッケージをインストール

    • ca-certificates: Common Authority(CA)証明書をシステムにインストールします。CA証明書は、ウェブサイトのセキュリティを確保するために使用されるデジタル証明書です。たとえば、https接続時にサーバーが本当に主張しているサーバーであることを確認するために使われます。インストールすることで、システムがこれらの証明書を信頼し、安全な通信を行うことが可能となります。

    • curl: コマンドラインからURLにアクセスするためのツールです。データを送信したり、ウェブサイトからデータをダウンロードしたりすることができます。このケースでは、DockerのGPGキーをダウンロードするために使用されます。

    • gnupg: GNU Privacy Guard (GnuPG)は暗号化と認証のツールで、通信のプライバシーとセキュリティを確保します。GnuPGは、公開鍵暗号化と対応する秘密鍵を用いて、メッセージを暗号化したり、デジタル署名を生成・検証したりします。このケースでは、DockerのGPGキーを受け取って処理するために使われます。

    • lsb-release: Linux Standard Base (LSB) version reporting utilityというツールです。システムのLSB情報(例えばディストリビューションの名前やバージョンなど)を表示するために使われます。このケースでは、適切なDockerリポジトリを選択するためにシステムの情報が必要となり、そのために使用されます。

  3. sudo mkdir -p /etc/apt/keyrings:mkdir(フォルダ作成用コマンド)で”/etc/apt/keyrings"というディレクトリ(フォルダ)を作成します。このディレクトリは後のステップでDockerのGPGキーを保存する場所として使用されます。

  4. curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg: このコマンドはDockerの公式GPGキーをダウンロードし、gpg --dearmorを使ってバイナリキーリングファイルに変換し、これを先ほど作成した/etc/apt/keyrings/ディレクトリに保存します。このキーは、ダウンロードしたパッケージが実際にDockerから提供されていることを確認するために使用されます。

  5. echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null: このコマンドは新たなリポジトリをシステムのリポジトリリストに追加します。このリポジトリはDockerのパッケージを提供します。このリポジトリはGPGキーによって署名されており、teeコマンドを使用してリポジトリ情報を/etc/apt/sources.list.d/docker.listというファイルに保存します。

  6. sudo apt-get update: 再度パッケージリストを更新します。今回は新たに追加したDockerのリポジトリからパッケージ情報を取得します。

  7. sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin: 最後にDockerのコアコンポーネント(docker-ce, docker-ce-cli, containerd.io)と、Docker Composeのプラグイン(docker-compose-plugin)をインストールします。

    • docker-ce:Docker Community EditionでDockerの基本パッケージ

    • docker-ce-cli:Dockerのコマンドラインインターフェイスです。これによりターミナルからDockerを操作できます。

    • containerd.io:ランタイムに関連する機能を提供します。コンテナの実行環境を担当します。

    • docker-compose-plugin:Docker Composeのプラグインで、複数のコンテナを一度に管理するためのツールです。

4-5.ibtablesの整合性を取る

 (よくわかりませんが)Dockerと Ubuntuが使用する ibtablesの整合性を取る必要があります。以下のコマンドを実行して iptables-legacyを Ubuntuのデフォルト参照先に指定します。なお、この設定をしないと Dockerサービスを起動できません。(参考: Dockerフォーラム

[Terminal]
$sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy

 以上でDocker CEの設定は完了です。後ほどDocker Composeの設定も実施します。

4-6.動作検証

 動作確認のためDockerサービスを起動して hello-worldが出力されることを確認します。多分これでうまくいけたと思います。

[Terminal]
sudo service docker start
sudo docker run hello-world

【docker run hello-worldの動作】
 このコマンドの動作は下記の通りです。詳細は次章で説明しますが、既にDockerコマンドを使用できる準備がされております。

  • "hello-world"というDockerイメージがなければダウンロード(おそらく裏側でdocker pullが実行されています)

  • Dockerイメージがあれば、コンテナを起動(名前はランダム)

  • ターミナルに”Hello from Docker!”を表示

  • コンテナを停止(※コンテナの削除でない点に注意)

4-7.ユーザーの設定変更:usermod

 次回以降は sudoを省略できるように、一般ユーザに dockerコマンドの実行権限を付与します。

[Terminal]
sudo usermod -a -G docker <ユーザー名>

 正常終了したか確認するために一度立ち下げ(Windows Terminalを閉じる or exitコマンド入力)/再起動して"docker ps"と入力してエラーがでなければ完了です。

4-8.Docker Composeのインストール

 Docker ComposeのVersion2.6.0をインストールします。

[Terminal]
sudo curl -L https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

 ”docker-compose --version”で出力がでれば正常です。以上で設定は完了しました。

[Terminal]
docker-compose --version

【参考:Linuxコマンド説明】

  1. sudo curl -L <URL> -o <ファイル保存先>

    • sudo(SuperUser DO):システム管理者としての権限でコマンド実行

      • "/usr/local/bin"ディレクトリに書き込むには管理者権限が必要

    • curl: URLからデータをダウンロードするためのツール

      • -L(curlコマンドオプション: 「リダイレクトされた場合もその先に追従する」という意味です。このオプションがないとURLがリダイレクトされた場合にダウンロードが失敗する可能性があります。

      • -o(curlコマンドオプション) :DLしたファイルをどこに保存するかを指定するオプションです。今回は/usr/local/bin/docker-composeに保存しました。

    • https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-uname -s-uname -m: ダウンロードするファイルのURL

      • uname -s:現在のシステムのOS(出力はLinux)

      • uname -m:現在のシステムのアーキテクチャ(出力はx86_64)

      • これらをバッククォートで囲むことで、シェルがこれらのコマンドを先に実行し、その結果をURLの一部として使用できます。

  2. sudo chmod +x /usr/local/bin/docker-compose

    • chmod: ファイルモード(権限設定)を変更するためのツール

    • 指定方法は"chmod [誰に][どうする][何を] <ファイル名>"

    • +x: "+"で権限を追加、”x”で「実行可能(executable)」フラグを追加

    • /usr/local/bin/docker-compose: 権限変更するファイルのパスを指定

【uname-s, uname-mの動作確認】
 下記のようにそれぞれOS, アーキテクチャを出力し、バッククォートで囲うことで値を挿入できます。

5.Docker基礎1:ローカル用

 Dockerを使用していくためにまずは簡単な基礎知識・基礎コマンドを学習していきます。
 なおPC立ち下げ後にdokcerを実行しようとしてエラーが出た場合、Dockerデーモン(Dockerのバックグラウンドで動作しているプロセスであり、DockerのコマンドがDockerエンジンと通信するために必要)が停止している可能性があります。その場合"sudo service docker start"で再起動します。

[Terminal]
sudo service docker start

5-1.確認用コマンド:images, ps, logs

【docker --help】
 Dockerコマンド確認します。公式Docsからでも確認可能です。

[IN]
docker --help

 コマンドの後ろに"--help"をつければそれのオプション確認が可能です。

【docker --version】
 DockerのVersionを確認できます。

[IN]
docker --version

[OUT]
Docker version 24.0.2, build cb74dfc

【 docker images】
 ローカルPCのDockerイメージの情報表示します。環境構築時に”docker run hello-world”を実行したためDockerイメージ(レポジトリ)に"hello-world"があります。

[IN]
docker images

[OUT]
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
hello-world   latest    9c7a54a9a43c   3 weeks ago   13.3kB

【docker ps】
 起動しているコンテナ情報を表示します。psにはオプションをつけることで詳細表示が可能です。

  • -a:終了したコンテナも含めてすべて表示

  • -a -q-qオプションはIDのみを出力するため"-a -q"で全コンテナのIDのみ出力

[IN]
docker ps

[OUT]
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

ーオプションの事例ー

 下記は"-a"オプションを付けた時の出力です。停止したコンテナが出力されました(削除されたコンテナは出力されません)。
 また"-a -q"ではIDのみ出力されます。

[IN]
docker ps -a

[OUT]
CONTAINER ID   IMAGE         COMMAND    CREATED             STATUS                         PORTS     NAMES
b6e316350548   hello-world   "/hello"   3 minutes ago       Exited (0) 3 minutes ago                 romantic_lamport
1ca162c853a7   hello-world   "/hello"   7 minutes ago       Exited (0) 7 minutes ago                 laughing_gauss
77d1bde80b2e   hello-world   "/hello"   About an hour ago   Exited (0) About an hour ago             dreamy_jones

【docker logs <コンテナ名>】
 コンテナのログを表示します。

5-2.コンテナ操作

 5-2-1.docker run <イメージ>:コンテナ起動

 "docker run <Dockerイメージ(レポジトリ)>"で新しいコンテナを作成し、指定したDockerイメージを実行します。

【オプション】

  • --name:コンテナに名前を付ける

  • -d:バックグラウンドでコンテナを実行

  • -e:コンテナ内で使用する環境変数を設定

  • -p:ホストとコンテナ間でポートをマッピング

    • ホストOS(自分のPC)とゲストOS(仮想環境)のポートを紐づけ

    • -p <ホストマシンのポート>:<コンテナ内のポート>

  • -v:ホストとコンテナ間でボリューム(データ)を共有

  • -it:ターミナル上でコンテナ内の操作が可能

 注意点として1つのイメージから複数のコンテナを作成することができます。不必要にコンテナが作成されていないか"docker ps"で確認できます。

 "docker run hello-world"では”hello-world”のDockerイメージが無い場合はDocker Hubから自動的にPullしてイメージを取得してくれます(おそらくdocker runの機能でイメージがなければDocker Hubから探してくれます)。

[IN]
docker run hello-world

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

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

 参考として"kiyo1st"という名前を付けてコンテナを作成してみました。

[terminal]
docker run --name kiyo1st hello-world

【エントリーポイントの設定:docker run -it <イメージ名> <エントリーポイント>】
 "docker run -it python /bin/bash"
とすることで"python"というDockerイメージからコンテナを作成するのに合わせて、pythonの対話モードではなくBashというLinuxやUnix系のシステムで広く使用されているターミナルを立ち上げることが出来ます。

 Windowsではターミナルとしてコマンドプロンプト(CMD)やPowerShellがあり、ターミナル⇔Pythonの対話モードの切り替えが簡単にできます。ターミナルでは"pip install"などを使用してライブラリの追加も可能です。

 "docker run -it python"だとpythonの対話モードから入るため、ターミナルでライブラリのインストールなどができません。そこでエントリーポイント(イメージを起動したときに実行されるデフォルトのプログラム)を指定することでDockerイメージに記載されているものとは別のエントリーポイントを実行することが出来ます。

 (詳細は6章参照)下記にPythonコンテナを立ち上げた例より、下記が確認できます。

  • 対話モードだとPythonを実行するためLinuxコマンドが使用できない

  • bashで入ると別の環境に入っていることが確認できる(lsコマンドより作業ディレクトリが違うことが確認できる)。

  • bashで入るとpip installでライブラリをインストールでき、その後python対話モードに入るとライブラリが使えることが確認できた。

【注意点】
 "docker run"は毎回異なるコンテナを立ち上げるため、同じ名前を指定しても環境構築したコンテナには入れません。また終了と同時にコンテナが停止するファイルではdocker startやdocker execでコンテナに入りなおすことは難しかったです(できるかもしれませんが私には無理でした)。
 環境構築したコンテナを再利用したいのであれば最悪①docker commitでコンテナをイメージ化、②作成したイメージから再度新しいコンテナを作成することで対応できます。

 5-2-2.その他操作:start, run

【docker start】 
 "docker stop"で停止したコンテナを立ち上げるためのコマンドです。コマンドは"docker start <Dockerイメージ(レポジトリ)名>"です。

 ポイントとして"docker start "は既存のコンテナを再起動するだけでありコンテナの実行結果は表示しません。よって"hello-world"を再起動しても、起動が成功したことを示すためのID(コンテナ名)は表示されますが、出力結果は表示されません。
 もし出力を確認したい場合は"docker logs <Dockerイメージ(レポジトリ)名>"を使用します。

[terminal]
docker start kiyo1st

【docker exec】
 コンテナ内に入りターミナルから操作可能です。docker execのオプションは下記の通りです。

  • -it:ターミナル上でコンテナ内の操作が可能(抜ける場合はCtrl+Q)

 5-2-3.起動コマンドの比較

 docker run, docker start との違いは下記の通りです。

  • docker run

    • コンテナ作成+コンテナ内のコマンド実行

    • イメージがローカルになければDocker HubからDL

    • -itオプションは、コンテナは停止中でも可能

  • docker start

    • 停止中の既設コンテナを再起動

    • 一度設定した環境をそのまま利用する場合に使用

  • docker exec

    • 起動中のコンテナでコマンド実行(コンテナの作成はしない)

    • イメージがなければエラー

    • -itオプションは、コンテナが起動中でないと不可(停止中でも不可)

5-3.コンテナからイメージ作成:commit

 コンテナからイメージ(※Con->ConでなくCon->Img)を作成するには"docker commit <コンテナ名> <イメージ名>"コマンドを使用します。
 例として"hello-world"イメージで作成した"kiyo1st"コンテナから"kiyo2nd"イメージを作成しました。

[Terminal]
docker commit kiyo1st kiyo2nd

5-4.停止・削除:stop, rm, rmi, prune

【docker stop <コンテナ名>】
 コンテナの停止(※削除ではない)は"docker stop <コンテナ名>"を使用します。停止成功したらID(コンテナ名)が表示されますが、"docker ps -a"のSTATUSが"Exited"になっているかでも確認可能です。

[Terminal]
docker stop kiyo1st

【docker rm <コンテナ名>】
 
コンテナの削除(※Dockerイメージの削除ではない)は"docker rm <コンテナ名>"を使用します。下記では"docker ps -a"で停止中のコンテナ名を確認してそれを削除しました。

[Terminal]
docker rm suspicious_dubinsky

 イメージは残して全コンテナを削除する場合は"docker rm $(docker ps -a -q)"を使用します。もし起動中のコンテナがあるとエラーが出るため、強制的に削除したい場合は"-fオプション"を追加して"docker rm -f $(docker ps -a -q)"とします。

[Terminal]
docker rm $(docker ps -a -q)

【docker rmi <Dokcerイメージ(レポジトリ)名>】
 Dockerイメージを削除します。注意点は下記の通りです。

  • コンテナが停止中でも存在する場合はイメージの削除はエラーとなる

  • イメージから作成したコンテナが無ければ削除可能

  • オプション

    • -f(-force):強制的にイメージを削除

【docker system prune -a】
 全てのコンテナとイメージを削除します。

[Terminal]
docker system prune -a

 下図は"hello-world"のDockerイメージが1個、コンテナが多数あります(docker run hello-worldコマンドを実行しまくれば、1個のイメージから複数のコンテナを作成することになります)。

 "docker system prune -a"実行後にコンテナ・イメージを確認すると全て削除されていることが確認できました。

5-5.インポート/保存:save/export, load/import  

 作成したDockerのデータを取得・保存方法はDockerイメージとコンテナを対象として2種あります。Dockerイメージはレイヤ情報なども含むためファイルサイズだけ見ればexportの方がファイルは小さくなります。

【Dockerイメージを対象とした操作】

  • docker save [オプション] <イメージ名>.tar:イメージの保存

    • よく使う形:docker save <イメージ名> > <保存名>.tar

  • docker load <イメージ名>.tar:saveで保存したイメージの読み込み

    • よく使う形:docker load < <保存名>.tar

【コンテナを対象とした操作】

  • docker export [オプション] <コンテナ名>.tar:コンテナの保存

    • よく使う形:docker export <コンテナ名> > <保存名>.tar

  • docker import <コンテナ名>.tar:importで保存したデータの読み込み

 下記に"hello-world"イメージから適当に色々してみます。

[Terminal]
docker run --name test1 hello-world

docker save hello-world > h2.tar
docker export test1 > container1.tar

6.Docker基礎2:Docker Hub

 Docker HubはDockerイメージを共有するためのクラウドベースのレジストリサービスです。開発者はDocker Hubを使用して自分が作成したDockerイメージを公開したり、他の人が作成して公開したイメージを検索したりダウンロード(pull)したりできます。またDocker Hubは自動的にイメージをビルドし、リポジトリをGitHubやBitbucketと連携させる機能も提供しています。

 Docker Hubのアカウントは作成しなくても様々な機能は使用できますが、無料で登録できるため事前に作成しておいてもよいです。

6-1.Dockerイメージの探し方

 Docker Hubに共有されたイメージを探します。手順は下記の通りです。

  1. キーワード入力:検索ボックスに欲しいアプリのキーワードを入力

  2. アプリ選択:検索一覧の中で欲しいアプリを選択

    • 悪意ある開発者もいるため基本的に「DOCKER OFFICIAL IMAGE」選択

  3. docker pullコマンドのコピー:Dockerイメージを自分のPC内に保存(Pull)

  4. Dockerイメージの使い方確認:”How to use this image”からイメージの使用方法を確認

【参考:別Versionの確認】
 
別Ver.(旧Ver.)を確認する時はTagsタグから確認可能です。

6-2.Docker Hubからイメージ取得:pull

 例としてPythonのDockerイメージをDocker HubのリモートレポジトリからローカルPCにダウンロードします。
 Pythonでは何も指定しなければ最新版がDLでき、タグをつけるとVersion指定することが可能です。

[Terminal]
docker pull python
docker pull python:3.8

 上記で最新版とVer3.8をDLしました。"docker images"で2つのイメージがDLされたことを確認できました。

[IN]
docker images

[OUT]
REPOSITORY   TAG       IMAGE ID       CREATED      SIZE
python       latest    0a6cd0db41a4   5 days ago   920MB
python       3.8       0869a4e92f01   5 days ago   905MB

 参考までに上記で"python"という名前のDockerイメージ(レポジトリ)を取得できましたので”docker run <イメージ名>”でコンテナを作成できます。"docker run --name kiyopy python"とすればversion指定なし(最新版の)kiyopyという名前のコンテナを作成できます。

[Terminal]
docker run --name kiyopy python

【PythonのVersion確認】
 インタラクティブモード(itフラグ)でPythonのVersionを確認します。なおpythonイメージから立ち上げたコンテナは終了後に自動で停止するためexecではエラーになります。
 (コンテナが増えるのは手間ですが)"docker run -it python"でコンテナ立ち上げ+ターミナル操作でVersionを確認しました。

[IN]
docker run -it python
from platform import python_version
print(python_version())
exit()

[OUT]
3.11.3
[IN]
docker run -it python:3.8
from platform import python_version
print(python_version())
exit()

[OUT]
3.8.16

【参考:Linux OSの種類】
 
Dockerイメージをpullしたりするとき、OSの指定どこにあるの?と思ったりしたのですが、ここでは軽量なLinuxのDebianが使用されています。
 普段WSL2を使用するため「Linux=Ubuntu」のイメージだったのですがUbuntuは比較的サイズが大きいLinux OSとなります。より軽量で動作するDebianがありますが、Versionによってそれぞれ名前が振られています。
 ”python:3.8-slim-buster”でPullするとPythonに合わせて(Linux)OSとしてDebian10がインストールされます。

https://future-architect.github.io/articles/20200513/
https://zenn.dev/ken3pei/articles/1abbf7d974cf5d

6-3.Docker Hubにアップロード:Push

 Docker Hubの自分のレポジトリにDockerイメージをPush(アップロード)するには"docker push"を使用します。全体の流れは下記の通りです。

  1. docker login:事前にアカウントにログイン

  2. docker commit <User>/<Image name>:PushしたいコンテナをDocker Hubのユーザー名を用いてイメージ化

  3. docker push <イメージ名>:前項で指定したイメージをPush

 Pushするためには事前にDocker Hubのアカウントを作成したうえで、"docker login"でログインしておく必要があります。
(事前ログインが無いとリクエスト拒否のエラーが発生)

[Terminal]
docker login

 次にコンテナをcommitでイメージ化します。この時"docker commit <Docker Hubのユーザー名>/<新規のイメージ名>"の形で作成します。ユーザー名のディレクトリを指定しないとPush時にエラーが出ます。

 最後に"docker push <User>/<イメージ名>" を実行し正常終了したら自分のDocker Hubレポジトリにイメージファイルが追加されました。

6-4.Docker Hubのレポジトリ削除

 Docker Hub上のレポジトリはローカルPC上からは削除できません。ローカルPCとDocker Hubが連動しているわけではないため"docker rmi <User>/<イメージ名>"だとローカルPC側のDockerイメージが削除されるだけであり、Docker Hub(クラウド)上のファイルは残ったままです。

 レポジトリの削除はDocker Hub上から直接実施します。

7.Docker基礎3:イメージ作成

7-1.Dockerfileの基礎

 DockerfileはDockerイメージを作成するためのスクリプトファイルです。Dockerfileでは、ベースとなるイメージを選択し、追加のインストールやファイルのコピー、環境変数の設定など、新しいイメージを作成するための一連の手順を定義します。

 7-1-1.Dockerfileコマンド

 Dockerfileには専用の記法があるため一部を紹介します。

【基本コマンド】

  • FROM:ベースになるDockerイメージを定義します

    • コマンド例:FROM <イメージ名>

    • イメージ名はDocker Hubのアプリ内のTagsから確認可能です。

    • 特殊例として"FROM scratch"とすることで空の状態から開始することも可能です(普段は使用しない)。

【シェルコマンド実行】
 RUNはコンテナ起動時、CMD・ENTRYPOINTはコンテナ実行時に動作します。

  • RUNコンテナイメージ作成時に実行するシェルコマンドであり、イメージの作成時にパッケージのインストール、ディレクトリの作成など、イメージ内の環境設定を行うために使用されます。

    • コマンド例:RUN <Linuxコマンド>、RUN apt-get update && apt-get install -y gi

    • pythonの環境構築では"pip install -r requiments.txt"などで使用

  • CMDコンテナ起動時に実行するデフォルトのコマンドを設定します。ただしこの設定はdocker runコマンドで新たなコマンドが指定されると、そのコマンドに上書きされます。

    • CMD命令はDockerfile内で一度だけ使用可能

    • 記法は  CMD ["python", "app.py"] のように記載

  • ENTRYPOINTコンテナ起動時に常に実行するコマンドを定義します。こちらはdocker runコマンドで上書きされません。その代わりdocker runコマンドで指定したコマンドは、ENTRYPOINTで指定したコマンドの引数として扱われます。

【ファイルコピー】

  • COPY:ホストマシン(ローカルPC)のファイルやディレクトリをコンテナにコピーします。

    • コマンド例: COPY <ローカルPCのパス> <コンテナ側のパス>

    • Pythonの場合"requirements.txt"を使用して環境構築する場合、コンテナ側にこのファイルが無いと実行できないためCOPYする。

  • ADD:ホストマシン(ローカルPC)のファイルやディレクトリをコンテナにコピーします。COPYとは違いは下記の通り

    • URLを指定可能(リモート上のファイルも扱える※Docker HubだけでなくIrisデータのような公開データも可能)

    • tarファイルを自動で展開したりすることができる

    • コマンド例: ADD . /app , ADD http://example.com/big.tar.gz /app

【その他コマンド】

  • WORKDIR:"WORKDIR <パス>"で作業ディレクトリを設定

  • EXPOSE:コンテナのポートを公開します。例: EXPOSE 80

  • ENV:環境変数を設定(ENV <環境変数>=<設定値>)例: ENV PATH /usr/local/bin:$PATH

  • USER:ユーザー名を指定(例:USER root)

  • VOLUME:ー

 7-1-2.サンプルコード

 Pythonで簡単にHello worldを実行するためにサンプルコードを作成します。実行したいPythonスクリプトの"kiyo_hello.py"にはprint("Hello World")、Dockerfileには下記を記載しました。

  1. 取得するイメージ(FROM)※イメージはDocker HubのTagsのslim-busterからPythonのVersion指定

  2. コンテナ側にコピーするファイル指定(COPY)

  3. コンテナ立ち上げ時(起動時ではない)に実行するコマンド(CMD)

[Dockerfile]
FROM python:3.9-slim-buster
COPY kiyo_hello.py kiyo_hello.py
CMD python kiyo_hello.py
[kiyo_hello.py]
print("Hello World")

7-2.Dockerイメージの構築:docker build

 DockerfileからDockerイメージを作成(ビルド)するコマンド”docker build”です。このコマンドより、Dockerfileに記述された手順に従い新しいDockerイメージが作成されます。
 ビルドする時の作業ディレクトリはDockerfileやDockerfile内で指定したファイルが存在する場所で実行する必要があります。

 7-2-1.サンプル:簡単なビルド例

 WSL2においてWindows側の作業ディレクトリに移動するには"cd /mnt/c/Users/<username>/Desktop"を使用します。

[Terminal]
cd /mnt/c/Users/kiyo/Desktop

 Dockerfileがある作業ディレクトリで下記を実行します。実行後に"docker images"で確認すると新しく"kiyo_hello"レポジトリが作成されています。
 なおdocker内にDockerイメージが作成されますが、ローカルPC側に何かファイルが作成されるわけではありません。

[Terminal]
docker build -t kiyo_hello .

 作成したDockerイメージ(レポジトリ)をdocker runでコンテナ作成+コンテナ実行することで下記が確認できました。

  • 作成したPythonスクリプト(kiyo_hello.py)の処理が出力されている

  • bashでコンテナ内のファイルを確認するとPythonスクリプトが存在している(COPYコマンドでコンテナ側に追加されたため)

 7-2-2.docker buildのオプション

 docker buildのオプションは下記の通りです。

  • -t, --tag:イメージに名前とタグを付けるために使用します

    • docker build -t myapp:1.0 .とすると、作成したイメージにmyappという名前と1.0というタグが付けられます。

  • --file, -f:Dockerfileの名前やパスを指定するために使用します。

    • デフォルト:DockerfileのためファイルがDockerfileであれば指定不要

  • --no-cache:キャッシュを使用せずにイメージをビルドします。Dockerは通常、それぞれの命令の結果をキャッシュして再利用しますが、このオプションを指定すると全てのステップを新たに実行します。

 7-2-3.ビルドコンテキスト.

 概念が難しく理解があっているかわかりませんがおそらく、DockerがDockerfileをビルドする際に参照できるファイルやディレクトリのセットを指します。つまりdocker buildを実行した時の作業ディレクトリ以下にあるファイル(全てのファイルとサブディレクトリ)と思います。このため作業ディレクトリに大量の不要なファイルが存在すると、ビルドプロセスが無駄に遅くなる可能性があります。

 Dockerの概念図は下図の通りであり、作業ディレクトリのファイルをいったん"docker daemon"に送信した後、Dockerfileの指示に従い特定のファイルだけコンテナイメージに追加されます。

https://geekflare.com/docker-architecture/

 動作を確認するために適当に下記を作成しました。

  1. Pythonスクリプトを作成:(Linuxコマンドを使用して)「a.py, b.py, c.py, d.py」の4つを作成してコードはprint(this is <ファイル名>)とした

  2. Dockerfile作成:下記3つを実行

    1. python3.8のDockerイメージをDocker HubからPull

    2. a.pyとb.pyファイルをcopy

    3. CMDでb.pyのみ実行

  3. Dockerイメージのビルド:イメージファイルの作成

    1. コマンド: docker build -t <イメージ名:タグ> <ビルドコンテキスト>

    2. -tオプションで適当にTAG付け

    3. ビルドコンテキスト . を指定

[terminal]
echo "print('This is a.py')" > a.py
echo "print('This is b.py')" > b.py
echo "print('This is c.py')" > c.py
echo "print('This is d.py')" > d.py
[Dockerfile]
# Pythonイメージをベースにする
FROM python:3.8

# ファイルをコピー
COPY a.py .
COPY b.py .

# b.pyを実行
CMD ["python", "b.py"]

 Dockerfileの作業ディレクトリに移動してDockerfileからイメージを作成します。”docker images”で指定のTAGを付けたイメージ生成を確認しました。

[terminal]
docker build -t tesim:1.0 .

 作成したイメージの起動(docker run)やbashを起動してコンテナ内を操作することで下記を確認できました。

  • ビルドコンテキストは「a.py, b.py, c.py, d.py」の4つのはずだが、コンテナ内にはDockerfileで指定した2つしかない。

  • lsコマンドで確認するとコンテナ内にはa.py, b.pyのみ確認できた

  • docker runでイメージからコンテナを起動するとDockerfile内に記載したCMDによるコマンドが実行されるためb.pyのみ実行された。

[terminal]
docker run -it tesim:1.0 /bin/bash
ls
python a.py
python b.py 
exit
docker run tesim:1.0

 このため、作業ディレクトリに大量の不要なファイルが存在すると、ビルドプロセスが無駄に遅くなる可能性があります。対策としては".dockerignore"ファイルを使用するか、不必要なファイルは作業ディレクトリに置かないことが推奨されます。

7-3.Dockerfileのサンプルコード

 適当に何個かDockerfileでイメージを作成・実行することで動作イメージを理解します。

【1.コンテナでstreamlitを立ち上げて猫画像を表示】
 設計思想・作業フローは下記の通りです。

  1. app.py:Streamlitで猫の画像を表示するスクリプト作成

  2. requirements.txt:app.pyに必要なライブラリをインストール

  3. Dockerfile

    • PythonイメージのPull、Streamlitのポート指定

    • requirements.txtのコピー/インストール

    • app.pyのコピー/CMDによる実行

  4. docker build:イメージ作成

  5. docker run -p 8501:8501:ホスト/ゲストのポート番号を紐づけてコンテナを起動

[app.py]
# app.py
import streamlit as st
from PIL import Image
import requests
from io import BytesIO

# 画像のURL
url = "https://assets.st-note.com/img/1661919379413-vE07W5wCwS.jpg"

response = requests.get(url)
img = Image.open(BytesIO(response.content))

st.title('Dockerfileのテスト')
st.image(img, caption='konan.jpの画像', use_column_width=True)
st.text('https://assets.st-note.com/img/1661919379413-vE07W5wCwS.jpg')
[requirements.txt]
streamlit
Pillow
requests
[Dockerfile]
# Dockerfile
# ベースとなるDockerイメージ指定
FROM python:3.8

# Streamlitのデフォルトのポート番号
EXPOSE 8501

# 作業ディレクトリを設定
WORKDIR /app

# 依存関係ファイルを作業ディレクトリにコピー
COPY requirements.txt ./ 

# 依存関係ファイルを使用して必要なパッケージをインストール
RUN pip install -r requirements.txt

# Streamlitアプリケーションを作業ディレクトリにコピー
COPY app.py ./ 

# コンテナが起動した際に実行されるコマンド
CMD streamlit run app.py

 準備が出来たら作業ディレクトリに移動してビルドします。ビルド後に"docker images"でDockerイメージの生成を確認します。

[Termianl]
docker build -t streamlit-app .

 "docker run -p <ホストのポート>:<コンテナのポート>"を指定してコンテナの作成・起動します。出力されたURLはコンテナ側視点のため意味ないですが「http://localhost:8501/」をブラウザに入力することで立ち上がっているstreamlitが確認できました。
※ちなみにsteamlit起動後にCtrl+Cでターミナルに戻れないため、終わったタイミングでdocker stopでコンテナを手動で停止させました。

[Termianl]
docker run -p 8501:8501 streamlit-app

8.Docker compose

 Docker Composeとは、複数のDockerコンテナを一度に管理・実行(起動・停止・ビルド)するためのツールです。それぞれのDockerコンテナがどのように動作するかを詳細に定義するのは手間のためDocker Composeが使用されます。
 設定はYAMLファイルに記述され、これにより各サービス(コンテナ)がどのように動作するかが定義されます。

 なお、Docker Composeは基本的には開発・テスト環境での利用が想定されており、大規模な本番環境や高度なオーケストレーションを必要とする場合はKubernetesのようなより高機能なツールを検討する必要があります。

 現状の目的に対してDocker composeは無くてもよいと思うので、学習コストの面で本記事では省略します。

9.Docker実践:ML実装

 下記流れのMLモデルを作成していきます。

  1. irisデータのダウンロード:wgetコマンドでローカルPCにIrisデータをDL

  2. model.py:DLしたirisデータセット用の機械学習モデルスクリプト

    • 機械学習モデル:決定木

    • 乱数値:再現性を確保するために固定

    • 学習:テスト=8:2

    • 出力(数値ベース):精度(Accuracy)、F1スコアを出力

    • 出力(画像):混同行列、dtreevizでの要因分析、graphvizでの要因分析(重要度分析、木構造の可視化)をpngで出力

  3. requirements.txt:必要なライブラリをインストール

  4. Dockerfile:コンテナを作成するためのDockerイメージ作成用

  5. docker build/docker run:イメージ作成/コンテナ起動で出力を取得

9-1.Irisデータのダウンロード

 Linuxコマンドのwgetを使用してIrisデータをDLします。

[OUT]
wget https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data

9-2.機械学習モデルの作成

 機械学習モデルのスクリプトを実装しました(dtreevizは最新VerでAPIが変更されているため参考程度となります)。

[model.py]
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix
from sklearn.tree import export_graphviz
import dtreeviz
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import LabelEncoder
from cairosvg import svg2png
import pydotplus


# データ読み込み
df = pd.read_csv('iris.data', header=None)
X = df.iloc[:, :-1].values
y = df.iloc[:, -1].values

# Split data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)


# ラベルエンコーダーの作成
le = LabelEncoder()
y_train_encoded = le.fit_transform(y_train)
y_test_encoded = le.transform(y_test)

# モデルの作成と学習
model = DecisionTreeClassifier(random_state=42)
model.fit(X_train, y_train_encoded)

# 推論と評価
y_pred = model.predict(X_test)
print('Accuracy:', accuracy_score(y_test_encoded, y_pred))
print('F1 Score:', f1_score(y_test_encoded, y_pred, average='micro'))

# 混同行列の表示
cm = confusion_matrix(y_test_encoded, y_pred)
sns.heatmap(cm, annot=True, cmap='Blues')
plt.savefig('confusion_matrix.png')

# dtreevizでの要因分析
feature_names = ['sepal length', 'sepal width', 'petal length', 'petal width']

viz = dtreeviz.model(
    model, X_train, y_train_encoded, 
    target_name='class',
    feature_names=feature_names, 
    class_names=list(le.classes_)
)
viz_view = viz.view() 
viz_view.save("decision_tree.svg")
svg2png(url="decision_tree.svg", write_to="decision_tree.png")


# graphvizでの要因分析
dot_data = export_graphviz(model, 
                           out_file=None, 
                           feature_names=feature_names,
                           class_names=list(le.classes_), 
                           filled=True)

graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_png("tree.png")

  事前確認として動作チェックしました。正常終了したため作成されたファイルはすべて手動で削除します。

[Terminal]
python model.py

[OUT]
Accuracy: 1.0
F1 Score: 1.0

9-3.requirements.txtの作成

 ライブラリをインストールするために”requirements.txt”を準備します。

[requirements.txt]
pandas
scikit-learn
matplotlib
seaborn
dtreeviz
cairosvg
pydotplus

9-4.Dockerfileの作成

 Dockerfileを作成します。一部のコマンドを紹介します。

【メモ】
 欲張ってdtreevizとgraphvizを使用しようとしたせいでRUNコマンドが鬼畜になってしまいました。

  • dtreeviz:APIの変更、cairosvgパッケージをインストールするためにlibcairo2、libgirepository1.0-dev、pkg-config、python3-dev、gir1.2-gtk-3.0をインストール

  • Graphviz:"findfont: Font family 'Arial' not found."エラーが消えない。

【コマンドの説明】

  1. FROM python:3.8-slim-buster:ベースとなる Dockerイメージを指定

    • Pythonのバージョン3.8

    • Debian Busterのスリムバージョン(必要最小限のパッケージのみ)

  2. RUN pip install --upgrade pip:イメージ作成時に実行するコマンド 

    • コンテナ内でpipをアップグレードする命令を実行

    • pipはPythonのパッケージマネージャーで、これを最新版に保つことで更新をスムーズに実施

  3. WORKDIR /app: コンテナ内の作業ディレクトリを設定

    • /appディレクトリが作業ディレクトリになる

    • Dockerfile内の後続の命令(例えば、COPYRUNなど)は、このディレクトリを基準に実行される

  4. COPY . /app: ホストマシンの現在のディレクトリ(Dockerfileが存在するディレクトリ)のすべてのファイルとディレクトリ(.がこれを表す)をコンテナ内の/appディレクトリにコピー

  5. RUN pip install -r requirements.txt:

    • コンテナ内でrequirements.txt指定のライブラリをインストール

  6. CMD ["python", "model.py"]:コンテナが起動時に実行するコマンド

    • python model.pyコマンドが実行されmodel.pyスクリプトが実行

[DOckerfile]
FROM python:3.8-slim-buster

RUN apt-get update && apt-get install -y \
    libcairo2 \
    libgirepository1.0-dev \
    pkg-config \
    python3-dev \
    gir1.2-gtk-3.0 \
    libpango1.0-dev \
    fonts-liberation \
    graphviz  # <- Graphvizをインストールする行を追加

WORKDIR /app

COPY . /app

RUN pip install --upgrade pip
RUN pip install -r requirements.txt

CMD ["python", "model.py"]

9-5.イメージ作成/コンテナ起動

 下記コマンドでdockerイメージを作成します。

[Terminal]
docker build -t iris_model .

 下記コマンドでDockerコンテナを作成・起動します。CMD指定でPythonスクリプトが実行されるため出力も合わせて確認できました。
 またオプションとして"-v"のボリュームマウントを使用しております。結果として1.Dockerfileにiris.dataの記載が無くても学習しており、2.出力画像もコンテナでなくローカルPC側に出力されることを確認しました。

[Terminal]
docker run -v ${PWD}:/app iris_model
[Out]
Accuracy: 1.0
F1 Score: 1.0

参考資料

あとがき

 一応会社でやれば「Docker使えます!!」って言っていいのかな・・・・・

 


この記事が気に入ったらサポートをしてみませんか?