Slide 1

Slide 1 text

1 Container for Research Yuki Iwazaki@chck | AI Lab Press Space for next page AI Lab Skill Up Onboarding 2024

Slide 2

Slide 2 text

1 Prerequisites

Slide 3

Slide 3 text

1 Yuki Iwazaki @ chck 2014 … Backend Engineer in DSP 2017 … ML / DS in Ad Platform 2018 … Research Engineer in AI Lab github.com/chck Research Engineer | Applied ML

Slide 4

Slide 4 text

1 Why Container?

Slide 5

Slide 5 text

1 Today’s Goal コンテナ技術を使った実験環境の作成・共有・デバッグ方法を知る 話さないこと: コンテナ技術を前提としたクラウドサービスの使い方

Slide 6

Slide 6 text

1 What is Container? A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.[1] JupyterLab, Flask, MySQL, Original App macOS, Windows, Linux MacBook, ThinkPad, GCE, EC2 -----> ------> ------>

Slide 7

Slide 7 text

1 Why Container? ○: Isolated Environment & Better Portability インフラ層以上の依存 (OS, Libraries, Apps ∈ Docker) を Container に閉じ込めることで、 環境の違いによる問題を回避できる[1] ○: Reproducibility 研究コードを動かすための長く複雑な手順をContainerで隠蔽できる[2] Containerを前提としたクラウドサービスと連携することで効率の良い実験が回せる ✗: Over Engineered Python Packageで十分な場合、Container化はやりすぎなことも ✗: Infrastructure Matters インフラ層に依存するアプリは恩恵が受けづらい (e.g. NVIDIA GPU)

Slide 8

Slide 8 text

1 Container Ecosystem Macの場合PerformanceはQEMU (Software Emulation) < Rosetta (Hardware Acceralation)[1][2] OS Engine Runtime Linux VMs Windows macOS Linux Docker Desktop Rancher Desktop Podman Desktop Moby Containerd Podman Virtual Box HyperKit QEMU Rosetta Lima/Colima Podman machine WSL

Slide 9

Slide 9 text

1 Hands-on: Simple

Slide 10

Slide 10 text

1 Download Hands-on code ls Dockerfile poetry.lock pyproject.toml README.md src git clone https://github.com/CyberAgentAILab/skillup2024-container.git cd skillup2024-container ls .dockerignore .github 1-simple 3-withdb LICENSE .git .gitignore 2-jupyter docs README.md cd 1-simple

Slide 11

Slide 11 text

1 Case 1: 学習スクリプトをコンテナ化したい 1. Python Scriptを動かすための依存を含んだImageを作成 2. Containerの実行確認 3. DockerfileのコミットやContainer RegistryにImageをUpload コンテナ化の流れ

Slide 12

Slide 12 text

1 Docker Keywords Dockerfile It is a straightforward text file containing a collection of commands or procedures. A Dockerfile is the Docker image’s source code. Docker Image An image is a read-only template with instructions for creating a Docker container. Often, an image is based on another image, with some additional customization.[2] Docker Container Containers are compact, virtualized runtime environments used to run applications. […] including all of the configuration files, dependencies, system tools, libraries, and source code required to run a certain application. 用語の説明 [1] 1. https://cto.ai/blog/docker-image-vs-container-vs-dockerfile/

Slide 13

Slide 13 text

1 1. BaseとなるImageを決める "$keyword docker hub"で検索

Slide 14

Slide 14 text

1 1. BaseとなるImageを決める Version Tagは用途に応じて選択 依存の多い順(≒イメージサイズの大きい順): bookworm (OS Version) > slim > alpine 試しに docker pull してみる(時間がかかるので待ち時間に次スライド) docker pull python:3.11-bookworm docker pull python:3.11-slim docker pull python:3.11-alpine

Slide 15

Slide 15 text

