Docker→Podman包括的移行ガイドライン
このガイドは、既存のDocker環境からPodmanへの段階的な移行を支援します。実践的なチェックリストとツールを提供し、リスクを最小化しながら確実な移行を実現します。
対象バージョン
- 移行元: Docker 20.x以降
- 移行先: Podman 5.0.x
- 検証済みOS: RHEL 9.3、Ubuntu 22.04 LTS、CentOS Stream 9
表記について
- 本ガイドでは Compose の定義ファイル名として
docker-compose.yml等の表記を用います(ファイル名/パターンを示すため)。 - コマンドは Compose v2 の
docker composeを基本とし、docker-composeは Compose v1(legacy)の残存チェックや互換目的のエイリアス/ラッパー例など、限定的な文脈でのみ登場します。
移行前評価チェックリスト
Phase 0: 現状分析(1週間)
インベントリ作成
#!/bin/bash
# docker-inventory.sh - Docker環境の棚卸しスクリプト
echo "=== Docker環境インベントリ ==="
echo ""
echo "1. Dockerバージョン:"
docker --version
echo ""
echo "2. 実行中のコンテナ:"
docker ps --format "table \{\{.Names\}\}\t\{\{.Image\}\}\t\{\{.Status\}\}\t\{\{.Ports\}\}"
echo ""
echo "3. イメージ一覧:"
docker images --format "table \{\{.Repository\}\}:\{\{.Tag\}\}\t\{\{.Size\}\}"
echo ""
echo "4. ボリューム一覧:"
docker volume ls
echo ""
echo "5. ネットワーク一覧:"
docker network ls
echo ""
echo "6. Composeプロジェクト(Compose 定義ファイル: docker-compose*.yml):"
find . -name "docker-compose*.yml" -type f 2>/dev/null | head -20
echo ""
echo "7. Dockerfile一覧:"
find . -name "Dockerfile*" -type f 2>/dev/null | head -20
互換性評価
#!/bin/bash
# compatibility-check.sh - Podman互換性チェック
echo "=== Podman互換性チェック ==="
# Docker特有機能の使用確認
echo "チェック項目:"
echo -n "[ ] Docker Swarmの使用: "
docker node ls 2>&1 | grep -q "This node is not a swarm manager" && echo "[OK] 未使用" || echo "[WARN] 使用中"
echo -n "[ ] Docker Compose v2(docker compose)の利用可/インストール状況: "
docker compose version >/dev/null 2>&1 && echo "[OK] 利用可" || echo "[WARN] 未検出"
echo -n "[ ] Docker Compose v1(docker-compose)の残存: "
command -v docker-compose >/dev/null 2>&1 && echo "[WARN] 検出(legacy)" || echo "[OK] 未検出"
echo -n "[ ] 特権コンテナの使用: "
docker ps --format '\{\{.Names\}\}' | xargs -I {} docker inspect {} | grep -q '"Privileged": true' && echo "[WARN] 使用中" || echo "[OK] 未使用"
echo -n "[ ] カスタムDockerネットワーク: "
docker network ls --format '\{\{.Name\}\}' | grep -v -E 'bridge|host|none' | wc -l | xargs -I {} test {} -gt 0 && echo "[WARN] 使用中(要確認)" || echo "[OK] 標準のみ"
Phase 1: 互換性確認と準備(1〜2週間)
Docker Compose互換性の確保
docker-compose.ymlの変換
# 変換前(Docker Compose)
version: '3.8'
services:
web:
build: .
ports:
- "8080:80"
volumes:
- ./data:/app/data
environment:
- NODE_ENV=production
depends_on:
- db
restart: unless-stopped
db:
image: postgres:13
volumes:
- db-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: secret
volumes:
db-data:
# 変換後(Podman Compose対応)
version: '3.8'
services:
web:
build: .
ports:
- "8080:80"
volumes:
- ./data:/app/data:Z # SELinuxラベル追加
environment:
- NODE_ENV=production
depends_on:
- db
restart: unless-stopped
# Podman固有の設定
userns_mode: keep-id # ユーザー名前空間の保持
db:
image: postgres:13
volumes:
- db-data:/var/lib/postgresql/data:Z
environment:
POSTGRES_PASSWORD: secret
# セキュリティ強化
security_opt:
- label=disable # 必要に応じて
volumes:
db-data:
イメージ移行スクリプト
#!/bin/bash
# migrate-images.sh - DockerイメージのPodmanへの移行
# Dockerイメージをtarファイルにエクスポート
migrate_image() {
local image=$1
local tar_name=$(echo $image | tr '/' '_' | tr ':' '_').tar
echo "エクスポート中: $image"
docker save -o $tar_name $image
echo "インポート中: $image"
podman load -i $tar_name
# 検証
if podman images | grep -q $image; then
echo "✓ $image の移行成功"
rm $tar_name
else
echo "✗ $image の移行失敗"
fi
}
# 全イメージの移行
docker images --format '\{\{.Repository\}\}:\{\{.Tag\}\}' | grep -v '<none>' | while read image; do
migrate_image $image
done
ボリュームデータの移行
#!/bin/bash
# migrate-volumes.sh - Dockerボリュームの移行
migrate_volume() {
local vol_name=$1
# Dockerボリュームのパスを取得
docker_path=$(docker volume inspect $vol_name --format '\{\{.Mountpoint\}\}')
# Podmanボリューム作成
podman volume create $vol_name
# Podmanボリュームのパスを取得
podman_path=$(podman volume inspect $vol_name --format '\{\{.Mountpoint\}\}')
# データコピー(root権限が必要な場合あり)
echo "コピー中: $vol_name"
sudo cp -rp $docker_path/* $podman_path/
echo "✓ $vol_name の移行完了"
}
# 全ボリュームの移行
docker volume ls -q | while read volume; do
migrate_volume $volume
done
Phase 2: パイロット導入(2〜4週間)
段階的移行戦略
開発環境での検証
# 1. Podman aliasの設定(一時的)
alias docker=podman
# Composeファイル(docker-compose.yml 等)は podman-compose を使用
pip3 install podman-compose
# 1-1. 既存スクリプトに残る Compose 呼び出しの吸収(検証用途)
# - docker-compose を呼ぶ場合(Compose v1 形式)
alias docker-compose=podman-compose
#
# - docker compose を呼ぶ場合(Compose v2 形式)のラッパー例(bash)
# ※ 本番運用前には、スクリプト側の呼び出しを `podman-compose` / `podman` に書き換えることを推奨
# docker() {
# if [ "${1:-}" = "compose" ]; then
# shift
# podman-compose "$@"
# else
# command podman "$@"
# fi
# }
# 2. 既存スクリプトのテスト
./deploy.sh # 既存のデプロイスクリプト(上記方針で Compose 呼び出しを吸収)
# 3. 動作確認
podman ps
podman logs <container_name>
サイドバイサイド実行
# Dockerは8080ポート、Podmanは8081ポートで同じアプリを実行
docker run -d -p 8080:80 --name app-docker nginx:alpine
podman run -d -p 8081:80 --name app-podman nginx:alpine
# パフォーマンス比較
ab -n 10000 -c 100 http://localhost:8080/ > docker-perf.txt
ab -n 10000 -c 100 http://localhost:8081/ > podman-perf.txt
移行時の注意点と対処法
1. ネットワーク設定の違い
# Docker: デフォルトブリッジネットワーク
docker network create mynet
# Podman: 同等の設定
podman network create mynet
# ただし、IPアドレス範囲が異なる場合があるため確認
podman network inspect mynet
2. ビルドコンテキストの違い
# Dockerfile内でのユーザー権限
# Dockerではroot、Podmanではrootlessがデフォルト
# 互換性を保つための記述
FROM alpine:latest
# 明示的にユーザーを指定
USER root
RUN apk add --no-cache nginx
# 非rootユーザーで実行
USER nginx
3. ログドライバーの違い
# Docker: json-fileがデフォルト
docker run --log-driver json-file nginx
# Podman: journaldがデフォルト(systemd環境)
podman run --log-driver json-file nginx # Dockerと同じ動作
Phase 3: 本番環境移行(1〜3ヶ月)
カットオーバー計画
ブルーグリーンデプロイメント
#!/bin/bash
# blue-green-migration.sh
# 現在の本番(Docker - Blue)
BLUE_PORT=80
GREEN_PORT=8080
# 新環境(Podman - Green)の準備
podman run -d --name app-green -p $GREEN_PORT:80 myapp:latest
# ヘルスチェック
for i in {1..30}; do
if curl -f http://localhost:$GREEN_PORT/health; then
echo "Green環境: 正常"
break
fi
sleep 2
done
# トラフィック切り替え(ロードバランサー設定変更)
# この部分は環境に応じて実装
# 旧環境の停止
docker stop app-blue
ロールバック手順
#!/bin/bash
# rollback-procedure.sh
# 問題検出時の自動ロールバック
if ! podman healthcheck run app-production; then
echo "ヘルスチェック失敗: ロールバック開始"
# Podman停止
podman stop app-production
# Docker再起動
docker start app-production-backup
# アラート送信
send_alert "Podman移行ロールバック実行"
fi
移行ツールとユーティリティ
自動変換ツール
#!/usr/bin/env python3
# docker2podman.py - Docker Compose自動変換
import yaml
import sys
def convert_compose(docker_compose_file):
with open(docker_compose_file, 'r') as f:
compose = yaml.safe_load(f)
# Podman固有の変換
for service_name, service in compose.get('services', {}).items():
# SELinuxコンテキスト追加
if 'volumes' in service:
service['volumes'] = [
f"{vol}:Z" if ':Z' not in vol else vol
for vol in service['volumes']
]
# rootless対応
if 'user' not in service:
service['userns_mode'] = 'keep-id'
return compose
if __name__ == "__main__":
converted = convert_compose(sys.argv[1])
print(yaml.dump(converted, default_flow_style=False))
継続的な互換性チェック
#!/bin/bash
# continuous-compatibility-check.sh
# CI/CDパイプラインに組み込む
run_compatibility_test() {
echo "Docker/Podman互換性テスト開始"
# 同じイメージでコンテナ起動
docker run -d --name test-docker -p 9000:80 $TEST_IMAGE
podman run -d --name test-podman -p 9001:80 $TEST_IMAGE
# 機能テスト実行
./run-tests.sh http://localhost:9000 > docker-results.txt
./run-tests.sh http://localhost:9001 > podman-results.txt
# 結果比較
if diff docker-results.txt podman-results.txt; then
echo "✓ 互換性テスト合格"
return 0
else
echo "✗ 互換性テスト失敗"
return 1
fi
}
移行後の最適化
パフォーマンスチューニング
# Podman固有の最適化
# 1. ストレージドライバーの最適化
podman info | grep graphDriverName
# overlay が推奨
# 2. ログサイズの制限
podman run --log-opt max-size=10m nginx
# 3. cgroup v2の活用
podman run --memory 512m --cpus 0.5 nginx
監視とメトリクス
# Prometheus対応
podman run -d \
--name prometheus \
-p 9090:9090 \
-v prometheus-data:/prometheus:Z \
prom/prometheus
# メトリクスエクスポート
podman stats --format json | jq '.'
移行完了チェックリスト
- すべてのコンテナがPodmanで実行されている
- ボリュームデータの整合性確認
- ネットワーク接続性の確認
- パフォーマンスベンチマーク完了
- 監視・ログ収集の移行
- バックアップ・リストア手順の更新
- 運用ドキュメントの更新
- チームトレーニングの完了
トラブルシューティング
よくある問題と解決策
- 権限エラー
# 問題: permission denied # 解決: podman unshare chown -R $UID:$GID /path/to/volume - ネットワーク接続問題
# 問題: コンテナ間通信不可 # 解決: 同一Podまたはネットワークで実行 podman network create shared podman run --network shared ... - ビルドエラー
# 問題: COPY失敗 # 解決: SELinuxコンテキスト podman build --security-opt label=disable .
この移行ガイドラインに従うことで、Dockerから Podmanへの移行を計画的かつ安全に実施できます。