はじめに
Dockerは、アプリケーションをコンテナという単位でパッケージ化して動かすためのツールです。「はじめてのClaude Code」「はじめてのCodex」に続く、「はじめての〇〇シリーズ」第3弾です。
前回までのAIエージェント2本は「開発を加速する道具」でした。今回のDockerは「開発環境そのものを管理する道具」です。AIエージェントを使いこなすにも、Dockerの知識があると一段上のレベルに進めます。
開発 ・ 研究室あるある、こんな経験ありませんか?
あるある① — 先輩のコードが動かない
先輩が卒業前に残してくれたPythonコード。python main.py で動かしたら SyntaxError の嵐。原因はPythonのバージョンが違うだけ。先輩はPython 3.9で書いていたのに、自分のMacにはPython 3.12が入っていた。
あるある② — pip installしたら別のライブラリが壊れた
「このライブラリが必要です」と言われて pip install したら、他のプロジェクトで使っていたライブラリのバージョンが勝手に変わって動かなくなった。直そうとして pip install を繰り返すと、さらにカオスに。
あるある③ — サーバーで「docker psしろ」と言われて固まる
研究室のGPUサーバーを使わせてもらうことになった。先輩に「とりあえず docker ps して」と言われたけど、Dockerって何? ターミナルに打ち込んでも何が表示されているのかわからない。
この3つに共通する根本原因は、「環境が人や場所によって違う」ことです。Dockerはこの問題を解決します。
Dockerとは? — 「レシピ付きの箱」
Dockerを一言でたとえると、レシピ付きの箱です。
- 箱(コンテナ) — アプリケーションと、それが動くのに必要なもの(Python、ライブラリ、設定ファイルなど)が全部入っている
- レシピ(Dockerfile) — その箱の作り方が書いてある。誰がどのPCで作っても、同じ箱ができる
つまり、先輩のコードに Dockerfile が付いていれば、Pythonのバージョン違いで悩むことはありません。レシピ通りに箱を作れば、先輩と同じ環境が一瞬で再現されるからです。
仮想マシンとの違い
「環境をまるごとパッケージにする」という意味では**仮想マシン(VM)**と似ていますが、大きな違いがあります。
| 仮想マシン (VM) | Docker コンテナ | |
|---|---|---|
| たとえ | PC丸ごとのコピー | 必要なものだけ入った箱 |
| 起動時間 | 数分 | 数秒 |
| サイズ | 数GB〜数十GB | 数十MB〜数百MB |
| OS | ゲストOSが丸ごと必要 | ホストOSのカーネルを共有 |
| 用途 | OS自体の検証など | アプリの実行環境 |
ポイント: Dockerコンテナは仮想マシンと違ってOSを丸ごとコピーしないので、軽くて速い。研究用途では、ほとんどの場面でDockerの方が適しています。
この記事で作る環境
この記事では、Macでの基本操作(記事の70%)から研究室GPUサーバーでの活用(30%)まで、レベル別に解説します。前回の記事でターミナルの基本は覚えた前提で進めます。
| レベル | 内容 | できるようになること |
|---|---|---|
| Lv.1 | インストール | DockerがMacで動く |
| Lv.2 | 既存イメージを動かす | 公開イメージを使える |
| Lv.3 | Dockerfileを書く | 自分のアプリをコンテナ化できる |
| Lv.4 | Docker Compose | 複数コンテナをまとめて管理できる |
| Lv.5 | GPUサーバー | 研究室サーバーでDockerが使える |
Lv.3まで理解すれば、日常の開発で困ることはほぼなくなります。Lv.5まで到達すれば、研究室のGPUサーバーで先輩に「Docker使えるんだね」と言われるレベルです。
それでは、Lv.1から始めましょう。
Lv.1 — Docker Desktop のインストールと動作確認
Docker Desktop をインストールする
MacにDockerを入れるには、Docker Desktopというアプリをインストールします。方法は2つあります。
方法A:Homebrew でインストール(おすすめ)
前回の記事でNode.jsをインストールしたときにHomebrew を使いましたね。同じ要領で、ターミナルに以下を打つだけです。
brew install --cask docker
--cask って何? Homebrewには、コマンドラインツールを入れる brew install と、GUIアプリを入れる brew install --cask の2種類があります。Docker Desktopはアプリなので --cask を付けます。
インストールが終わると、アプリケーションフォルダに Docker.app が追加されます。
方法B:公式サイトからダウンロード
Homebrewを使っていない場合は、公式サイトからインストーラをダウンロードできます。
- Docker公式サイト にアクセス
- 「Download for Mac — Apple Silicon」 をクリック(M1/M2/M3/M4 Macの場合)
- ダウンロードした
.dmgファイルを開いて、Docker.app をアプリケーションフォルダにドラッグ
Intel Macの場合は「Download for Mac — Intel Chip」を選んでください。自分のMacがどちらかわからない場合は、画面左上の → 「このMacについて」でチップの欄を確認できます。「Apple M〇」と書いてあればApple Siliconです。
利用規約について
Docker Desktopは個人利用・教育目的・小規模企業(従業員250人未満かつ年間売上1000万ドル未満)では無料です。大学の研究や個人の学習で使う分には、料金を気にする必要はありません。
初回起動と設定
インストールが終わったら、Docker Desktopを起動しましょう。
- アプリケーションフォルダから Docker.app をダブルクリック(またはSpotlightで「Docker」を検索)
- 初回起動時に**利用規約(Service Agreement)**が表示されるので、内容を確認して Accept をクリック
- セットアップが始まります
初回起動は少し時間がかかります。 Docker Desktopが内部でLinuxの仮想環境を準備するため、1〜2分ほど待つことがあります。
セットアップが完了すると、画面上部のメニューバーにクジラのアイコン 🐳 が表示されます。このクジラが元気に泳いでいれば(アニメーションが止まれば)、Dockerが正常に起動しているサインです。
動作確認
ターミナルを開いて、Dockerが正しくインストールされたか確認しましょう。
バージョンの確認
docker --version
以下のように表示されればOKです(バージョン番号は異なっていて構いません)。
Docker version 28.1.1, build 4eba377
hello-world を動かしてみる
Dockerの世界にも「Hello, World!」があります。以下のコマンドを実行してみましょう。
docker run hello-world
初回実行時は、以下のような出力が表示されます。
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
e6590344b1a5: Pull complete
Digest: sha256:...
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
この出力を1行ずつ見ていきましょう。
| 出力 | 意味 |
|---|---|
Unable to find image 'hello-world:latest' locally |
「hello-world」というイメージが自分のPC(ローカル)に見つからなかった |
latest: Pulling from library/hello-world |
Docker Hubという公開サイトからイメージをダウンロード(pull)している |
Pull complete |
ダウンロード完了 |
Hello from Docker! |
コンテナが起動して、メッセージを表示した |
2回目以降は Unable to find image... と Pulling... は表示されません。 イメージが既にローカルに保存されているため、ダウンロードをスキップしてすぐにコンテナが起動します。
つまり、docker run hello-world は以下の3つを自動でやってくれたわけです。
- イメージを探す — ローカルになければDocker Hubからダウンロード
- コンテナを作る — イメージからコンテナを作成
- コンテナを実行する — コンテナの中のプログラムを動かす
たった1行のコマンドで、ここまで自動化されているのがDockerの便利なところです。
基本用語の整理
ここまでに出てきた用語を整理しておきましょう。Docker独自の用語が多いですが、料理のたとえで考えるとわかりやすくなります。
| 用語 | 意味 | たとえ |
|---|---|---|
| イメージ | コンテナの設計図。OS・ライブラリ・アプリをまとめたもの | レシピ |
| コンテナ | イメージから作った実行環境。実際に動くもの | レシピから作った料理 |
| Docker Hub | イメージが公開・共有されているサイト | レシピサイト(クックパッドのようなもの) |
| Dockerfile | イメージの作り方を書いたファイル | 自作レシピ |
イメージとコンテナの関係がピンとこない場合は、こう考えてみてください。イメージ(レシピ)は何度でも使い回せて、1つのイメージから複数のコンテナ(料理)を作れます。レシピ自体は食べられないけど、レシピから作った料理は食べられる。コンテナもイメージから作って初めて「動く」のです。
ここまでできれば、Lv.1は完了です。Dockerがあなたのmacで動く状態になりました。次のLv.2では、Docker Hubに公開されている便利なイメージを使って、もう少し実用的なことをやってみましょう。
Lv.2 — 既存イメージを使ってみよう
Lv.1で「hello-world」を動かしましたが、あれは動作確認用のミニマムなイメージでした。Dockerの本当の便利さは、世界中の人が公開しているイメージをそのまま使えるところにあります。
Docker Hub — イメージの宝庫
Lv.1の用語整理で「Docker Hub=レシピサイト」と紹介しました。ここでもう少し詳しく見てみましょう。
Docker Hub は、Dockerイメージが公開・共有されている公式のレジストリ(倉庫)です。ブラウザで開いて、検索バーにキーワードを入れるだけで、膨大な数のイメージを探せます。
たとえば、検索バーに python と入力してみてください。検索結果の一番上に、「Docker Official Image」 というバッジが付いたイメージが表示されるはずです。
「Docker Official Image」バッジが付いているイメージは信頼できます。 Docker社が公式にレビュー・メンテナンスしているイメージで、セキュリティアップデートも定期的に行われています。初心者のうちは、このバッジが付いたイメージを選ぶようにしましょう。
よく使われるOfficial Imageをいくつか紹介します。
| イメージ名 | 内容 | 使いどころ |
|---|---|---|
| nginx | 高性能なWebサーバー | Webサイトの公開、リバースプロキシ |
| python | Python実行環境 | Pythonスクリプトの実行、機械学習 |
| node | Node.js実行環境 | JavaScriptアプリの開発・実行 |
| postgres | PostgreSQLデータベース | データの保存・管理 |
| redis | インメモリデータストア | キャッシュ、セッション管理 |
| ubuntu | Ubuntu Linux | Linux環境が必要なとき全般 |
これらはすべて docker run イメージ名 で動かせます。では、実際にやってみましょう。
nginx を動かしてみよう
nginx(エンジンエックス) は、世界中のWebサイトで使われている超有名なWebサーバーです。これをDockerで動かして、ブラウザでアクセスしてみましょう。
ターミナルで以下のコマンドを実行してください。
docker run -d -p 8080:80 nginx
初回はイメージのダウンロードが入るので少し待ちます。完了すると、長い文字列(コンテナID)が表示されます。
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
...
Status: Downloaded newer image for nginx:latest
a1b2c3d4e5f6...(コンテナID)
これでnginxがバックグラウンドで動いています。ブラウザを開いて、以下のURLにアクセスしてみてください。
「Welcome to nginx!」 というページが表示されれば成功です! たった1行のコマンドで、Webサーバーが立ち上がりました。
コマンドのオプションを理解しよう
docker run -d -p 8080:80 nginx の各パーツを分解してみましょう。
| パーツ | 意味 |
|---|---|
docker run |
イメージからコンテナを作って実行する |
-d |
detached(デタッチド)モード。バックグラウンドで動かす。これを付けないと、ターミナルがnginxのログ表示に占有されてしまう |
-p 8080:80 |
ポートマッピング。ホスト(Mac)の8080番ポートを、コンテナの80番ポートに転送する |
nginx |
使用するイメージの名前 |
-p 8080:80 のポートマッピングをもう少し詳しく。 コンテナは「箱」なので、そのままでは外(Mac)からアクセスできません。-p ホスト側:コンテナ側 と書くことで、「Macの8080番ポートに来たアクセスを、コンテナの80番ポートに転送してね」という設定ができます。nginxはコンテナの中で80番ポートを使っているので、Macのブラウザからは8080番ポートでアクセスする、という仕組みです。ホスト側のポート番号は好きな数字に変えられます(例:-p 3000:80 なら http://localhost:3000 でアクセス)。
コンテナの操作コマンド一覧
nginxが動いている状態で、コンテナを管理するための基本コマンドを覚えましょう。
| コマンド | 意味 | 使いどころ |
|---|---|---|
docker ps |
動いているコンテナを一覧表示 | 「今なにが動いてる?」を確認 |
docker ps -a |
停止中も含めてすべてのコンテナを一覧表示 | 「前に作ったコンテナどこいった?」を確認 |
docker stop <コンテナID> |
コンテナを停止 | 使い終わったコンテナを止める |
docker rm <コンテナID> |
コンテナを削除 | 不要なコンテナを片付ける |
docker logs <コンテナID> |
コンテナのログを表示 | エラーが起きたときの調査 |
docker exec -it <コンテナID> bash |
動いているコンテナの中に入る | コンテナ内部の状態を確認・操作 |
コンテナIDは全部打たなくてOK。 docker ps で表示されるコンテナIDは長い文字列ですが、先頭の数文字だけで指定できます。たとえばIDが a1b2c3d4e5f6 なら、docker stop a1b のように先頭3〜4文字で十分です。他のコンテナと区別できればOK。
実際にやってみましょう。
# 動いているコンテナを確認
docker ps
# nginxのログを見る(コンテナIDは自分の環境に合わせて)
docker logs a1b
# nginxを停止
docker stop a1b
# 停止したコンテナも含めて確認
docker ps -a
# コンテナを削除
docker rm a1b
Python をインタラクティブモードで動かす
次は、Pythonの実行環境をDockerで動かしてみましょう。今度は -d(バックグラウンド)ではなく、対話的に操作します。
docker run -it python:3.12 python
実行すると、見慣れたPythonの対話モード(REPL)が起動します。
Python 3.12.x (main, ...) ...
Type "help", "copyright", "credits" or "license" for more information.
>>>
普通にPythonが使えます。試しに何か打ってみましょう。
>>> print("Hello from Docker!")
Hello from Docker!
>>> 1 + 1
2
>>> exit()
exit() を入力すると、Pythonが終了してコンテナも停止します。
-it オプションの意味
| オプション | 正式名 | 意味 |
|---|---|---|
-i |
--interactive |
標準入力(キーボード入力)をコンテナに接続する |
-t |
--tty |
仮想ターミナルを割り当てる(表示をきれいにする) |
この2つを合わせて -it と書きます。「コンテナの中で対話できるようにする」ためのオプションです。
-d と -it の使い分け
-
-d(detached) — Webサーバーやデータベースなど、裏で動き続けるものに使う。ターミナルを占有しない -
-it(interactive + tty) — PythonのREPLやbashなど、自分で操作したいものに使う。コンテナの中に入って対話する
迷ったら「自分がキーボードで操作する必要があるか?」で判断してください。操作するなら -it、放置して動かすなら -d です。
ここまでで、Docker Hubからイメージを探して、コンテナを動かして、操作する一連の流れを体験しました。Lv.2はこれで完了です。次のLv.3では、いよいよ自分だけのイメージをDockerfileで作る方法を学びます。
Lv.3 — Dockerfileで自分のイメージを作ろう
なぜ自分でDockerfileを書くのか
Lv.2では、Docker Hubにある既存のイメージ(NginxやPython)をそのまま使いました。でも実際の開発では、自分のアプリを動かしたいですよね。そのためには、自分でイメージを作る必要があります。
Dockerfileを書くということは、自分のアプリを**「レシピ化」**するということです。レシピがあれば、誰のPCでも同じ環境で同じアプリが動きます。先輩のコードを引き継いだ後輩も、研究室のサーバーでも、まったく同じ手順で動かせます。
簡単なFlaskアプリをコンテナ化してみよう
ここでは、PythonのFlaskというWebフレームワークを使って、超シンプルなWebアプリを作り、それをDockerでコンテナ化します。
まず、適当なフォルダを作って、その中に3つのファイルを用意しましょう。
mkdir my-flask-app
cd my-flask-app
① app.py — アプリ本体
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello from Docker!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
たった数行のWebアプリです。ブラウザでアクセスすると「Hello from Docker!」と表示します。
② requirements.txt — 必要なライブラリ一覧
flask
Pythonで使うライブラリを1行ずつ書きます。今回は flask だけです。
③ Dockerfile — イメージのレシピ
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
これがDockerfileです。1行ずつ見ていきましょう。
| 命令 | 意味 |
|---|---|
FROM python:3.12-slim |
ベースイメージを指定する。python:3.12-slim は軽量版のPython 3.12が入ったイメージ |
WORKDIR /app |
コンテナ内の作業ディレクトリを /app に設定する。以降のコマンドはここで実行される |
COPY requirements.txt . |
ホスト(自分のPC)の requirements.txt をコンテナの /app にコピーする |
RUN pip install -r requirements.txt |
ビルド時にライブラリをインストールする |
COPY . . |
残りのファイル(app.py など)をすべてコンテナにコピーする |
CMD ["python", "app.py"] |
コンテナを起動したときに実行するコマンドを指定する |
なぜ requirements.txt を先にCOPYするの?
Dockerはビルド時にレイヤーキャッシュという仕組みを使います。ファイルに変更がなければ、そのステップの結果をキャッシュから再利用して高速にビルドできます。
requirements.txt を先にコピーして pip install すると、ライブラリに変更がない限りインストール済みのキャッシュがそのまま使われます。app.py のコードを変更するたびにライブラリを再インストールせずに済むので、ビルド時間が大幅に短縮されます。
ビルドして動かす
3つのファイルが揃ったら、いよいよイメージをビルドしてコンテナを動かしましょう。
ステップ1:イメージをビルドする
docker build -t my-flask-app .
| 部分 | 意味 |
|---|---|
docker build |
Dockerfileからイメージをビルドする |
-t my-flask-app |
イメージに my-flask-app というタグ名を付ける(-t は tag の略) |
. |
Dockerfileがある場所(カレントディレクトリ)を指定する |
ビルドが始まると、Dockerfileの各行が順番に実行されていきます。初回はライブラリのダウンロードがあるので少し時間がかかりますが、2回目以降はキャッシュが効いて高速です。
ステップ2:コンテナを起動する
docker run -d -p 5000:5000 my-flask-app
Lv.2で学んだ -d(バックグラウンド実行)と -p(ポート転送)をここでも使います。5000:5000 は「ホストの5000番ポートをコンテナの5000番ポートに転送する」という意味でしたね。
ステップ3:ブラウザで確認する
ブラウザを開いて、以下のURLにアクセスしてみましょう。
http://localhost:5000
画面に 「Hello from Docker!」 と表示されたら成功です!自分で書いたアプリが、Dockerコンテナの中で動いています。
確認できたらコンテナを停止しておきましょう。
docker ps # コンテナIDを確認
docker stop <コンテナID> # コンテナを停止
よくあるトラブルと知っておきたいこと
① .dockerignore を用意しよう
COPY . . はカレントディレクトリのすべてのファイルをコンテナにコピーします。.git フォルダや __pycache__、.env(秘密情報)など、コンテナに不要なファイルまでコピーされてしまいます。
.dockerignore というファイルを作って、不要なファイルを指定しておきましょう。.gitignore と同じ書き方です。
.git
__pycache__
*.pyc
.env
② ビルドキャッシュに注意
Dockerは変更がないレイヤーをキャッシュから再利用して高速にビルドします。これは普段は便利ですが、まれにキャッシュが原因で古い状態のままビルドされることがあります。
「コードを変更したのに反映されない」と感じたら、以下のコマンドでキャッシュを無視してビルドし直しましょう。
docker build --no-cache -t my-flask-app .
お片付け — 不要なイメージやコンテナを削除する
Dockerを使い続けると、停止したコンテナや使わなくなったイメージがどんどん溜まっていきます。ディスク容量を圧迫するので、ときどきお掃除しましょう。
docker system prune
このコマンドを実行すると、停止中のコンテナ・使われていないネットワーク・**タグなしイメージ(dangling images)**をまとめて削除してくれます。確認メッセージが出るので y を入力すればOKです。
もっと強力にお掃除したい場合は docker system prune -a を使うと、使われていないイメージもすべて削除します。ただし、次回 docker build や docker run の際に再ダウンロードが必要になるので注意してください。
ここまでで、Dockerfileを書いて自分のアプリをコンテナ化する流れを一通り体験しました。Lv.3はこれで完了です。次のLv.4では、Docker Composeを使って複数のコンテナを連携させる方法を学びます。
Lv.4 — Docker Composeで複数コンテナを連携させよう
なぜDocker Composeが必要か
Lv.3ではコンテナ1つだけでアプリを動かしました。でも実際のアプリケーションは、複数のサービスで構成されることがほとんどです。たとえば:
- Webサーバー(Flask, Django, Node.js など)
- データベース(MySQL, PostgreSQL, Redis など)
- キャッシュサーバー(Redis, Memcached など)
これらを全部 docker run で1つずつ起動すると、こうなります:
# 毎回これを全部打つの?
docker run -d --name redis redis:alpine
docker run -d --name web --link redis -p 5000:5000 my-flask-app
コンテナが2つならまだ何とかなりますが、3つ、4つと増えていくと面倒だし、打ち間違えやすいですよね。
Docker Composeは、この問題を解決してくれるツールです。複数のコンテナの構成を1つのファイル(compose.yaml)にまとめて、コマンド1つで一括起動・一括停止ができます。
Docker Composeは追加インストール不要です。 Docker Desktopをインストールした時点で、docker compose コマンドはすでに使えます(Lv.1でインストール済み)。
Flask + Redis のアクセスカウンターを作ろう
Lv.3ではFlaskで「Hello, Docker!」を表示しましたが、今回はRedisというデータベースと連携して、ページが何回表示されたかをカウントするアプリを作ります。
まず、新しいフォルダを作って移動しましょう。
mkdir ~/flask-redis-app
cd ~/flask-redis-app
以下の4つのファイルを用意します。
① app.py — Flaskアプリ本体
from flask import Flask
import redis
app = Flask(__name__)
cache = redis.Redis(host="redis", port=6379)
@app.route("/")
def hello():
count = cache.incr("hits")
return f"このページは {count} 回表示されました!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
-
redis.Redis(host="redis", ...)の"redis"はサービス名です(後で説明します) -
cache.incr("hits")で、hitsというキーの値を1ずつ増やしています
② requirements.txt — Pythonライブラリの一覧
flask
redis
③ Dockerfile — イメージの作り方(Lv.3とほぼ同じ)
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Lv.3で学んだDockerfileとまったく同じ構成です。requirements.txt に redis が追加されただけですね。
④ compose.yaml — Docker Composeの設定ファイル
services:
web:
build: .
ports:
- "5000:5000"
depends_on:
- redis
redis:
image: redis:alpine
これがDocker Composeの設定ファイルです。たったこれだけで、2つのコンテナの構成を定義できます。
各項目の意味を表で確認しましょう。
| 項目 | 意味 |
|---|---|
services |
起動するコンテナ(サービス)をまとめて定義するセクション |
web |
サービス名(自分で自由に決められる) |
build: . |
カレントディレクトリの Dockerfile を使ってイメージをビルドする |
ports: - "5000:5000" |
ホストの5000番ポートをコンテナの5000番ポートに接続する |
depends_on: - redis |
redis サービスが先に起動してから web を起動する |
redis |
2つ目のサービス名 |
image: redis:alpine |
Docker Hub の redis:alpine イメージをそのまま使う |
host="redis" がなぜ動くのか?
Docker Composeは、定義されたサービス同士を自動的にネットワークで繋いでくれます。しかも、サービス名がそのままホスト名として使えます。だから redis.Redis(host="redis", ...) と書くだけで、redis サービスのコンテナに接続できるのです。IPアドレスを調べる必要はありません。
compose.yaml と docker-compose.yml の違い
昔のDocker Compose(v1)では docker-compose.yml というファイル名が使われていました。現在のDocker Compose v2では compose.yaml が推奨されています。ただし、docker-compose.yml も引き続き使えるので、古い記事やチュートリアルで見かけても混乱しないでください。
動かしてみよう
4つのファイルが揃ったら、compose.yaml があるディレクトリで次のコマンドを実行します。
docker compose up -d
-d はバックグラウンドで起動するオプションです(Lv.2で使った docker run -d と同じ意味)。初回はイメージのビルドとダウンロードが行われるので、少し時間がかかります。
起動したら、ブラウザで http://localhost:5000 を開いてみましょう。
このページは 1 回表示されました!
ページをリロードするたびにカウントが増えていきます。 FlaskアプリとRedisが連携している証拠です。
コンテナの状態を確認してみましょう。
docker compose ps
web と redis の2つのコンテナが running になっていれば成功です。
Composeの基本コマンド
Docker Composeでよく使うコマンドを表にまとめます。
| コマンド | 意味 |
|---|---|
docker compose up -d |
全コンテナをバックグラウンドで起動 |
docker compose down |
全コンテナを停止&削除 |
docker compose ps |
コンテナの一覧と状態を表示 |
docker compose logs |
全サービスのログをまとめて表示 |
docker compose logs -f web |
特定サービスのログをリアルタイムで表示 |
-f はfollow(追跡)の意味です。 ログがリアルタイムに流れるので、エラーの原因を調べるときに便利です。Ctrl + C で抜けられます。
遊び終わったら、コンテナを停止&削除しましょう。
docker compose down
これで web と redis の両方のコンテナが停止・削除されます。コマンド1つで片付くのがComposeの便利なところです。
ボリューム — コンテナのデータを永続化する
ここで1つ問題があります。docker compose down を実行すると、Redisに保存されていたカウンターのデータも消えてしまいます。 試しにもう一度 docker compose up -d してブラウザを開くと、カウントが1に戻っているはずです。
これは、コンテナが削除されるとコンテナ内のデータもすべて消えるからです。
この問題を解決するのが**ボリューム(volumes)**です。ボリュームを使うと、データをコンテナの外(ホストマシン上)に保存できるので、コンテナを削除してもデータが残ります。
compose.yaml にボリュームを追加してみましょう。
services:
web:
build: .
ports:
- "5000:5000"
depends_on:
- redis
redis:
image: redis:alpine
volumes:
- redis-data:/data
volumes:
redis-data:
変更点は2つだけです:
-
redisサービスにvolumes: - redis-data:/dataを追加 —redis-dataという名前のボリュームを、コンテナ内の/dataにマウント(接続)する - ファイル末尾に
volumes: redis-data:を追加 — ボリュームの定義
これで docker compose down → docker compose up -d してもカウントがリセットされなくなります。
docker compose down -v を使うとボリュームも削除されます。 データを残したい場合は -v を付けないように注意してください。
ここまでで、Docker Composeを使って複数のコンテナを連携させる方法を学びました。Lv.4はこれで完了です。次のLv.5では、GPUサーバーでのDockerの使い方を学びます。
Lv.5 — 研究室のGPUサーバーでDockerを使おう
ここまではMacのDocker Desktopで学んできました。いよいよ、研究室のGPUサーバーでDockerを使います。
GPUサーバーでは、PyTorchやvLLMといったGPU向けの機械学習フレームワークがDockerコンテナとして動いています。大規模なモデルの学習や推論は、MacではなくGPUサーバーで行うのが一般的です。
GPUサーバーにSSHで接続する
「はじめてのClaude Code」で学んだSSH接続を使って、サーバーに繋ぎます。
ssh username@server-address
ログインできたら、まずDockerが使える状態か確認しましょう。
docker --version
Docker version 28.5.1, build xxxxxxxxxxxx
バージョンが表示されればOKです。
GPUサーバーのDockerは管理者がセットアップ済みです。 Lv.1でインストールしたDocker Desktopとは違い、サーバーにはDocker Engine(LinuxネイティブのDocker)が入っています。自分でインストールする必要はありません。
サーバーで動いているコンテナを見る
GPUサーバーでは、自分だけでなく他の研究室メンバーもDockerを使っていることがあります。まずは何が動いているか確認してみましょう。
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0c7d9c582f3e nvcr.io/nvidia/pytorch:25.12-py3 "/opt/nvidia/nvidia_…" 12 days ago Up 3 days 6006/tcp, 8888/tcp nemotron_train
見慣れない部分がありますね。順番に見ていきましょう:
-
IMAGE が
nvcr.io/nvidia/pytorch:25.12-py3— これはNVIDIAが提供するGPU用の公式PyTorchイメージです。Docker Hubのpython:3.12-slimのように、nvcr.ioというレジストリから取得されています -
PORTS に
6006/tcp, 8888/tcp— TensorBoardやJupyter Notebookのポートです。GPUで学習しながらブラウザで結果を確認する、という使い方ですね -
NAMES が
nemotron_train— 誰かがモデルの学習を実行中です
次に、サーバーにダウンロード済みのイメージも見てみましょう。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nvcr.io/nvidia/vllm 26.02-py3 1f992bc7f8cc 5 weeks ago 14.7GB
nvcr.io/nvidia/pytorch 25.12-py3 edda8a492f5b 3 months ago 19.7GB
サイズが14GB〜19GBもあります! Lv.2で使った python:3.12-slim は50MB程度でしたよね。GPU用のイメージがこんなに大きいのは、CUDAライブラリ(GPUを動かすためのNVIDIA製ソフトウェア)やフレームワーク本体が丸ごと含まれているためです。
nvcr.io/nvidia/... はNVIDIAが提供するGPU最適化イメージです。 Docker Hubの一般的なイメージと違い、GPU用のドライバやライブラリが最初から組み込まれています。自分でCUDAをインストールする必要がないので、GPU環境のセットアップが圧倒的に楽になります。
NGC(NVIDIA GPU Cloud)— GPUイメージのカタログ
nvcr.io のイメージは、NGC(NVIDIA GPU Cloud) というサービスで公開されています。
NGC カタログ: https://catalog.ngc.nvidia.com/
NGCは、いわばDocker HubのNVIDIA版です。GPU用に最適化されたコンテナイメージが多数公開されています。
| カタログ | 特徴 | 代表的なイメージ |
|---|---|---|
| Docker Hub | 汎用。あらゆるソフトウェア |
python, node, redis, nginx
|
| NGC | GPU特化。NVIDIA公式 |
pytorch, tensorflow, vllm, tritonserver
|
研究でGPUを使うなら、NGCのイメージを使うのが定番です。PyTorch、TensorFlow、vLLM(大規模言語モデルの推論エンジン)など、GPU向けの主要フレームワークのイメージがすべて揃っています。
GPUが使えることを確認する
サーバーのGPUがDockerから使えるか確認してみましょう。以下のコマンドを実行してください。
docker run --rm --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi
このコマンドには見慣れないオプションがあります:
-
--rm— コンテナの実行が終わったら自動的に削除する。使い捨ての確認用コンテナに便利 -
--gpus all— ホストマシンのGPUをコンテナの中から見えるようにする。これがGPUサーバーならではのオプション
成功すると、nvidia-smi の出力が表示されます:
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.124.06 Driver Version: 570.124.06 CUDA Version: 13.0 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
|=========================================+========================+======================|
| 0 NVIDIA Graphics Device On | 00000009:01:00.0 Off | 0 |
| N/A 44C P0 22W / 100W | 0MiB / 122880MiB | 0% Default |
+-----------------------------------------+------------------------+----------------------+
GPUの名前、ドライバのバージョン、メモリ容量などが表示されれば成功です。コンテナの中からGPUが見えているということです。
nvidia-smi でエラーが出た場合は、管理者に相談してください。 このコマンドが動くのは、管理者がNVIDIA Container Toolkit(DockerからGPUを使えるようにするツール)をサーバーにセットアップ済みだからです。自分で解決しようとせず、「docker run --gpus all でエラーが出ます」と伝えればOKです。
MacとGPUサーバーの違いまとめ
ここまでの内容を表で整理しておきましょう。
| 項目 | Mac (Docker Desktop) | GPUサーバー |
|---|---|---|
| Docker本体 | Docker Desktop | Docker Engine |
| GPU | 使えない |
--gpus all で使える |
| 管理 | 自分で管理 | 管理者が管理 |
| 用途 | 開発・テスト | 学習・推論の本番実行 |
| イメージの取得元 | Docker Hub | Docker Hub + NGC |
MacのDocker Desktopは開発やテストの場、GPUサーバーは本番の学習・推論の場と使い分けるのが基本です。Lv.1〜4で学んだDockerの知識は、そのままGPUサーバーでも活きます。docker ps、docker images、docker run — コマンドは同じです。違うのはGPUが使えることとイメージのサイズ・取得元だけです。
まとめ — Dockerでできるようになったこと
この記事を通して、以下のことができるようになりました。振り返りチェックリストで確認してみましょう。
-
Lv.1: Docker DesktopをMacにインストールして
hello-worldを動かした - Lv.2: Docker Hubからnginxやpythonのイメージを取得して動かした
- Lv.3: Dockerfileを書いて自分のFlaskアプリをコンテナ化した
- Lv.4: Docker Composeで複数コンテナ(Flask + Redis)をまとめて管理した
- Lv.5: 研究室のGPUサーバーでDockerコンテナとGPUの動作を確認した
Lv.1の「とりあえず動かしてみる」から始めて、Lv.5では研究室のGPUサーバーでコンテナを動かすところまで来ました。ここまでできれば、研究で「Dockerで環境を作って」と言われても、もう怖くありません。
次に学ぶとよいこと
Dockerの基本はこの記事でカバーしました。さらにステップアップしたい人は、以下のトピックに挑戦してみてください。
- マルチステージビルド — イメージサイズを劇的に小さくするテクニック。本番用イメージを軽量に保てます。
- Docker ネットワーク — コンテナ間の通信をより細かく制御。マイクロサービス的な構成で役立ちます。
- CI/CD連携 — GitHub Actionsなどでビルド・テスト・デプロイを自動化。研究コードの再現性が格段に上がります。
- Kubernetes — 大規模なコンテナ管理のためのオーケストレーションツール。研究室レベルでは不要なことが多いですが、知っておくとキャリアの幅が広がります。
シリーズの他の記事
「はじめての〇〇」シリーズでは、研究室の新入生が最初につまずきやすいツールを、ゼロから丁寧に解説しています。
シリーズは今後も追加予定です。お楽しみに!
