Container Management Docker Podman
コンテナ管理 Docker/Podman 完全ガイド
目次
- はじめに
- コンテナの基本概念
- 2.1 名前空間(Namespaces)
- 2.2 cgroups(コントロールグループ)
- 2.3 ユニオンファイルシステム
- 2.4 コンテナ vs 仮想マシン
- Docker アーキテクチャ
- 3.1 Docker エンジンの構成
- 3.2 Docker デーモン
- 3.3 containerd と runc
- 3.4 Docker レジストリ
- Docker のインストール
- 4.1 RHEL/CentOS へのインストール
- 4.2 Ubuntu へのインストール
- 4.3 インストール後の設定
- Dockerfile
- 5.1 基本命令
- 5.2 マルチステージビルド
- 5.3 ベストプラクティス
- Docker コマンド詳細
- Docker Compose
- 7.1 docker-compose.yml の構造
- 7.2 実践的な構成例
- 7.3 Compose コマンド
- Docker ネットワーキング
- 8.1 ブリッジネットワーク
- 8.2 ホストネットワーク
- 8.3 オーバーレイネットワーク
- 8.4 macvlan
- Docker ボリュームとバインドマウント
- 9.1 ボリューム
- 9.2 バインドマウント
- 9.3 tmpfs マウント
- Docker セキュリティベストプラクティス
- Podman:Docker の代替
- 11.1 Podman の概要
- 11.2 デーモンレスアーキテクチャ
- 11.3 ルートレスコンテナ
- 11.4 Pod コンセプト
- 11.5 Podman コマンド
- Buildah と Skopeo
- コンテナオーケストレーション概要
- 13.1 Kubernetes 基礎
- 13.2 Docker Swarm
- トラブルシューティング
- ベストプラクティスまとめ
- 参考文献
1. はじめに
コンテナ技術は、アプリケーションの開発・デプロイ・運用において革命的な変化をもたらした。OS レベルの仮想化によって軽量で高速な分離環境を提供し、「一度ビルドすれば、どこでも動く」というポータビリティを実現する。
本ドキュメントでは、Linux コンテナの基礎技術、Docker、Podman、および関連ツールについて、基礎概念から実践的な運用ノウハウまでを網羅的に解説する。
2. コンテナの基本概念
2.1 名前空間(Namespaces)
Linux 名前空間は、プロセスが見えるシステムリソースを分離する カーネル機能である。
| 名前空間 | 分離対象 | フラグ |
|---|---|---|
| PID | プロセス ID | CLONE_NEWPID |
| NET | ネットワークスタック | CLONE_NEWNET |
| MNT | マウントポイント | CLONE_NEWNS |
| UTS | ホスト名・ドメイン名 | CLONE_NEWUTS |
| IPC | プロセス間通信 | CLONE_NEWIPC |
| USER | ユーザー/グループ ID | CLONE_NEWUSER |
| Cgroup | cgroup ルート | CLONE_NEWCGROUP |
| Time | システム時刻(Linux 5.6+) | CLONE_NEWTIME |
# コンテナの名前空間を確認
$ docker inspect --format '{{.State.Pid}}' my-container
12345
$ ls -la /proc/12345/ns/
total 0
lrwxrwxrwx 1 root root 0 Apr 10 10:00 cgroup -> 'cgroup:[4026532456]'
lrwxrwxrwx 1 root root 0 Apr 10 10:00 ipc -> 'ipc:[4026532454]'
lrwxrwxrwx 1 root root 0 Apr 10 10:00 mnt -> 'mnt:[4026532451]'
lrwxrwxrwx 1 root root 0 Apr 10 10:00 net -> 'net:[4026532457]'
lrwxrwxrwx 1 root root 0 Apr 10 10:00 pid -> 'pid:[4026532455]'
lrwxrwxrwx 1 root root 0 Apr 10 10:00 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Apr 10 10:00 uts -> 'uts:[4026532453]'
# 名前空間に入る(デバッグ用)
$ nsenter -t 12345 -m -u -i -n -p -- /bin/bash
2.2 cgroups(コントロールグループ)
cgroups はプロセスのリソース使用量を制限・監視する機能である。
# cgroups v2 の確認
$ stat -fc %T /sys/fs/cgroup/
cgroup2fs
# コンテナの cgroup 情報
$ cat /sys/fs/cgroup/system.slice/docker-<container-id>.scope/memory.max
8589934592 # 8 GiB
$ cat /sys/fs/cgroup/system.slice/docker-<container-id>.scope/cpu.max
100000 100000 # CPU 100%
# Docker でリソース制限を指定
$ docker run -d \
--memory=512m \
--memory-swap=1g \
--cpus=2.0 \
--cpu-shares=512 \
--pids-limit=100 \
--blkio-weight=300 \
nginx:latest
主要な cgroups コントローラ:
| コントローラ | 制限対象 | Docker オプション |
|---|---|---|
| memory | メモリ使用量 | --memory, --memory-swap |
| cpu | CPU 使用率 | --cpus, --cpu-shares |
| cpuset | CPU コア/メモリノード | --cpuset-cpus, --cpuset-mems |
| blkio/io | ブロック I/O | --blkio-weight, --device-read-bps |
| pids | プロセス数 | --pids-limit |
2.3 ユニオンファイルシステム
ユニオンファイルシステムは、複数のファイルシステムレイヤーを重ね合わせて一つのファイルシステムとして見せる技術である。
┌────────────────────────────┐
│ コンテナレイヤー (R/W) │ ← コンテナ固有の変更
├────────────────────────────┤
│ イメージレイヤー 3 (R/O) │ ← COPY app.jar
├────────────────────────────┤
│ イメージレイヤー 2 (R/O) │ ← RUN apt-get install
├────────────────────────────┤
│ イメージレイヤー 1 (R/O) │ ← FROM ubuntu:24.04
└────────────────────────────┘
主要なストレージドライバ:
| ドライバ | 特徴 | 推奨環境 |
|---|---|---|
| overlay2 | 標準的、高性能 | ほとんどの環境(推奨) |
| btrfs | Btrfs ファイルシステム用 | Btrfs ボリューム |
| zfs | ZFS ファイルシステム用 | ZFS ボリューム |
| devicemapper | LVM thin provisioning | RHEL 旧版 |
# 使用中のストレージドライバを確認
$ docker info | grep "Storage Driver"
Storage Driver: overlay2
2.4 コンテナ vs 仮想マシン
| 項目 | コンテナ | 仮想マシン |
|---|---|---|
| 起動時間 | 数秒 | 数十秒〜数分 |
| リソース消費 | 軽量(数 MB〜) | 重い(数百 MB〜) |
| 分離レベル | プロセスレベル | ハードウェアレベル |
| カーネル | ホストと共有 | 独自カーネル |
| ポータビリティ | 高い | 中程度 |
| セキュリティ | 中程度 | 高い |
| 密度 | 高い(数百/ホスト) | 低い(数十/ホスト) |
3. Docker アーキテクチャ
3.1 Docker エンジンの構成
┌─────────────────────────────────────────────┐
│ Docker CLI │
│ (docker コマンド) │
├─────────────────────────────────────────────┤
│ Docker API (REST) │
├─────────────────────────────────────────────┤
│ Docker Daemon (dockerd) │
│ ┌────────────┐ ┌────────────────┐ │
│ │ イメージ管理 │ │ ネットワーク管理 │ │
│ └────────────┘ └────────────────┘ │
│ ┌────────────┐ ┌────────────────┐ │
│ │ ボリューム │ │ プラグイン │ │
│ └────────────┘ └────────────────┘ │
├─────────────────────────────────────────────┤
│ containerd │
│ (コンテナランタイム管理) │
├─────────────────────────────────────────────┤
│ runc (OCI runtime) │
│ (コンテナの実行) │
├─────────────────────────────────────────────┤
│ Linux カーネル │
│ (namespaces, cgroups, seccomp) │
└─────────────────────────────────────────────┘
3.2 Docker デーモン
# Docker デーモンの設定ファイル
$ cat /etc/docker/daemon.json
{
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"default-address-pools": [
{"base": "172.17.0.0/16", "size": 24}
],
"live-restore": true,
"userland-proxy": false,
"experimental": false,
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 64000,
"Soft": 64000
}
}
}
# デーモンの再起動
$ sudo systemctl restart docker
3.3 containerd と runc
# containerd の状態確認
$ sudo systemctl status containerd
# containerd の直接操作(ctr コマンド)
$ sudo ctr images ls
$ sudo ctr containers ls
# runc の直接操作
$ runc --version
runc version 1.1.12
spec: 1.0.2-dev
3.4 Docker レジストリ
| レジストリ | URL | 特徴 |
|---|---|---|
| Docker Hub | hub.docker.com | 公式、最大のパブリックレジストリ |
| GitHub Container Registry | ghcr.io | GitHub 統合 |
| Amazon ECR | .dkr.ecr..amazonaws.com | AWS 統合 |
| Google Artifact Registry | *.pkg.dev | GCP 統合 |
| Azure Container Registry | *.azurecr.io | Azure 統合 |
| Harbor | 自己ホスト | OSS プライベートレジストリ |
4. Docker のインストール
4.1 RHEL/CentOS へのインストール
# 古いバージョンの削除
$ sudo dnf remove docker docker-client docker-client-latest \
docker-common docker-latest docker-latest-logrotate \
docker-logrotate docker-engine
# リポジトリの追加
$ sudo dnf install -y yum-utils
$ sudo yum-config-manager --add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# インストール
$ sudo dnf install docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
# サービスの起動
$ sudo systemctl enable --now docker
# 動作確認
$ sudo docker run hello-world
4.2 Ubuntu へのインストール
# 古いパッケージの削除
$ sudo apt remove docker docker-engine docker.io containerd runc
# リポジトリの設定
$ sudo apt update
$ sudo apt install ca-certificates curl gnupg
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# インストール
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
4.3 インストール後の設定
# 一般ユーザーで Docker を使用可能にする
$ sudo usermod -aG docker $USER
$ newgrp docker
# Docker の情報確認
$ docker info
Client: Docker Engine - Community
Version: 26.1.0
Context: default
Server:
Server Version: 26.1.0
Storage Driver: overlay2
Cgroup Driver: systemd
Cgroup Version: 2
Kernel Version: 6.8.0
Operating System: Rocky Linux 9.4
Architecture: x86_64
CPUs: 8
Total Memory: 31.25GiB
5. Dockerfile
5.1 基本命令
# FROM: ベースイメージの指定
FROM ubuntu:24.04
# LABEL: メタデータの付加
LABEL maintainer="admin@example.com"
LABEL version="1.0"
LABEL description="My application container"
# ENV: 環境変数の設定
ENV APP_HOME=/app \
APP_USER=appuser \
NODE_ENV=production
# ARG: ビルド時の変数(実行時には残らない)
ARG BUILD_VERSION=1.0.0
# RUN: コマンドの実行
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
ca-certificates \
python3 && \
rm -rf /var/lib/apt/lists/*
# WORKDIR: 作業ディレクトリの設定
WORKDIR ${APP_HOME}
# COPY: ファイルのコピー(ビルドコンテキストから)
COPY --chown=appuser:appuser . .
# ADD: ファイルの追加(tar 展開や URL ダウンロードも可能)
ADD https://example.com/config.tar.gz /tmp/
# USER: 実行ユーザーの変更
RUN useradd -r -s /bin/false ${APP_USER}
USER ${APP_USER}
# EXPOSE: 公開するポートの宣言
EXPOSE 8080
# VOLUME: ボリュームマウントポイントの宣言
VOLUME ["/data"]
# HEALTHCHECK: ヘルスチェックの定義
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
# ENTRYPOINT: コンテナのエントリーポイント
ENTRYPOINT ["python3"]
# CMD: デフォルトの引数(ENTRYPOINT と組み合わせ)
CMD ["app.py"]
ENTRYPOINT と CMD の違い:
| 項目 | ENTRYPOINT | CMD |
|---|---|---|
| 役割 | メインコマンド | デフォルト引数 |
| オーバーライド | --entrypoint で可能 | docker run の引数で可能 |
| 推奨用途 | 実行バイナリの指定 | デフォルトパラメータ |
# 組み合わせ例
ENTRYPOINT ["python3", "app.py"]
CMD ["--port", "8080"]
# docker run myapp → python3 app.py --port 8080
# docker run myapp --port 9090 → python3 app.py --port 9090
5.2 マルチステージビルド
# ステージ 1: ビルド環境
FROM golang:1.22-alpine AS builder
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
# ステージ 2: 実行環境(最小イメージ)
FROM alpine:3.19
RUN apk --no-cache add ca-certificates tzdata && \
adduser -D -g '' appuser
WORKDIR /app
COPY --from=builder /build/app .
USER appuser
EXPOSE 8080
ENTRYPOINT ["./app"]
# Java アプリケーションのマルチステージビルド
FROM maven:3.9-eclipse-temurin-21 AS build
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
FROM eclipse-temurin:21-jre-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=build /build/target/*.jar app.jar
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "app.jar"]
5.3 ベストプラクティス
# 1. 軽量なベースイメージを使用
FROM alpine:3.19 # 最小(~7MB)
FROM distroless/base # Google Distroless(~20MB)
FROM ubuntu:24.04 # フル機能(~78MB)
# 2. レイヤー数を最小化(RUN 命令を結合)
# 悪い例:
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean
# 良い例:
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
# 3. .dockerignore を活用
# .dockerignore ファイル
.git
node_modules
*.md
Dockerfile
docker-compose.yml
.env
# 4. 非 root ユーザーで実行
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
USER appuser
# 5. COPY を ADD より優先(明示的)
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
# 6. 固定バージョンのタグを使用
FROM python:3.12.3-slim # 良い
FROM python:latest # 悪い(予測不能)
6. Docker コマンド詳細
6.1 コンテナ操作
# コンテナの起動
$ docker run -d \
--name web-app \
--hostname web-app \
-p 8080:80 \
-v /host/data:/container/data \
-e APP_ENV=production \
--restart unless-stopped \
--memory=512m \
--cpus=1.0 \
nginx:1.25
# コンテナの一覧
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abc123def456 nginx:1.25 "/docker-entrypoint.…" 2 hours ago Up 2 hours 0.0.0.0:8080->80/tcp web-app
# コンテナの停止・起動・再起動
$ docker stop web-app
$ docker start web-app
$ docker restart web-app
# コンテナに入る
$ docker exec -it web-app /bin/bash
$ docker exec -it web-app sh # Alpine 系
# コンテナのログ
$ docker logs web-app
$ docker logs -f web-app # フォロー(リアルタイム)
$ docker logs --tail 100 web-app # 最後の100行
$ docker logs --since 1h web-app # 直近1時間
# コンテナの詳細情報
$ docker inspect web-app
$ docker inspect --format '{{.NetworkSettings.IPAddress}}' web-app
# コンテナのリソース使用状況
$ docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
abc123def456 web-app 0.05% 12.5MiB / 512MiB 2.44% 1.2kB / 0B 0B / 0B
# コンテナの削除
$ docker rm web-app
$ docker rm -f web-app # 強制削除(実行中でも)
# 停止中の全コンテナを削除
$ docker container prune
# コンテナからファイルをコピー
$ docker cp web-app:/etc/nginx/nginx.conf ./nginx.conf
$ docker cp ./index.html web-app:/usr/share/nginx/html/
6.2 イメージ操作
# イメージのビルド
$ docker build -t myapp:1.0 .
$ docker build -t myapp:1.0 -f Dockerfile.prod .
$ docker build --no-cache -t myapp:1.0 .
$ docker build --build-arg VERSION=2.0 -t myapp:2.0 .
# イメージの一覧
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myapp 1.0 sha256:abc... 2 hours ago 150MB
nginx 1.25 sha256:def... 3 days ago 187MB
# イメージの取得
$ docker pull nginx:1.25
$ docker pull ghcr.io/org/repo:tag
# イメージのプッシュ
$ docker tag myapp:1.0 registry.example.com/myapp:1.0
$ docker push registry.example.com/myapp:1.0
# イメージの削除
$ docker rmi myapp:1.0
$ docker image prune # 未使用イメージの削除
$ docker image prune -a # タグなし + 未使用の全削除
# イメージの履歴(レイヤー確認)
$ docker history myapp:1.0
IMAGE CREATED CREATED BY SIZE
abc123def456 2 hours ago CMD ["python3" "app.py"] 0B
bcd234efg567 2 hours ago COPY . . # buildkit 15.2MB
cde345fgh678 2 hours ago RUN /bin/sh -c pip install -r requirements... 45.3MB
# イメージの保存とロード
$ docker save myapp:1.0 -o myapp.tar
$ docker load -i myapp.tar
6.3 ネットワーク操作
# ネットワーク一覧
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
abc123def456 bridge bridge local
bcd234efg567 host host local
cde345fgh678 none null local
# カスタムネットワークの作成
$ docker network create \
--driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
my-network
# コンテナをネットワークに接続
$ docker network connect my-network web-app
$ docker network disconnect my-network web-app
# ネットワークの詳細
$ docker network inspect my-network
6.4 ボリューム操作
# ボリュームの作成
$ docker volume create my-data
# ボリューム一覧
$ docker volume ls
# ボリュームの詳細
$ docker volume inspect my-data
[
{
"CreatedAt": "2026-04-10T10:00:00Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-data/_data",
"Name": "my-data",
"Options": {},
"Scope": "local"
}
]
# ボリュームを使用してコンテナを起動
$ docker run -d -v my-data:/app/data myapp:1.0
# 未使用ボリュームの削除
$ docker volume prune
6.5 その他の操作
# システムの情報
$ docker info
$ docker version
# ディスク使用量
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 15 5 3.2GB 1.8GB (56%)
Containers 8 3 25MB 15MB (60%)
Local Volumes 10 4 500MB 200MB (40%)
Build Cache 20 0 800MB 800MB (100%)
# 全クリーンアップ(注意)
$ docker system prune -a --volumes
7. Docker Compose
7.1 docker-compose.yml の構造
# docker-compose.yml の基本構造
version: "3.9"
services:
# サービス定義
service-name:
image: image:tag
# または
build:
context: .
dockerfile: Dockerfile
ports:
- "host:container"
volumes:
- volume:/path
environment:
- KEY=value
depends_on:
- other-service
networks:
- my-network
restart: unless-stopped
volumes:
volume-name:
driver: local
networks:
my-network:
driver: bridge
7.2 実践的な構成例
# Web アプリケーション + データベース + キャッシュの構成
version: "3.9"
services:
# Web アプリケーション
app:
build:
context: .
dockerfile: Dockerfile
args:
- BUILD_ENV=production
container_name: myapp
ports:
- "8080:8080"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
- REDIS_URL=redis://cache:6379
- NODE_ENV=production
volumes:
- app-logs:/app/logs
- ./config:/app/config:ro
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
networks:
- frontend
- backend
restart: unless-stopped
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 256M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# PostgreSQL データベース
db:
image: postgres:16-alpine
container_name: myapp-db
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
volumes:
- db-data:/var/lib/postgresql/data
- ./init-db.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
interval: 10s
timeout: 5s
retries: 5
secrets:
- db_password
# Redis キャッシュ
cache:
image: redis:7-alpine
container_name: myapp-cache
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- cache-data:/data
networks:
- backend
restart: unless-stopped
# Nginx リバースプロキシ
nginx:
image: nginx:1.25-alpine
container_name: myapp-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- app
networks:
- frontend
restart: unless-stopped
volumes:
db-data:
driver: local
cache-data:
driver: local
app-logs:
driver: local
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true
secrets:
db_password:
file: ./secrets/db_password.txt
7.3 Compose コマンド
# サービスの起動
$ docker compose up -d
# サービスの停止
$ docker compose down
# サービスの停止(ボリュームも削除)
$ docker compose down -v
# サービスの再ビルドと起動
$ docker compose up -d --build
# 特定のサービスのみ起動
$ docker compose up -d app db
# サービスのスケーリング
$ docker compose up -d --scale app=3
# ログの表示
$ docker compose logs -f app
# サービスの状態確認
$ docker compose ps
# コンテナ内でコマンド実行
$ docker compose exec app bash
# 設定の検証
$ docker compose config
8. Docker ネットワーキング
8.1 ブリッジネットワーク
# デフォルトブリッジ(docker0)
$ docker run -d --name web1 nginx
$ docker run -d --name web2 nginx
# web1 と web2 は IP アドレスでのみ通信可能
# カスタムブリッジ(DNS サービスディスカバリ付き)
$ docker network create my-bridge
$ docker run -d --name web1 --network my-bridge nginx
$ docker run -d --name web2 --network my-bridge nginx
# web1 と web2 はコンテナ名で通信可能
# カスタムブリッジからの ping テスト
$ docker exec web1 ping web2
PING web2 (172.20.0.3): 56 data bytes
64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.089 ms
8.2 ホストネットワーク
# ホストネットワーク(ポートマッピング不要、最高性能)
$ docker run -d --name web --network host nginx
# ホストの 80 番ポートで直接アクセス可能
8.3 オーバーレイネットワーク
# Swarm モードで使用(マルチホスト通信)
$ docker network create --driver overlay --attachable my-overlay
8.4 macvlan
# macvlan ネットワーク(物理ネットワークに直接接続)
$ docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
my-macvlan
9. Docker ボリュームとバインドマウント
9.1 ボリューム
# 名前付きボリューム(推奨)
$ docker run -d -v my-data:/app/data myapp
# 匿名ボリューム
$ docker run -d -v /app/data myapp
# ボリュームのバックアップ
$ docker run --rm \
-v my-data:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/my-data-backup.tar.gz -C /source .
# ボリュームの復元
$ docker run --rm \
-v my-data:/target \
-v $(pwd):/backup \
alpine tar xzf /backup/my-data-backup.tar.gz -C /target
9.2 バインドマウント
# バインドマウント(ホストディレクトリを直接マウント)
$ docker run -d \
-v /host/path:/container/path \
-v $(pwd)/config:/app/config:ro \
myapp
# --mount 構文(より明示的)
$ docker run -d \
--mount type=bind,source=/host/data,target=/app/data,readonly \
myapp
9.3 tmpfs マウント
# tmpfs マウント(メモリ上の一時ファイルシステム)
$ docker run -d \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
myapp
10. Docker セキュリティベストプラクティス
イメージのセキュリティ
# 1. 信頼できるベースイメージを使用
FROM docker.io/library/nginx:1.25-alpine
# 2. イメージの脆弱性スキャン
$ docker scout cves myapp:1.0
$ trivy image myapp:1.0
# 3. 固定ダイジェストを使用(再現性の保証)
FROM nginx@sha256:abc123def456...
ランタイムのセキュリティ
# 非 root ユーザーで実行
$ docker run -d --user 1000:1000 myapp
# read-only ルートファイルシステム
$ docker run -d --read-only --tmpfs /tmp myapp
# capabilities の制限
$ docker run -d \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
myapp
# seccomp プロファイルの適用
$ docker run -d --security-opt seccomp=./seccomp-profile.json myapp
# no-new-privileges の設定
$ docker run -d --security-opt no-new-privileges myapp
# リソース制限
$ docker run -d \
--memory=512m \
--cpus=1.0 \
--pids-limit=100 \
myapp
ネットワークのセキュリティ
# 内部ネットワーク(外部アクセス不可)
$ docker network create --internal backend
# 特定の IP にバインド
$ docker run -d -p 127.0.0.1:8080:80 myapp
11. Podman:Docker の代替
11.1 Podman の概要
Podman (Pod Manager) は Red Hat が開発したコンテナエンジンで、Docker の代替として設計されている。
Docker との主な違い:
| 項目 | Docker | Podman |
|---|---|---|
| アーキテクチャ | クライアント-サーバー(デーモン必須) | デーモンレス |
| 実行権限 | デフォルトで root | ルートレスが標準 |
| Pod サポート | なし(Compose のみ) | ネイティブ Pod サポート |
| systemd 統合 | 限定的 | ネイティブ統合 |
| OCI 準拠 | はい | はい |
| CLI 互換性 | - | Docker CLI と互換 |
| セキュリティ | デーモンが root で動作 | fork/exec モデル |
11.2 デーモンレスアーキテクチャ
Docker: Podman:
┌──────────┐ ┌──────────┐
│ docker │ │ podman │
│ CLI │ │ CLI │
└────┬─────┘ └────┬─────┘
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│ dockerd │ (デーモン) │ conmon │ (コンテナモニタ)
└────┬─────┘ └────┬─────┘
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│containerd│ │ runc/ │
└────┬─────┘ │ crun │
│ └──────────┘
▼
┌──────────┐
│ runc │
└──────────┘
11.3 ルートレスコンテナ
# Podman のインストール
$ sudo dnf install podman # RHEL系
$ sudo apt install podman # Ubuntu
# ルートレスでのコンテナ実行(一般ユーザー)
$ podman run -d --name web -p 8080:80 nginx:latest
# ルートレスの確認
$ podman info | grep rootless
rootless: true
# ユーザー名前空間のマッピング確認
$ podman unshare cat /proc/self/uid_map
0 1000 1
1 100000 65536
# subuid/subgid の設定確認
$ cat /etc/subuid
user:100000:65536
$ cat /etc/subgid
user:100000:65536
11.4 Pod コンセプト
Podman の「Pod」は Kubernetes の Pod と同じ概念で、複数のコンテナをグループ化する。
# Pod の作成
$ podman pod create --name my-pod -p 8080:80
# Pod にコンテナを追加
$ podman run -d --pod my-pod --name web nginx:latest
$ podman run -d --pod my-pod --name app myapp:latest
# Pod 内のコンテナは localhost で相互通信可能
# Pod の一覧
$ podman pod ls
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
abc123def456 my-pod Running 2 hours ago bcd234efg567 3
# Pod の停止
$ podman pod stop my-pod
# Pod の削除
$ podman pod rm my-pod
# Kubernetes YAML の生成
$ podman generate kube my-pod > my-pod.yaml
# Kubernetes YAML からの実行
$ podman play kube my-pod.yaml
11.5 Podman コマンド
# Docker 互換(ほぼ同じコマンド体系)
$ podman run -d --name web -p 8080:80 nginx
$ podman ps -a
$ podman logs web
$ podman exec -it web bash
$ podman stop web
$ podman rm web
$ podman images
$ podman build -t myapp:1.0 .
$ podman push myapp:1.0 registry.example.com/myapp:1.0
# Docker エイリアスの設定
$ alias docker=podman
# systemd ユニットファイルの生成
$ podman generate systemd --new --files --name web
# /home/user/.config/systemd/user/container-web.service が生成される
# systemd でコンテナを管理
$ systemctl --user enable --now container-web.service
$ systemctl --user status container-web.service
# Quadlet(Podman 4.4+、systemd ネイティブ統合)
$ cat ~/.config/containers/systemd/web.container
[Container]
Image=nginx:latest
PublishPort=8080:80
Volume=web-data.volume:/usr/share/nginx/html
[Service]
Restart=always
[Install]
WantedBy=default.target
$ systemctl --user daemon-reload
$ systemctl --user start web
12. Buildah と Skopeo
12.1 Buildah
Buildah はコンテナイメージをビルドするための専用ツールで、Dockerfile なしでもイメージを構築できる。
# Buildah のインストール
$ sudo dnf install buildah
# Dockerfile からのビルド
$ buildah bud -t myapp:1.0 .
# スクリプトによるビルド(Dockerfile 不要)
$ container=$(buildah from alpine:3.19)
$ buildah run $container -- apk add --no-cache python3 pip
$ buildah copy $container ./app /app
$ buildah config --workingdir /app $container
$ buildah config --entrypoint '["python3", "app.py"]' $container
$ buildah config --port 8080 $container
$ buildah commit $container myapp:1.0
# レイヤーの制御が柔軟
$ buildah config --label maintainer="admin@example.com" $container
$ buildah config --env APP_ENV=production $container
12.2 Skopeo
Skopeo はコンテナイメージの検査・コピー・署名を行うツールである。
# Skopeo のインストール
$ sudo dnf install skopeo
# イメージの検査(ダウンロード不要)
$ skopeo inspect docker://docker.io/library/nginx:1.25
{
"Name": "docker.io/library/nginx",
"Digest": "sha256:abc123...",
"RepoTags": ["1.25", "1.25.0", "1.25.1", ...],
"Created": "2026-03-15T12:00:00Z",
"Architecture": "amd64",
"Os": "linux"
}
# レジストリ間のイメージコピー
$ skopeo copy \
docker://docker.io/library/nginx:1.25 \
docker://registry.example.com/nginx:1.25
# ローカルディレクトリにコピー
$ skopeo copy docker://nginx:1.25 dir:/tmp/nginx-image
# OCI イメージとしてコピー
$ skopeo copy docker://nginx:1.25 oci:/tmp/nginx-oci:1.25
# イメージの削除
$ skopeo delete docker://registry.example.com/myapp:old
# レジストリのタグ一覧
$ skopeo list-tags docker://docker.io/library/nginx
13. コンテナオーケストレーション概要
13.1 Kubernetes 基礎
Kubernetes(K8s)はコンテナオーケストレーションの事実上の標準である。
# 基本的な Pod 定義
apiVersion: v1
kind: Pod
metadata:
name: web-pod
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
# Deployment 定義
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
type: LoadBalancer
Kubernetes の主要コンポーネント:
| コンポーネント | 役割 |
|---|---|
| kube-apiserver | API サーバー(全操作のエントリーポイント) |
| etcd | 分散 KVS(クラスタの状態管理) |
| kube-scheduler | Pod のスケジューリング |
| kube-controller-manager | コントローラの管理 |
| kubelet | ノード上のコンテナ管理 |
| kube-proxy | ネットワークプロキシ |
13.2 Docker Swarm
# Swarm の初期化
$ docker swarm init
# サービスのデプロイ
$ docker service create \
--name web \
--replicas 3 \
-p 80:80 \
nginx:1.25
# サービスの一覧
$ docker service ls
# スケーリング
$ docker service scale web=5
14. トラブルシューティング
コンテナが起動しない
# ログの確認
$ docker logs my-container
$ docker logs --tail 50 my-container
# コンテナの詳細情報
$ docker inspect my-container
# イベントの確認
$ docker events --since "1h"
# 起動に失敗するコンテナをデバッグ
$ docker run -it --entrypoint /bin/sh myapp:1.0
ネットワークの問題
# DNS 解決の確認
$ docker exec my-container nslookup other-container
# ネットワーク接続の確認
$ docker exec my-container ping other-container
$ docker exec my-container curl http://other-container:8080
# ネットワークの詳細
$ docker network inspect bridge
ディスク容量不足
# Docker のディスク使用量
$ docker system df -v
# クリーンアップ
$ docker system prune # 停止コンテナ、未使用ネットワーク、ダングリングイメージ
$ docker system prune -a # + 未使用イメージ全て
$ docker volume prune # 未使用ボリューム
$ docker builder prune # ビルドキャッシュ
パフォーマンスの問題
# リソース使用状況の確認
$ docker stats --no-stream
# コンテナ内のプロセス
$ docker top my-container
# ファイルシステムの変更確認
$ docker diff my-container
15. ベストプラクティスまとめ
イメージのビルド
- 軽量なベースイメージを使用する(Alpine、Distroless)
- マルチステージビルドでイメージサイズを最小化する
- .dockerignore を活用してビルドコンテキストを制限する
- レイヤーキャッシュを意識した命令順序にする
- 固定バージョンのタグを使用する
セキュリティ
- 非 root ユーザーでコンテナを実行する
- read-only ルートファイルシステムを使用する
- 必要最小限の capabilities のみ付与する
- イメージの脆弱性スキャンを CI/CD に組み込む
- シークレットは環境変数ではなく、Docker Secrets や外部管理を使う
運用
- ログドライバとローテーションを設定する
- ヘルスチェックを定義する
- リソース制限(メモリ、CPU)を設定する
- restart ポリシーを適切に設定する
- Docker Compose/Podman Compose で構成を管理する
Podman 固有
- ルートレスコンテナをデフォルトで使用する
- systemd (Quadlet) でコンテナのライフサイクルを管理する
- Pod を活用してコンテナをグループ化する
podman generate kubeで Kubernetes への移行パスを確保する
16. 参考文献
-
公式ドキュメント:
- Docker: https://docs.docker.com/
- Podman: https://podman.io/docs/
- Buildah: https://buildah.io/
- Skopeo: https://github.com/containers/skopeo
- Kubernetes: https://kubernetes.io/docs/
-
OCI 仕様:
- OCI Runtime Spec: https://github.com/opencontainers/runtime-spec
- OCI Image Spec: https://github.com/opencontainers/image-spec
-
セキュリティ:
- CIS Docker Benchmark: https://www.cisecurity.org/benchmark/docker
- Docker Security Best Practices: https://docs.docker.com/engine/security/
-
書籍:
- 「Docker Deep Dive」Nigel Poulton
- 「Kubernetes in Action」Marko Luksa
- 「Container Security」Liz Rice
本ドキュメントは 2026年4月時点の情報に基づいています。最新の情報は各ソフトウェアの公式ドキュメントを参照してください。