はじめに
前回は、Docker Composeで作ったContainerを一度削除し、docker compose up から環境を再構築しました。
ここまでで、
- ImageからContainerを作る
- DockerfileからImageをBuildする
- Docker Composeで複数Containerを管理する
- Volumeでデータを永続化する
- Containerを削除して再構築する
というDockerの基本的な流れを試してきました。
今回は少し視点を変えて、
動いているContainerの中で何が起きているのか調べる
ことをテーマにします。
Dockerを実際に運用していると、
「Containerは起動しているのにWebページが表示されない」
「アプリケーションでエラーが出ている」
「Containerの中を確認したい」
といった場面が出てきます。
そんなときに使うのが、
docker compose psdocker compose logsdocker compose execdocker inspectdocker statsdocker top
などのコマンドです。
今回もRaspberry Pi上で動かしているFlask + Redis環境を使って確認していきます。
今回の環境
現在はDocker Composeで、次の2つのContainerを動かしています。
Webブラウザ
|
| :8080
v
+---------+
| Flask |
+---------+
|
| redis:6379
v
+---------+
| Redis |
+---------+
FlaskからRedisへ接続し、Webページを表示するたびにカウンターが増える構成です。
まずContainerの状態を確認します。
sudo docker compose ps
Docker Composeで起動しているサービスの状態を一覧で確認できます。
docker compose psでContainerの状態を確認する
Dockerを触っていて、
「Containerって今動いているの?」
と思ったら、まず確認したいのがpsです。
sudo docker compose ps
ここでは、
- Container名
- 使用しているImage
- 起動状態
- 公開Port
などを確認できます。
STATUSが、
Up
となっていればContainerは動作しています。
逆にContainerが停止していれば、ここから異常に気付くことができます。
Dockerのトラブル調査では、
まず ps で状態を見る
という流れを覚えておくと便利そうです。
docker compose logsでログを見る
Containerが起動していても、中のアプリケーションが正常に動いているとは限りません。
そこでログを確認します。
sudo docker compose logs web
Flaskのログが表示されます。
ブラウザからアクセスすると、
GET / HTTP/1.1
のようなアクセスログを確認できます。
場合によっては、
GET /favicon.ico HTTP/1.1" 404
のようなログも表示されます。
最初は、
「404が出ている。アプリが壊れた?」
と思ってしまいますが、これはブラウザがWebサイトのアイコンであるfavicon.icoを取得しようとして、ファイルが存在しなかっただけです。
つまり、ログにエラーらしい表示があったとしても、
何のリクエストで発生したのかを見ることが重要
ということが分かりました。
ログをリアルタイムで見る
ログはリアルタイムで追いかけることもできます。
sudo docker compose logs -f web
-fはfollowの意味です。
この状態でブラウザからFlaskへアクセスすると、新しいログがその場で追加されていきます。
ブラウザ
|
| HTTPアクセス
v
Flask Container
|
v
docker compose logs -f
アプリケーションの動作確認やトラブル調査では、かなり便利なコマンドです。
終了するときは、
Ctrl + C
です。
Container自体が停止するわけではなく、ログの表示を終了するだけです。
docker compose execでContainerの中に入る
次はContainerの中を直接確認してみます。
sudo docker compose exec web sh
すると、シェルの表示が変わりました。
Container内部のシェルを操作している状態です。
まず現在のディレクトリを確認します。
pwd
今回のDockerfileでは、
WORKDIR /app
と設定しているため、
/app
となります。
ファイルも確認できます。
ls
Dockerfileでコピーした、
app.py
requirements.txt
などが存在していることを確認できます。
Dockerfileに書いた内容が、実際にContainer内部のファイルシステムを作っていることが分かります。
ContainerのPythonを確認する
Containerの中で、
python --version
を実行してみます。
今回使用しているImageは、
FROM python:3.13-slim
なので、Container内部にはPython 3.13系が入っています。
ここで重要なのは、
ContainerはホストOSとは別のユーザー空間を持っている
という点です。
Raspberry Pi本体に入っているPython環境を直接使っているわけではありません。
Docker Imageに用意された環境の中でFlaskが動いています。
slim Imageにはコマンドが少ない
Container内でプロセスを確認しようとして、
ps
を実行してみました。
しかし、今回のContainerではpsが使えませんでした。
これは、
FROM python:3.13-slim
のslim Imageを使用しているためです。
slim系のImageは、必要最低限のパッケージだけを入れてImageサイズを小さくしています。
そのため、
Linuxなら当然ありそうなコマンド
が入っていないことがあります。
Containerの中に入れば普通のLinux環境が全部揃っている、というわけではないことが分かりました。
Containerは仮想マシンなのか?
ここでDockerを勉強し始めたときに疑問だったことを確認しました。
Containerは小さな仮想マシンなのか?
完全な仮想マシンとは仕組みが異なります。
Docker Containerは、ホストのLinux Kernelを共有しています。
イメージとしては、
Raspberry Pi
|
+-- Linux Kernel
| |
| +-- Flask Container
| |
| +-- Redis Container
|
+-- Raspberry Pi上の通常プロセス
という構造です。
仮想マシンの場合は、それぞれが独自のOS Kernelを持つ構成になりますが、ContainerはホストのKernelを利用します。
そのためDocker Containerは比較的軽量に起動できます。
docker inspectでContainerの詳細を見る
次はContainerの設定を詳しく調べます。
まずContainer名を確認します。
sudo docker ps
今回のWeb Containerは、
docker-lab-web-1
です。
詳細情報を表示します。
sudo docker inspect docker-lab-web-1
かなり大量のJSONが表示されます。
inspectでは、
- Containerの状態
- Image
- 環境変数
- Network
- IPアドレス
- Port
- Mount
- 起動コマンド
など、Containerに関する詳細な情報を確認できます。
ContainerのIPアドレスを見る
docker inspectを見ると、ContainerにはDocker Network内部のIPアドレスが割り当てられていることが分かります。
例えば、
172.18.x.x
のようなアドレスです。
つまり、
Raspberry Pi
192.168.1.x
Docker Network
172.18.x.x
のように、Dockerは内部に独自のNetworkを作っています。
ただしDocker Composeでは、通常このIPアドレスを直接指定する必要はありません。
今回FlaskからRedisへは、
redis.Redis(host="redis", port=6379)
としていました。
redisというComposeのサービス名を使って通信できます。
ContainerのIPアドレスは再作成などで変わる可能性があるため、サービス名で通信できる仕組みは非常に便利です。
docker statsでリソース使用量を見る
次はContainerがどれくらいCPUやメモリを使っているか確認します。
sudo docker stats
次のような項目がリアルタイムで表示されます。
CONTAINER
CPU %
MEM USAGE / LIMIT
NET I/O
BLOCK I/O
PIDS
ブラウザからFlaskへアクセスすると、Network I/Oなどの数値が変化することも確認できます。
docker statsは、
Containerが異常にCPUを使っていないか
などを調べるときに便利です。
終了するときは、
Ctrl + C
です。
今回のRaspberry Pi環境では、メモリ使用量が、
0B / 0B
のように表示されることもありました。
これは「Containerがメモリをまったく使っていない」という意味ではなく、環境によってDockerがメモリ関連の値を取得・表示できない場合があるためです。
表示された数字だけを見るのではなく、
その値が本当に取得できているのか
にも注意する必要がありそうです。
docker topでContainerのプロセスを見る
Container内にはpsコマンドがありませんでした。
しかし、ホスト側からContainer内のプロセスを確認することができます。
sudo docker top docker-lab-web-1
Web Containerでは、
python app.py
が動いていることを確認できました。
Redisも確認します。
sudo docker top docker-lab-redis-1
こちらでは、
redis-server *:6379
が動いていました。
ここで、
Container
=
その中で動いているプロセス
というDockerの仕組みが少し見えてきます。
Containerのプロセスはホストからも見える
さらに面白かったのが、ContainerのプロセスをRaspberry Pi側からも確認できたことです。
docker topで表示されたプロセスにはPIDがあります。
そのPIDをホスト側から確認すると、Container内で動いているプロセスをRaspberry Pi側からも見ることができます。
つまり、
Flask Container
|
+-- python app.py
|
v
Raspberry PiのLinux Kernelから見ても
実際に存在するプロセス
ということです。
Containerの中に「完全に別のコンピューター」が存在しているわけではありません。
Linux Kernelが持つ隔離機能を使って、
- プロセス
- Network
- ファイルシステム
- その他のリソース
などを分離して、Containerとして見せています。
ここはDockerを理解するうえでかなり重要なポイントでした。
logs・exec・inspect・statsの使い分け
今回使ったコマンドを整理します。
| コマンド | 用途 |
|---|---|
docker compose ps |
Containerの起動状態を見る |
docker compose logs |
ログを見る |
docker compose logs -f |
ログをリアルタイムで見る |
docker compose exec |
Container内でコマンドを実行する |
docker inspect |
Containerの詳細設定を見る |
docker stats |
CPU・メモリ・Networkなどを見る |
docker top |
Containerで動いているプロセスを見る |
例えばWebアプリが動かなくなったときは、
docker compose ps
|
v
Containerは起動している?
|
v
docker compose logs
|
v
エラーは出ている?
|
v
docker compose exec
|
v
Container内部を確認
|
v
docker inspect / stats / top
|
v
設定・Network・リソース・プロセスを確認
という流れで調査できます。
今回理解できたこと
今回の実験で、Containerを「起動する」だけでなく、「調べる」方法が分かりました。
特に重要だったのは、
Container = 小さな仮想マシン
と単純に考えるのではなく、
Container
=
Linux Kernelの機能によって隔離されたプロセスとその実行環境
として考えることです。
Dockerfileで環境を作り、
Docker ComposeでContainer同士を接続し、
Volumeでデータを残し、
今回のコマンドで動作状態を調べる。
これまで別々に試してきたDockerの機能が、少しずつつながってきました。
まとめ
今回はDocker Containerの状態を調べるために、
docker compose ps
docker compose logs
docker compose logs -f
docker compose exec
docker inspect
docker stats
docker top
を試しました。
Dockerを使ううえでは、
Containerを起動できることだけでなく、問題が起きたときに中で何が起きているのか調べられること
も重要だと分かりました。
また、Container内部のプロセスがRaspberry PiのLinux Kernel上で実際に動いていることを確認したことで、
Docker Containerは完全な仮想マシンではない
ということも実感できました。
次回は、ここまで作ってきたDocker環境から少し発展して、実際に使えるサービスをContainerとして動かしてみます。
Uptime KumaをDocker Composeで構築し、Raspberry Pi上で動いているサービスを監視してみます。