1 !! 読み進める上での注意事項 !! ※ PythonのPackage Managerとして、この資料を公開した当時有力だったPoetryを使っていますが 2025年3月現在、uvが代替候補になっています そのため以降のhandsonで使っているPoetryの部分はuvに差し替えることをおすすめします その際、本稿では詳しく紹介しないmulti-stage buildやcache mountが登場するので 別途キャッチアップしながら使ってみましょう

Slide 16

Slide 16 text

1 2. Dockerfileを書く $EDITOR Dockerfile FROM python:3.11-slim ENV APP_HOME /app RUN apt update && apt install -y --no-install-recommends \ build-essential \ git \ && apt clean \ && rm -rf /var/lib/apt/lists/* \ && pip install -U pip && pip install --no-cache-dir poetry \ && poetry config virtualenvs.create false

Slide 17

Slide 17 text

1 2. Dockerfileを書く $EDITOR Dockerfile # Container起動時に実行するコマンドを指定 CMD ["python", "-m", "simple"] FROM python:3.11-slim [...]

Slide 18

Slide 18 text

1 3. Imageの作成 DOCKERFILEを元にIMAGEをビルド docker build . -t $(whoami)/skillup24-simple:1.0 │ │ └── イメージのタグ │ └── イメージ名 └── コンテキストの指定・COPY句の起点になるパス ローカルのIMAGE一覧を表示 docker images -/skillup24-simple 1.0 d19a531278a0 42 hours ago 677MB REPOSITORY TAG IMAGE ID CREATED SIZE python 3.11-alpine 53bb490579d2 6 days ago 64.2MB python 3.11-slim 4bc494c2b591 2 months ago 157MB python 3.11-bookworm 7b493b7d0435 2 months ago 1.01GB [...]

Slide 19

Slide 19 text

1 4. Containerの実行確認 コンテナプロセス(実行履歴)の監視 watch "docker ps -a | grep skillup24-simple" コンテナの実行( ↑とは別窓で何回か実行すると、WATCH窓にログが追加される) docker run $(whoami)/skillup24-simple:1.0 コンテナの実行(履歴を残さないのでこちらがおすすめ) docker run --rm $(whoami)/skillup24-simple:1.0 コンテナ内で実行しているコードの確認 cat src/simple/__main__.py [...] logger.info(f"Fitting {self.name} model...") [...]

Slide 20

Slide 20 text

1 Container Registry Container Imageの共有サービス。Docker社が運営しているDocker Hubの他、パブリッククラウドである GCP、AWS、Azureなどもほぼ同機能を提供している。 Docker Hub (Docker) Artifact Registry (GCP) Elastic Container Registry (AWS) Container Registry (Azure) GitHub / GitBucket / GitLab の違いのようなもので、どれを使っても似たようなことができるが、メインで使う クラウドに寄せるとクラウド内でのシナジーが高い(ベンダーロックインに注意) 用語の説明

Slide 21

Slide 21 text

1 5. ImageのUpload DockerHubから自分のアカウントのリポジトリ一覧を開いておく DOCKER HUBへアップロード docker login docker tag $(whoami)/skillup24-simple:1.0 $(DOCKER_HUB_ID)/skillup24-simple:1.0 docker images | grep skillup docker push $(DOCKER_HUB_ID)/skillup24-simple:1.0 イメージの再ダウンロード(IMAGE_ID指定でRMIするとALIAS含め指定イメージがすべて消える) docker rmi -f $(IMAGE_ID) docker pull $(DOCKER_HUB_ID)/skillup24-simple:1.0 参考:GOOGLE CONTAINER REGISTRYへアップロードする場合 gcloud auth application-default login docker tag $(whoami)/skillup24-simple:1.0 asia-northeast1-docker.pkg.dev/$(GCLOUD_PROJECT)/$(TEAM)/$(wh docker push asia-northeast1-docker.pkg.dev/$(GCLOUD_PROJECT)/$(TEAM)/$(whoami)/skillup24-simple:1.0

Slide 22

Slide 22 text

1 Tips: Image Tagは複数付与できる 数字によるバージョン管理と、latestによる最新版の上書きを併用することが一般的 イメージを参照する際もlatest指定は避ける、Python Versionで * 指定しているようなもので ある日急にアプリが動かなくなったりする SKILLUP24-SIMPLEに1.0とLATESTのタグ両方付与 docker tag $(whoami)/skillup24-simple:1.0 $(DOCKER_HUB_ID)/skillup24-simple:1.0 docker tag $(whoami)/skillup24-simple:1.0 $(DOCKER_HUB_ID)/skillup24-simple:latest DOCKER HUBへアップロード(後者のLATESTはレイヤー単位の差分検知によりバイナリは上がらずTAGが追加されるだけ) docker push $(DOCKER_HUB_ID)/skillup24-simple:1.0 docker push $(DOCKER_HUB_ID)/skillup24-simple:latest PULLでTAGを省略するとLATESTで補完される docker pull $(DOCKER_HUB_ID)/skillup24-simple ↑と同義 docker pull $(DOCKER_HUB_ID)/skillup24-simple:latest

Slide 23

Slide 23 text

1 Tips: slim vs alpine Tag Size Note bookworm large Debian v12全部入り slim medium 最小構成、curlやwgetも入っていない alpine small Debianですらない軽量Linuxディストリビューション、bashも入っていない トレードオフになるが、慣れるまではslimがおすすめ docker images | grep python python 3.11-alpine 53bb490579d2 6 days ago 64.2MB python 3.11-slim 4bc494c2b591 2 months ago 157MB python 3.11-bookworm 7b493b7d0435 2 months ago 1.01GB

Slide 24

Slide 24 text

1 Hands-on: Jupyter

Slide 25

Slide 25 text

1 Case 2: JupyterLabをコンテナ化したい 1. JupyterLabを動かすための依存を含んだImageを作成 2. Containerの実行確認 3. DockerfileのコミットやContainer RegistryにImageをUpload コンテナ化の流れ

Slide 26

Slide 26 text

1 1. Dockerfileを書く cd ../2-jupyter $EDITOR Dockerfile FROM python:3.11-slim ENV APP_HOME /app RUN apt update && apt install -y --no-install-recommends \ build-essential \ && apt clean \ && rm -rf /var/lib/apt/lists/* \ && pip install -U pip && pip install --no-cache-dir poetry \ && poetry config virtualenvs.create false

Slide 27

Slide 27 text

1 1. Dockerfileを書く cd ../2-jupyter $EDITOR Dockerfile # JupyterLabの起動コマンド(ip制限, token, passwordをオフに) CMD ["jupyter", "lab", "--allow-root", "--ip=0.0.0.0", "--no-browser", "--Ser FROM python:3.11-slim [...] # JupyterLab用のPortを開放 EXPOSE 8888

Slide 28

Slide 28 text

1 2. Imageの作成 -> compose.ymlを書く

Slide 29

Slide 29 text

1 Docker Compose Docker Compose is a tool for defining and running multi-container applications. Compose simplifies the control of your entire application stack, making it easy to manage services, networks, and volumes in a single YAML configuration file. Then, with a single command, you create and start all the services from your configuration file. docker コマンドのサブセット docker build や docker run で指定 していたオプションをYAMLに記述でき、 1コマンドで複数のイメージを作成・起 動できる 1. https://docs.docker.com/compose/ ↩︎ [1]

Slide 30

Slide 30 text

1 Docker vs Docker Compose コンテナに慣れてくると実行時オプションが増えてくる -> Docker Composeを導入することで管理が楽になる マルチコンテナ向けと記述があったが、上記のように1コンテナでも利点がある Composeで作られるイメージ・コンテナは今までの機能と同じなのでdockerコマンドと併用可能 DOCKER (参考なので実行しなくてOK) docker build . -t $(whoami)/skillup24-jupyter:1.0 --platform linux/amd64 docker run --rm -p 8888:8888 -v ${PWD}:/app --platform linux/amd64 $(who DOCKER COMPOSE (COMPOSE.YMLがある状態で) docker compose up

Slide 31

Slide 31 text

1 2. Imageの作成 -> compose.ymlを書く $EDITOR compose.yml services: jupyter: image: asia-northeast1-docker.pkg.dev/$(GCLOUD_PROJECT)/ailab-onboar build: context: . cache_from: - asia-northeast1-docker.pkg.dev/$(GCLOUD_PROJECT)/ailab-onboard ports: - "8888:8888" volumes: - ${PWD}:/app # tty: true # for debug platform: linux/amd64

Slide 32

Slide 32 text

1 2. compose.ymlを書く $EDITOR compose.yml # CPU Archの指定 (amd/arm等CPU規格依存による起動の失敗防止) platform: linux/amd64 services: jupyter: image: [...] build: [...] ports: [...] volumes: [...] # tty: true # for debug

Slide 33

Slide 33 text

1 3. Imageの作成 & Containerの実行確認 docker composeはImageの作成と実行が同時に可能 ≒ DOCKER BUILD & DOCKER RUN docker compose up COMPOSEで作成したIMAGE一覧を表示( ↑とは別窓かつ2-JUPYTER/直下で実行) docker compose images COMPOSEで実行したコンテナプロセスを表示(JUPYTERLABは自動終了しないのでWATCHは不要) docker compose ps

Slide 34

Slide 34 text

1 3. Imageの作成 & Containerの実行確認 1. コンテナとして起動したJupyterLabにアクセス 2. notebooks/train.ipynb を開いて上部メニューのRun -> Run All Cells 3. 2-jupyter/data/ 配下にファイルが出力されたことを確認 ( volumes: ${PWD}:/app オプションの効果) 起動時にvolumeオプションによってマウントしているので、ローカルのファイルがコンテナ内に同期される ここで、次の章で ↑の出力ファイルを参照するので 3-withdb/data に移しておく open http://localhost:8888 以下のコマンドはコンテナ上のJUPYTER・ローカルどちらでもOK ls data .gitkeep test.tsv train.tsv ua_classifier.bin useragent.tsv cp data/* ../3-withdb/data

Slide 35

Slide 35 text

1 User Agent (UA) Client (e.g. ブラウザ) がServerアクセス時に付与するOS等の情報をまとめた文字列 擬似的な個人情報として使えてしまうため昨今規制が厳しい 1. https://towardsdatascience.com/still-parsing-user-agent-strings-for-your-machine-learning-models-use- this-instead-8928c0e7e74f ↩︎ 今回扱っているデータについて [1]

Slide 36

Slide 36 text

1 UA Classifier Simpleな学習モデルの例として、UserAgent StringからPC or Mobileを分類するタスクを想定した

Slide 37

Slide 37 text

1 Tips: Containerのデバッグ方法 Dockerfile を動くところまででコメントアウト -> 改めて docker build docker run 時にCMDを上書きしてbashやshとして起動 コメントアウトした部分を手動で実行 -> 失敗するはずなのでエラーを読む (別パターン)既に起動中のコンテナに入る場合 ( docker compose up 等が動いている想定) 🤕 docker build や docker run が失敗した docker build [...] docker run --rm -it $(whoami)/skillup24-simple:1.0 bash pip install scipyy docker compose exec -it jupyter bash

Slide 38

Slide 38 text

1 Hands-on: With DB

Slide 39

Slide 39 text

1 Case 3: DBと連携したデモアプリをコンテナ化したい 1. デモアプリを動かすための依存を含んだImageを作成 2. Containerの実行確認 3. DockerfileのコミットやContainer RegistryにImageをUpload コンテナ化の流れ

Slide 40

Slide 40 text

1 1. Dockerfileを書く cd ../3-withdb $EDITOR Dockerfile FROM python:3.11-slim ENV APP_HOME /app ENV GRADIO_SERVER_NAME 0.0.0.0 RUN apt update && apt install -y --no-install-recommends \ build-essential \ git \ && apt clean \ && rm -rf /var/lib/apt/lists/* \ && pip install -U pip && pip install --no-cache-dir poetry \

Slide 41

Slide 41 text

1 2. compose.ymlを書く $EDITOR compose.yml services: gradio: image: asia-northeast1-docker.pkg.dev/$(GCLOUD_PROJECT)/ailab-onboarding/skillup24-withdb:1.0 build: context: . cache_from: - asia-northeast1-docker.pkg.dev/$(GCLOUD_PROJECT)/ailab-onboarding/skillup24-withdb:latest command: ["gradio", "src/withdb/__main__.py"] # auto-reloading mode for development ports: - "7860:7860" volumes: - ${PWD}:/app env_file: - env example

Slide 42

Slide 42 text

1 3. Containerの実行確認 postgresqlで使えるコマンド: \d , select * from useragent; , … DBだけ起動 docker compose up db 起動したDBにアクセス PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres withdb CONTAINERをまとめて停止 (CURRENT DIRECTORYにCOMPOSE.YMLがあることを確認) docker compose down

Slide 43

Slide 43 text

1 3. Containerの実行確認 このようにDocker Composeは複数のコンテナ (e.g. Web App & DB) の依存関係を考慮しつつ、 煩雑なコンテナの実行時オプションをYAMLに落とし込んで実行できる(もちろん単体実行も可) DBとデモアプリ(GRADIO)を起動( -D でバックグラウンド実行) docker compose up -d バックグラウンド実行時のログ確認 docker compose logs -f (CONTAINER起動までログを確認しつつ少し待ってから) デモアプリにアクセス open http://localhost:7860 CONTAINERをまとめて停止 (CURRENT DIRECTORYにCOMPOSE.YMLがあることを確認) docker compose down ローカルボリュームを圧迫するのでCONTAINER RESOURCEをまとめて掃除したい時 (定期的に叩くことを推奨)

Slide 44

Slide 44 text

1 Demo ( localhost:7860 )

Slide 45

Slide 45 text

1 DockerfileのBest Practice 1. 要らない依存は消す なるべくショートカットできるBase Imageを FROM に指定する(とはいえUnofficial Imageは要注意) ビルドの過程で作られた不要なデータは消す(e.g. wgetするけど最終的には要らないインストーラ) 2. レイヤーキャッシュを活用する Dockerfile内の命令単位 (e.g. RUN , COPY ) で差分を見ている(イメージレイヤー) 。上から順に実行されるた め、変更がない部分はビルドやpullの時間短縮になる。つまり変更されにくい処理(e.g. apt-get)を上、 変更の多い処理(e.g. requirements.txtやソースコード本体)ほど下に書くと良い。 3. マルチステージビルドを行う マルチステージビルドはビルドコンテナと実行コンテナを分離できる機能で、ビルドコンテナで作成した内容 のみを別のイメージにコピーしてしまう。ビルドで使った依存が実行時には不要な場合に有効。 主にイメージの軽量化について[1] 1. https://speakerdeck.com/devops_vtj/jin-sarawen-kenaidockerru-men-dockerfilenobesutopurakuteisubian?slide=20

Slide 46

Slide 46 text

1 時間が余った時用 Apple Silicon MacのPython開発事情 1 Image : 1 Appの理由 Container化が特にうれしい場面 ModelをStorageに持つかImageに持つか 変数によってbuildの振る舞いを変えたい時 Training/Servingは同じImageか分けるか DevContainerについて Securityの話 And more …

Slide 47

Slide 47 text

1 Thank you for listening! Questions?