Open7

Docker first step

kejitakejita

Docker Desktopの容量が大きい問題

【背景】
AI/機械学習モデルの個人開発の途中経過で、Dockerを初めて使用してみた。
ふとタスクマネージャーを開くとvmmemWSが約4MBを使用していることが判明、コンテナを実行する前なのに、、!
自分のPCのRAMは16GBなので、実行中でもないのにそんなに消費されると厳しいかも?PCのスペック問題やメモリ容量の拡張問題になるのか、、?と思い、ChatGPTに質問。

【回答】
Docker Desktop は“VMごと”動くので、何もしてなくても数 GB 食うのはわりと普通です。特に Windows(WSL2)だと vmmemWSL が 3–6GB くらい持っていくことがよくあります。
とはいえ、以下でだいぶ絞れます。

まず状況を知る

  • どれが食ってる?
    タスク マネージャーの vmmemWSL(=WSL2 の仮想マシン)や Docker Desktop 本体を見ます。

  • Docker の “中身”のサイズ感

    docker system df
    

    これで images / containers / volumes / build cache の使用量が見えます。

手早く効く節約ワザ(Windows/WSL2)

  1. WSL2 の上限を決める(最重要)

    ユーザーフォルダに C:\Users\<あなた>\.wslconfig を作成/編集:

    [wsl2]
    memory=2GB        # 上限(例: 2GB)。4GBに抑えたいなら 4GB と書く
    processors=2      # CPUコア上限(任意)
    swap=0            # スワップ切る(任意。発熱/ディスク節約)
    localhostForwarding=true
    

    反映:

    wsl --shutdown
    # その後 Docker Desktop を起動
    

    これで vmmemWSL の天井が下がります。

  2. Kubernetes を無効化

    Docker Desktop → Settings → Kubernetes → Disable。
    有効だと常にクラスターが常駐してメモリを食います。

  3. 自動起動&バックグラウンドを絞る

    • Settings → General → “Start Docker Desktop when you log in” をオフ
    • Pause when inactive” の類いがあればオン(バージョンによる)
  4. 使ってないデータを掃除

    # 止まってるコンテナ/未使用ネットワーク/未参照イメージ/ボリュームまで全部
    docker system prune -af --volumes
    
    # ビルドキャッシュも削る
    docker builder prune -af
    

    古いイメージやキャッシュが何 GB も居座っていること、よくあります。

  5. ファイル共有の最適化

    プロジェクトを WSL 側(\\wsl$ / Ubuntu のホーム配下) に置く。
    Windows ↔ WSL のファイル越境は I/O が重く、メモリ・CPU を余計に使いがち。

コンテナ単位で制限する

  • 単発起動:

    docker run --memory=512m --cpus=1 ...
    
  • Compose(Swarmを使わない前提なら、古典の mem_limit が効きやすい):

    services:
      app:
        image: your/app
        mem_limit: 512m
        cpus: 1.0
    

    deploy.resources.limits は Swarm 専用挙動なので、通常の docker compose では無視されます。

Mac の場合(参考)

Docker Desktop → Resources → CPU/Memory スライダーで直接上限を設定。Kubernetes を切り、不要データを docker system prune

“なぜ 4GB も?”のミニ解説

Docker Desktop は軽い EXE ではなく、軽量 VM(WSL2/Hypervisor)上でエンジンが走っています。WSL2 は動的メモリですが、いったん確保した分をすぐ返さない特性があり、タスクマネージャー上は大きく見えがち。上記の .wslconfig で上限を定めるのが一番確実です。


ここまでやっても 4GB 付近で張り付くなら、.wslconfigmemory=2–3GB に下げて挙動を見つつ、プロジェクト側で --memory を併用するのが現実解。

【まとめ】
セットアップすれば容量制限できそう!ということでいったん一安心。
KubernetesはOFFしました。
そもそもまだコンテナ使い始められずメモリもそこまで圧迫されていないので、いったんは様子を見て、今後調整しようと思います。
容量問題はいろいろな場面で発生すると思うので、今後も都度調べて深堀り→最適化を繰り返したいなと思いました。

kejitakejita

ちなみにのKubernetes、勝手にきゅばーねっつと読んでました。

Kubernetes(クバネティス)とは?

Google が開発し、現在は CNCF(Cloud Native Computing Foundation)が管理している コンテナオーケストレーションツール

オーケストレーションとは、「たくさんのコンテナをまとめて管理する仕組み」。
役割や目的はざっくり言うと:

  • 自動化:コンテナの起動・停止・再起動を自動でやる
  • スケーリング:トラフィックに応じてコンテナ数を増減
  • 負荷分散:アクセスを複数コンテナにうまく振り分け
  • 自己修復:落ちたコンテナを自動で再起動
  • 宣言的管理:YAMLファイルに「この状態を保って」と書けば、Kubernetesがその状態に調整してくれる

