😆

公式Dockerイメージ × uvで作るローカルKaggle環境

に公開

はじめに

サイバーエージェント26卒内定者 Advent Calendarの8日目の記事です。

本記事では、私がKaggleコンペで使用しているローカル環境(Ubuntu + Docker + uv)の構築手順を紹介します。

コンテナを10回以上破壊・再構築してたどりついた「現状の運用」です。ベストプラクティスとは限りませんが、環境構築で沼にハマっている方の助けになれば幸いです。 もしより良い方法があれば、ぜひコメントで教えてください。

この記事で伝えたいこと

  • Dockerを用いた Kaggleローカル環境構築 手順

  • コンペごとのライブラリを uv で管理する際のハマりポイントと回避策

前提

Kaggleでは「ローカルで学習 → Kaggle Notebookで推論」というフローが一般的です。この際、ローカルとKaggle上の環境差異による推論エラーを防ぐため、Kaggle公式のDockerイメージを利用するのが定石です。

しかし、これには以下の課題があります。

解決したい課題

  1. コンペごとにコンテナを立て直すのは手間: コンペごとに GitHubの設定、コーディングエージェントの設定などを毎回やり直すのは面倒です。また、コンテナ間のデータのやり取りも手間です。

  2. 1コンテナを使い回すと環境の管理が難しい: 1つのコンテナにあらゆるライブラリを追加していくと、依存関係が競合します。例えば「LLMコンペ」と「画像コンペ」のライブラリが干渉し、ベース環境が破壊されるリスクがあります。

課題を解決する技術・手法

この課題に対し、私は以下の構成で対応しています。

「Kaggle公式コンテナを1つだけ常駐させ、内部で uv を使い『システムパッケージを継承した軽量な仮想環境』をプロジェクトごとに切る」


公式Dockerイメージ × uvで作るローカルKaggle環境 (Nano Banana Proで作成)

実行環境

ホストマシン

  • OS: Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-92-generic x86_64)
  • Memory: 256GB

補足:
厳密には MacBook Pro から SSH で上記マシンに接続して開発を行っています。

手順1: Kaggle公式コンテナの準備

Kaggle公式リポジトリからGPU版のイメージをプルします。
プルには時間がかかるので気長に待ちましょう。

docker pull gcr.io/kaggle-gpu-images/python:latest

※Docker未導入の場合は先に公式ドキュメント を参照してインストールしておいてください。

手順2: コンテナの起動

コンテナ起動には、私は以下のコマンドを使っています。

docker run -itd \
  --gpus all \
  --shm-size=32g \
  -v ~/program:/root/program \
  -v /data:/data \
  --name kaggle \
  gcr.io/kaggle-gpu-images/python:latest \
  /bin/bash

各引数の解説:

  • --gpus all: コンテナ内からホストのGPUを認識させるために必須です。

  • --shm-size=32g: 共有メモリのサイズ指定です。

    • デフォルト(64MB)のままだと、PyTorchのDataLoaderでデータを読み込む際にメモリ不足となり落ちることがあります。(--ipc=host も使えるらしい?)
  • -v ~/program:/root/program: コード置き場のマウント。

    • ホスト側の ~/program をコンテナ内の /root/program に同期します。こうすることで、コンテナを削除してもコードは消えませんし、コンテナ外からも編集可能です。コンテナの移行も楽になります。
  • -v /data:/data: データセット置き場のマウント。

    • HDDなどの大容量領域をマウントします。Kaggleのデータセットは巨大なので、コンテナ内部に保存せず、外部ストレージを使うといいと思います。
  • --name kaggle: コンテナに名前をつけます。なんでもよいですが、今回はkaggleとしました。

コンテナへの接続:

# 基本的な接続
docker attach kaggle
# 抜けるときは `Ctrl+P` -> `Ctrl+Q` でデタッチ(コンテナを生かしたまま抜ける)

※ exit コマンドで抜けるとコンテナが停止してしまいます。もし exit で抜けたい場合は、以下のように exec で新しいプロセスとして入るのがいいと思います。

docker exec -it kaggle /bin/bash

これで、ターミナルやVSCodeからKaggle環境を使えるようになりました!

手順3: uvによる仮想環境の構築

コンテナのベース環境(PyTorch等)を活かしつつ、コンペ固有の差分だけを管理するため、uv で仮想環境を作成します。

プロジェクトのルートディレクトリで以下を実行してください。 (uvが未インストールの場合は公式ドキュメントを参照してインストールしてください)

# プロジェクトの初期化
uv init

# コンテナのパッケージを継承してvenv作成(重要!)
uv venv .venv --system-site-packages 

# アクティベート
source .venv/bin/activate

手順4: パッケージ追加時の注意点

パッケージを追加する際は、必ず --python .venv を付けてインストール先を明示してください。

uv add numpy --python .venv

アクティベート状態であっても、uv がベース環境のパッケージを上書きしてしまうケースがあるためです。

実際に、このオプションなしで vllm をインストールした際、コンテナ自体の PyTorch が勝手にバージョンアップされ(2.6→2.7)、環境が壊れた経験があります。事故防止のため、常に .venv を指定するのが無難です。

環境の再現

uv.lock から環境を再構築する uv sync の際も、ベース環境への干渉を防ぐために一応 .venv を指定することをおすすめします。

# 最初にベース環境を継承
uv venv .venv --system-site-packages 

# アクティベート
source .venv/bin/activate

# 環境再現 .venvを指定しておく
uv sync --python .venv

まとめ

完璧ではありませんが、「環境構築の手間」と「ライブラリ管理のしやすさ」 のバランスを取る運用として、現在はこれに落ち着いています。

大事な点:

  1. データとコードは -v でホスト側に置く。

  2. --shm-size を必ず指定する(例: 8g など)

  3. uv venv --system-site-packagesでベース環境を引き継ぐ

  4. 追加インストールは uv add {lib} --python .venv で行う。

おわりに

本記事では、私がKaggleコンペに参加する際に使用しているローカル環境の構築手順をご紹介しました。

Kaggleのローカル環境を公式Docker 環境にしてから、環境関連のストレスがかなり減りました。学習したモデルが推論で動かない!という悲劇が起こらなくなったので...

もし「もっと良い構成があるよ」という知見をお持ちの方は、ぜひコメント等で教えていただけると嬉しいです。

それでは、よきKaggleライフを!

参考記事

https://zenn.dev/yuto_mo/articles/d261e96f35986a

Discussion