containers-internals について
Linux コンテナーの内部構造を Agent 向けに解説するガイドです。隔離、リソース制御、ストレージ、安全対策をコマンドやコード例とともに扱い、デバッグやランタイム開発、ワークロードの保護に役立ちます。
主な機能
- 01Linux 名前空間とプロセス隔離
- 02cgroups v2 のリソース制限
- 03overlayfs と OCI ランタイム
- 04seccomp、ケーパビリティ、脱出対策
- 05コンテナー障害の調査例
活用シーン
- 01コンテナーの OOM や CPU 制限の調査
- 02サンドボックス用 seccomp プロファイルの作成
- 03Docker を使わない最小コンテナーの構築
- 04コンテナー脱出リスクの調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill containers-internalsインストール後、Claude Code で/containers-internalsを入力して読み込まれたか確認します。
詳細
コンテナーの内部構造
目的
Linux コンテナーの内部構造についてエージェントをガイドします。名前空間(clone、unshare、nsenter)、cgroups v2 のリソース制限、overlayfs ストレージ、runc と OCI ランタイム仕様、seccomp-bpf フィルタリング、権限を落とすための Linux ケーパビリティ、コンテナーエスケープの緩和策を扱います。
使用する場面
- Docker/Podman が内部でプロセスをどのように分離するか理解するとき
- コンテナーのリソース制限(OOM、CPU スロットリング)をデバッグするとき
- サンドボックス化されたワークロード向けにカスタム seccomp プロファイルを作成するとき
- Docker を使わずに最小限のコンテナーを構築するとき
- コンテナーエスケープの脆弱性を調査するとき
- Kubernetes ポッド向けに cgroups v2 を調整するとき
ワークフロー
1. 名前空間
# List namespaces for a process
ls -la /proc/self/ns/
readlink /proc/self/ns/pid
readlink /proc/1234/ns/net
# Enter container namespaces
nsenter -t <pid> -m -u -i -n -p bash
# Unshare namespaces (manual container)
unshare --fork --mount-proc --pid --net --uts --ipc bash
| 名前空間 | 分離する対象 |
|---|---|
CLONE_NEWNS(マウント) | マウントポイント、ファイルシステムのルート |
CLONE_NEWPID | プロセス ID |
CLONE_NEWNET | ネットワークスタック |
CLONE_NEWUTS | ホスト名 |
CLONE_NEWIPC | SysV IPC、POSIX メッセージキュー |
CLONE_NEWUSER | UID/GID のマッピング |
CLONE_NEWCGROUP | cgroup のルートビュー |
// clone() with namespaces
#define _GNU_SOURCE
#include <sched.h>
int container_init(void *arg) {
sethostname("container", 9);
mount("proc", "/proc", "proc", 0, NULL);
execv("/bin/sh", (char *[]){"/bin/sh", NULL});
return 1;
}
int stack[1024 * 1024];
clone(container_init, stack + sizeof(stack)/sizeof(int),
CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET | SIGCHLD, NULL);
2. cgroups v2
# Unified hierarchy (cgroup v2)
mount -t cgroup2 none /sys/fs/cgroup
# Create cgroup and set limits
mkdir /sys/fs/cgroup/mycontainer
echo $$ > /sys/fs/cgroup/mycontainer/cgroup.procs
# Memory limit 256MB
echo 256M > /sys/fs/cgroup/mycontainer/memory.max
# CPU weight (relative to siblings, default 100)
echo 50 > /sys/fs/cgroup/mycontainer/cpu.weight
# IO weight
echo default 100 > /sys/fs/cgroup/mycontainer/io.weight
# Check current cgroup
cat /proc/self/cgroup
# OOM events
cat /sys/fs/cgroup/mycontainer/memory.events
3. overlayfs
overlayfs layers
├── lowerdir (read-only image layers)
├── upperdir (container writes)
├── workdir (internal bookkeeping)
└── merged (mount point seen by container)
mount -t overlay overlay \
-o lowerdir=lower1:lower2,upperdir=upper,workdir=work \
merged
# Docker stores layers in /var/lib/docker/overlay2/
コピーオンライト:読み取りは lower から行い、書き込みは upper に行います。
4. runc と OCI 仕様
# Generate default OCI config
mkdir -p mycontainer/rootfs
runc spec
# Edit config.json — namespaces, mounts, process args
# Run container
sudo runc run mycontainer
# List
runc list
config.json の主なセクション:
{
"ociVersion": "1.0.2",
"process": {
"args": ["/bin/sh"],
"capabilities": { "bounding": ["CAP_NET_BIND_SERVICE"] }
},
"linux": {
"namespaces": [
{"type": "pid"}, {"type": "network"}, {"type": "mount"}
],
"seccomp": { ... },
"resources": {
"memory": { "limit": 268435456 }
}
},
"root": { "path": "rootfs", "readonly": false }
}
5. seccomp-bpf
// libseccomp example — block mount
#include <seccomp.h>
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mount), 0);
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(pivot_root), 0);
seccomp_load(ctx);
# Docker default seccomp profile (JSON)
# https://github.com/moby/moby/blob/master/profiles/seccomp/default.json
# Audit blocked syscalls
# kernel: seccomp log via auditd
ausearch -m SECCOMP
| アクション | 効果 |
|---|---|
SCMP_ACT_KILL | プロセスを終了 |
SCMP_ACT_ERRNO(n) | エラーを返す |
SCMP_ACT_TRACE | トレーサーに通知 |
SCMP_ACT_ALLOW | システムコールを許可 |
6. Linux ケーパビリティ
# Drop all caps except needed
capsh --drop=all --add=net_bind_service -- -c '/app/server'
# File capabilities
setcap cap_net_bind_service+ep /usr/bin/myserver
getcap /usr/bin/myserver
コンテナーでは、Docker のデフォルト設定により CAP_SYS_ADMIN、CAP_NET_RAW などが削除されます。root 以外のユーザーで実行し、バウンディングセットを最小限にします。
7. ユーザー名前空間による rootless 実行
# Rootless podman/docker maps root in container to unprivileged UID on host
cat /proc/self/uid_map
# 0 1000 1
# container UID 0 → host UID 1000
rootless 実行の制限:ほとんどのファイルシステムをマウントできず、CAP_SYS_ADMIN もありません。
8. エスケープの緩和策
Defense layers
├── User namespace (rootless)
├── seccomp (block dangerous syscalls)
├── AppArmor/SELinux (MAC)
├── Capabilities drop (--cap-drop=ALL)
├── Read-only rootfs
├── no-new-privileges
└── Seccomp + Landlock for filesystem
docker run --read-only --cap-drop=ALL --security-opt=no-new-privileges \
--security-opt seccomp=default.json myimage
既知のエスケープ経路:マウントされた docker.sock、特権モード、カーネル CVE、/proc の情報漏えい。
よくある問題
| 症状 | 原因 | 対処 |
|---|---|---|
| コンテナーが OOMKilled になる | memory.max を超過 | 上限を引き上げるか、メモリーリークを修正 |
| CPU がスロットリングされる | cpu.max のクォータが低い | cpu.max または weight を調整 |
| コンテナー内で権限が拒否される | ケーパビリティが削除されている | 個別のケーパビリティを追加するか、アプリを修正 |
| 起動時に seccomp がプロセスを終了する | プロファイルにシステムコールが不足 | strace で特定し、システムコールを許可 |
| overlay のマウントに失敗する | workdir が空ではない | workdir をクリーンアップし、権限を確認 |
| rootless のマウントに失敗する | ユーザー名前空間の制限 | ホストからボリュームをマウント |
関連スキル
skills/virtualization/qemu-kvm— VM の分離とコンテナーの比較skills/security/kernel-security— SELinux、AppArmor、seccomp の詳細skills/observability/ebpf— コンテナーのシステムコールをトレースskills/runtimes/binary-hardening— 本番環境における seccomp とケーパビリティskills/kernel/kernel-internals— カーネルにおける cgroups と名前空間skills/profilers/strace-ltrace— seccomp 調整のためのシステムコールトレース
コメント
Markdown 対応