クラウドや大規模システムで「常に安定して動く環境」を作るための土台。


無効化のメリット・デメリット

観点 有効化(Kubernetesを使う) 無効化(Docker単体で運用)
リソース消費 常に数GBのメモリ・CPUを消費 軽量化(数GB節約)、PCが快適
学習/検証 Kubernetesの練習環境になる シンプル、Dockerの基本操作だけで済む
ユースケース マイクロサービスや本番想定の開発に便利 個人開発や小規模プロジェクトに十分
管理機能 自動スケーリング、自己修復、負荷分散などを利用可 コンテナの起動・停止・ネットワーク管理は自分で行う必要あり
複雑さ 設定・YAMLファイル管理が必須で学習コスト大 設定がシンプル、直感的
起動速度 Docker Desktop 起動時に Kubernetes も立ち上がるので遅め Docker Desktop の起動が速くなる

結論

  • 学習や小規模開発なら無効化でOK
    (Docker Composeで十分対応できる)
  • 将来クラウドや大規模システムに携わるなら有効化して練習もアリ
    ただしPCリソースは食う

もしあなたが今やっているのが Power BIやPython分析用の環境構築小規模アプリ検証なら、Kubernetesは無効化して大丈夫。

本番想定で「マイクロサービスを10個以上連携させたい」とか「クラウド移行の事前演習をしたい」なら有効化を考えるのが現実的。

kejitakejita

Docker container run -itについて

docker container run -it ...-it は2つのオプションの組み合わせです。

  • -i (interactive)
    標準入力(STDIN)を開いたままにします。
    これを付けないと、コンテナはすぐ終了してしまう場合があります。

  • -t (tty)
    仮想端末(ターミナル)を割り当てます。
    これにより bashsh を実行したときに、通常のシェルのように対話的に使えるようになります。

つまり -it は「標準入力を有効にした対話型ターミナルを使えるようにする」という意味。
実際にはよく次のように使われます:

docker run -it ubuntu bash

これで Ubuntu のコンテナに入って、普通にターミナル操作ができます。

逆に -it を付けないと、

  • -i がない → 標準入力を受け付けないのでシェルを触れない
  • -t がない → 画面表示が崩れたり、行編集が効かない

という違いが出ます。

要するに、-it は「コンテナを人間が直接触るモードにする魔法スイッチ」です。

kejitakejita

jupyter-notebookで機械学習モデルを構築したい場合

公式の python:*-slim をベースにして必要最小限を積み、Jupyterは“ツールの1つ”として追加する構成が最適です。
(Jupyter Stacksは便利だけど“全部入り”寄りで、依存が読みにくく、本番と差分が出やすい。)

ここからのレシピは、**再現性・軽量・非root・ローカル時差(Asia/Tokyo)**まで押さえた「本番に近い学習環境」。


最小・本番寄りの構成

1) Dockerfile

# ベースは軽量・長期利用しやすい slim 系
FROM python:3.12-slim

# 環境変数(ロケール/タイムゾーン/UTF-8)
ENV TZ=Asia/Tokyo \
    LANG=C.UTF-8 \
    LC_ALL=C.UTF-8 \
    PIP_NO_CACHE_DIR=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

# ビルドに必要な基本ツール(必要最小限)
# 数値計算系でよく要る: build-essential, git, curl
# xgboost/scikit-image等で要ることが多い: libgomp1, libgl1
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential git curl ca-certificates libgomp1 libgl1 \
  && rm -rf /var/lib/apt/lists/*

# アプリ用ユーザを作成(非root運用)
ARG USERNAME=appuser
ARG UID=1000
ARG GID=1000
RUN groupadd -g ${GID} ${USERNAME} && \
    useradd -m -s /bin/bash -u ${UID} -g ${GID} ${USERNAME}

WORKDIR /workspace

# 依存は“固定”して再現性を確保
# (requirements.txt は後述のロック手順で生成)
COPY requirements.txt .
RUN python -m pip install --upgrade pip && \
    pip install -r requirements.txt

# JupyterLab は“開発用ツール”として明示的に追加
RUN pip install jupyterlab==4.*

# 権限調整
RUN chown -R ${USERNAME}:${USERNAME} /workspace
USER ${USERNAME}

# Jupyter を外からアクセス可能に起動(トークンはログに出る)
EXPOSE 8888
CMD ["jupyter", "lab", "--ip=0.0.0.0", "--port=8888", "--no-browser"]

2) 依存ロック(requirements)

本番寄りにするならバージョンを固定しましょう。まずは “最小セット” を固定。

requirements.txt(例)

numpy==2.1.1
pandas==2.2.2
matplotlib==3.9.2
scikit-learn==1.5.2
scipy==1.14.1
ipykernel==6.29.5

※ 将来は uvpip-tools で lock 管理に移行するとさらに堅いです(が、まずは固定版で十分)。

3) docker-compose(開発をラクに)

# compose.yaml
services:
  lab:
    build: .
    image: my-jupyter-slim:latest
    container_name: jupyter-lab
    ports:
      - "8888:8888"
    volumes:
      - ./:/workspace  # 手元のコードをそのまま使う
    environment:
      - TZ=Asia/Tokyo
    # Windows/WSL でもそのまま動く想定

起動:

docker compose up --build

ログに出る URL(?token=... 付き)をブラウザで開けばOK。
ノートブックは .//workspace として見えます。


これで“本番に近い”理由

  • Slim + 明示的pip:余計なものがない。差分が追いやすい。
  • バージョン固定:再現性(同じコードがいつでも同じ動き)。
  • 非rootユーザ:本番コンテナの基本に合わせる。
  • 最小ネイティブ依存(libgomp1 など):科学計算ライブラリが安定。
  • Jupyterは追加ツール:アプリ本体と役割の分離が明確。

よくある拡張ポイント

  • XGBoost / LightGBM / CatBoost を入れる場合:
    requirements.txt に固定版を追記。ビルドが重いときは libgomp1 など既に対応済み。
  • OpenCV を入れる場合:opencv-python-headless==<ver> の方が軽量。
  • GPU(NVIDIA) を使う場合:
    ベースを nvidia/cuda:12.4.1-runtime-ubuntu22.04 等にして、docker run --gpus all
    そのうえで pip install cupy-cuda12xtensorflow/torch のCUDA版をロック。
  • セキュリティ:社内/共有環境では --NotebookApp.token を環境変数で管理し、--NotebookApp.password(ハッシュ)も検討。
  • Dev Containers(VS Code):上の Dockerfile を .devcontainer に流用すると、エディタ体験が爆速。

次の一手:上の3ファイル(Dockerfile / requirements.txt / compose.yaml)をそのまま置いて起動すれば、今日から“本番寄りの学習環境”で走れます。

kejitakejita

Docker Command

機能 コマンド
公式イメージを取得(Pull) docker pull <image>:<tag>
ローカルのイメージ一覧 docker images または docker image ls
使わないイメージを削除 docker image prune
イメージを削除(単体) docker rmi <image> または docker image rm <image>
イメージにタグを付ける docker tag <image> <repo>:<tag>
Dockerfile からビルド docker build -t <name>:<tag> <path>
BuildKit を使ってビルド(推奨) DOCKER_BUILDKIT=1 docker build -t <name>:<tag> <path>
イメージを保存(tar) docker save -o <file>.tar <image>:<tag>
イメージを読み込み(tar) docker load -i <file>.tar
イメージ履歴表示 docker history <image>
イメージ詳細表示 docker image inspect <image>
コンテナ起動(新規・前面) docker run --rm -it <image> <cmd>
コンテナ起動(新規・背面) docker run -d --name <ctr> <image>
ポート公開して起動 docker run -d -p <host>:<container> <image>
ボリュームをマウントして起動 docker run -d -v <host_path>:<ctr_path> <image>
環境変数を渡して起動 docker run -d -e KEY=VALUE <image>
コンテナ一覧(起動中) docker ps
コンテナ一覧(全て) docker ps -a
実行中コンテナに入る docker exec -it <ctr> /bin/bash
直近のログ出力 docker logs <ctr>
ログを追尾 docker logs -f <ctr>
コンテナ停止 docker stop <ctr>
コンテナ開始(再起動) docker start <ctr>
コンテナ再起動 docker restart <ctr>
コンテナ強制停止 docker kill <ctr>
コンテナ削除(単体) docker rm <ctr>
使わないコンテナ一括削除 docker container prune
コンテナ詳細表示 docker inspect <ctr>
コンテナのプロセス確認 docker top <ctr>
コンテナのポート確認 docker port <ctr>
リソース使用状況(全体) docker stats
ファイルをコンテナへコピー docker cp <host_path> <ctr>:<path>
ファイルをコンテナからコピー docker cp <ctr>:<path> <host_path>
コンテナをエクスポート(fs) docker export -o <file>.tar <ctr>
エクスポートからインポート docker import <file>.tar <name>:<tag>
ネットワーク一覧 docker network ls
ネットワーク作成 docker network create <net>
ネットワークに接続 docker network connect <net> <ctr>
ネットワーク切断 docker network disconnect <net> <ctr>
ネットワーク詳細 docker network inspect <net>
使わないネットワーク削除 docker network prune
ボリューム一覧 docker volume ls
ボリューム作成 docker volume create <vol>
ボリューム詳細 docker volume inspect <vol>
ボリューム削除 docker volume rm <vol>
使わないボリューム削除 docker volume prune
システム全体の容量確認 docker system df
使わないデータ一括削除 docker system prune
さらに強力に一括削除 docker system prune -a
ログイン(レジストリ) docker login
ログアウト docker logout
イメージをプッシュ docker push <repo>:<tag>
バージョン確認 docker version
システム情報 docker info
イベント監視 docker events
コンテキスト一覧 docker context ls
コンテキスト切替 docker context use <name>
Buildx(マルチアーキ)ビルド docker buildx build --platform linux/amd64,linux/arm64 -t <repo>:<tag> <path>
Compose 起動 docker compose up -d
Compose 停止・削除 docker compose down
Compose ログ docker compose logs -f
Compose 状態確認 docker compose ps
Compose でビルド docker compose build
Compose で一時実行 docker compose run --rm <service> <cmd>
Compose で exec docker compose exec <service> <cmd>
Healthcheck 確認 docker inspect --format='{{json .State.Health}}' <ctr>
OCI ランタイム設定の確認 docker inspect <ctr> --format '{{.HostConfig.Runtime}}'
名前解決の確認(/etc/hosts) docker exec <ctr> cat /etc/hosts
レジストリからの脆弱性スキャン(対応環境) docker scout cves <image>
キャッシュ無効でビルド docker build --no-cache -t <name>:<tag> <path>
ビルド引数を渡す docker build --build-arg KEY=VALUE -t <name>:<tag> <path>
マルチステージのターゲット指定 docker build --target <stage> -t <name>:<tag> <path>
コンテナの自動削除で起動 docker run --rm <image> <cmd>
名前解決/ネットワーク疎通テスト docker run --rm -it --network <net> <image> ping <host>
GPU を割り当てて起動(対応環境) docker run --gpus all <image>
再起動ポリシー付き起動 docker run -d --restart=unless-stopped <image>
ulimit 設定付き起動 docker run --ulimit nofile=65536:65536 <image>
ラベル付与(メタデータ) docker run -d --label KEY=VALUE <image>
タイムゾーンやロケールを渡す docker run -e TZ=Asia/Tokyo -e LANG=ja_JP.UTF-8 <image>
kejitakejita

-it組み込み版

機能 コマンド(改善版:-it を多用)
コンテナを新規起動して対話操作 docker run -it --rm <image> /bin/bash
既存コンテナに入る docker exec -it <ctr> /bin/bash
既存コンテナに Python で入る docker exec -it <ctr> python
対話モードでポートを公開して起動 docker run -it -p 8080:80 <image>
ホストのファイルをマウントして対話起動 docker run -it -v $(pwd):/app <image> /bin/bash
環境変数を指定して対話起動 docker run -it -e TZ=Asia/Tokyo <image> /bin/bash
ネットワーク接続をテスト(ping) docker run -it --rm --network <net> busybox ping <host>
GPU コンテナで対話起動 docker run -it --gpus all <image> nvidia-smi
Compose で対話実行 docker compose run --rm -it <service> /bin/bash
一時的なコマンド実行 docker run -it --rm <image> <cmd>
コンテナ内でシェルを差し替えて入る docker exec -it <ctr> sh
名前解決の確認 docker exec -it <ctr> cat /etc/hosts
Python スクリプトを即実行 docker run -it --rm -v $(pwd):/app -w /app python:3.11 python script.py
Jupyter Notebook を対話付きで起動 docker run -it -p 8888:8888 -v $(pwd):/app jupyter/base-notebook
Nginx をデバッグ起動 docker run -it -p 8080:80 nginx /bin/bash
kejitakejita

デタッチドモード(-d) vs フォアグラウンドモード(it)

モード メリット デメリット
デタッチドモード (-d) バックグラウンドで実行できるのでターミナルを占有しない。
サービス提供(DB, Webサーバーなど)に向いている。
docker logs -f <ctr> で後からログ確認できる。
コンテナ内に直接入れないため、操作には docker exec -it <ctr> bash が必要。
起動エラー時に気づきにくい。
フォアグラウンドモード (-it) 起動時からコンテナ内にログインできる。
標準出力/エラーを即確認できるのでデバッグ向き
シェル操作やワンショット実行がしやすい 。
ターミナルを占有する(他作業に使えない)。
ターミナル閉じるとコンテナも落ちる(--rm 付きなら即削除)。
サービス稼働には不向き。
両方が実行できる(-itd) コンテナがバックグラウンドにいるのに、docker attach すればすぐに「そのときの端末」に戻れる。(br>デバッグ中に detach (Ctrl+P, Ctrl+Q) → 再度 attach、という使い方はできる。 -d の時点で通常はログを docker logs で見ればよいので、-t -i が冗長になりがち。
attach すると他の人が同じコンテナに入っていた場合に標準入力が共有されてカオスになる。=普段のサービス稼働(DB, Web サーバーなど)には無駄。