Dockerコンテナセキュリティ強化:2026年イメージからランタイムまで8層防御の完全ソリューション

DevOps

あなたのコンテナ、本当に安全ですか?

コンテナ化デプロイはデリバリを高速化しましたが、セキュリティ負債も急速に蓄積しています。デフォルト設定のDockerコンテナはrootで実行し、Docker Socketをマウントし、リソース制限がありません——攻撃者がコンテナ境界を突破すると、ホストのroot権限を取得できます。サプライチェーン攻撃が頻発し、悪意あるイメージが本番環境に混入;環境変数からの機密情報漏洩;ランタイム権限昇格脆弱性の悪用……これらは仮定のシナリオではなく、毎日発生しているセキュリティインシデントです。

2026年、コンテナセキュリティは「オプション」から「必須」になりました。本記事では8層防御体系を構築し、イメージビルドからランタイム保護まで、コンテナセキュリティの死角をなくします。


8層防御体系概要

防御対象 コア技術
第1層 イメージセキュリティ マルチステージビルド、distroless、イメージスキャン
第2層 サプライチェーンセキュリティ イメージ署名、SBOM、不変タグ
第3層 最小権限 非rootユーザー、読み取り専用ファイルシステム、ケイパビリティ削減
第4層 ネットワーク分離 ネットワークポリシー、Service Mesh、egress制御
第5層 リソース制限 CPU/メモリ制限、PIDs制限、OOMポリシー
第6層 システムコールフィルタリング Seccompプロファイル、AppArmorポリシー
第7層 ランタイム監視 脆弱性検出、異常行動アラート、ファイル完全性
第8層 コンプライアンス監査 CISベンチマーク、セキュリティベースライン、監査ログ

問題の深掘り:コンテナセキュリティの8つの脅威

脅威 攻撃経路 影響範囲 防御層
悪意あるベースイメージ サプライチェーン汚染 全コンテナ 第1-2層
コンテナエスケープ カーネル脆弱性悪用 ホスト 第3-6層
権限昇格 root実行+過剰ケイパビリティ ホスト 第3層
横展開 ネットワーク分離なし クラスタ内全サービス 第4層
リソース枯渇 リソース制限なし 同ノード全コンテナ 第5層
機密情報漏洩 環境変数/設定ファイル データ漏洩 第3層
サプライチェーン改ざん イメージタグ上書き 全コンテナ 第2層
ランタイム攻撃 既知脆弱性悪用 コンテナ内サービス 第7層

第1層:イメージセキュリティ

マルチステージビルド + distroless

FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server .

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/server /server
USER 65532:65532
ENTRYPOINT ["/server"]

イメージスキャン

trivy image --severity HIGH,CRITICAL --exit-code 1 registry.example.com/app:v1.0.0
grype registry.example.com/app:v1.0.0 --fail-on critical
docker scout cves registry.example.com/app:v1.0.0

第2層:サプライチェーンセキュリティ

# イメージ署名
cosign sign --key cosign.key registry.example.com/app:v1.0.0
cosign verify --key cosign.pub registry.example.com/app:v1.0.0

# SBOM生成
syft registry.example.com/app:v1.0.0 -o spdx-json > sbom.json

不変タグ

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-latest-tag
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-image-tag
      match:
        resources:
          kinds: [Pod]
      validate:
        message: "イメージは特定バージョンタグを使用してください"
        pattern:
          spec:
            containers:
              - image: "!*:latest"

第3層:最小権限

セキュアなDockerfile

FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --chown=appuser:appgroup . .
USER appuser
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["node", "server.js"]

セキュアなdocker-compose.yml

version: "3.9"
services:
  app:
    image: registry.example.com/app:v1.0.0
    security_opt:
      - no-new-privileges:true
      - seccomp:seccomp-profile.json
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    read_only: true
    tmpfs:
      - /tmp:noexec,nosuid,size=100m
    user: "65534:65534"
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
          pids: 100
    networks:
      - app-network
    volumes:
      - app-data:/app/data:noexec

networks:
  app-network:
    driver: bridge
    internal: true

第4層:ネットワーク分離

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-network-policy
spec:
  podSelector:
    matchLabels:
      app: web-app
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
      ports:
        - port: 3000
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              name: database
      ports:
        - port: 5432

第5層:リソース制限

apiVersion: v1
kind: LimitRange
metadata:
  name: production-limits
spec:
  limits:
    - default:
        cpu: "500m"
        memory: "256Mi"
      defaultRequest:
        cpu: "100m"
        memory: "128Mi"
      max:
        cpu: "2"
        memory: "2Gi"
      type: Container

第6層:システムコールフィルタリング

Seccompプロファイル

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "defaultErrnoRet": 1,
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": [
        "accept", "bind", "brk", "close", "connect", "epoll_wait",
        "exit", "exit_group", "fcntl", "fstat", "futex", "mmap",
        "mprotect", "munmap", "open", "openat", "read", "recvfrom",
        "sendto", "setgid", "setuid", "socket", "stat", "write"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

AppArmorポリシー

#include <tunables/global>

profile docker-apparmor flags=(attach_disconnected,mediate_deleted) {
  network inet tcp,
  network inet udp,
  /app/** r,
  /app/data/** rw,
  /tmp/** rw,
  deny /proc/*/mem rw,
  deny /sys/** rw,
  deny /etc/shadow r,
  capability net_bind_service,
  deny capability sys_admin,
  deny capability sys_ptrace,
}

第7層:ランタイム監視

apiVersion: falco.org/v1
kind: FalcoRule
metadata:
  name: container-security-rules
spec:
  rules:
    - rule: Read sensitive file
      desc: 機密ファイルの読み取りを検出
      condition: >
        container and open_read and fd.name in (/etc/shadow, /etc/passwd, /root/.ssh/id_rsa)
      output: 機密ファイル読み取り (container=%container.name file=%fd.name)
      priority: CRITICAL

    - rule: Unexpected outbound connection
      desc: 許可リスト外のアウトバウンド接続を検出
      condition: >
        container and outbound and not fd.sip in (10.0.0.0/8, 172.16.0.0/12)
      output: 予期しないアウトバウンド (container=%container.name)
      priority: WARNING

第8層:コンプライアンス監査

# CIS Docker Benchmark監査
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  docker/docker-bench-security

# kube-bench
kube-bench run --targets master,node,etcd,policies

# Docker daemonセキュリティ設定
cat > /etc/docker/daemon.json << 'EOF'
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" },
  "storage-driver": "overlay2",
  "userns-remap": "default",
  "no-new-privileges": true
}
EOF

よくある落とし穴ガイド

落とし穴1:Rootlessモードでボリュームマウントの権限エラー

RootlessモードではコンテナUIDがホストのサブUID範囲にマッピングされます。

解決策cat /etc/subuidでサブUID範囲を確認、ボリュームディレクトリの権限を調整。

落とし穴2:Seccomp設定が厳しすぎてアプリがクラッシュ

デフォルトですべてのシステムコールを拒否すると、アプリに必要なコールがブロックされます。

解決策straceで必要なシステムコールを収集、緩やかな設定から始めて段階的に厳格化。

落とし穴3:AppArmor設定が反映されない

AppArmorプロファイルが正しくロードされていない。

解決策aa-statusで確認、apparmor_parser -rで手動ロード。

落とし穴4:読み取り専用ファイルシステムで書き込み失敗

read_only: trueによりアプリが一時ファイルやキャッシュを書き込めない。

解決策tmpfsマウントとvolumesを追加。

落とし穴5:イメージスキャンの誤検出が多すぎる

スキャンツールが大量の低重大度脆弱性を報告し、真の問題が埋もれる。

解決策:HIGHとCRITICALレベルのみに注目、.trivyignoreで既知の誤検出を除外。


エラートラブルシューティング

# エラーメッセージ 原因 解決方法
1 permission denied: Docker daemon socket Dockerグループ権限なし sudo usermod -aG docker $USER
2 OCI runtime: rootfs propagation error Rootlessマウント競合 ボリュームパスとUIDマッピングを確認
3 seccomp: unknown syscall Seccompにシステムコール不足 許可リストに追加
4 AppArmor: denied AppArmorポリシーがブロック AppArmorプロファイルを更新
5 write /proc/self/attr/current: permission denied no-new-privilegesとSELinuxの競合 SELinuxポリシーを調整
6 read-only file system 読み取り専用ルートで書き込み tmpfsまたはvolumeを追加
7 OOMKilled メモリ制限が小さすぎる メモリ制限を増加
8 certificate verify failed レジストリ証明書検証失敗 信頼証明書を設定
9 image signature verification failed イメージ署名検証失敗 cosign署名と公開鍵を確認
10 no space left on device イメージレイヤ過多 docker system prune -a

高度な最適化

1. Rootless Dockerデプロイ

dockerd-rootless-setuptool.sh install
echo "export DOCKER_HOST=unix:///run/user/$UID/docker.sock" >> ~/.bashrc

2. ビルド-署名-スキャンCIパイプライン

name: Build and Sign Image
on:
  push:
    tags: ['v*']
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: docker build -t registry.example.com/app:${{ github.ref_name }} .
      - run: trivy image --exit-code 1 --severity HIGH,CRITICAL registry.example.com/app:${{ github.ref_name }}
      - uses: sigstore/cosign-installer@v3
      - run: cosign sign --yes --key env://COSIGN_KEY registry.example.com/app:${{ github.ref_name }}

3. 自動化ランタイムセキュリティポリシー

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: pod-security-defaults
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-non-root
      match:
        resources:
          kinds: [Pod]
      validate:
        message: "コンテナは非rootで実行してください"
        pattern:
          spec:
            containers:
              - securityContext:
                  runAsNonRoot: true
    - name: drop-all-capabilities
      match:
        resources:
          kinds: [Pod]
      mutate:
        patchStrategicMerge:
          spec:
            containers:
              - (name): "?*"
                securityContext:
                  capabilities:
                    drop:
                      - ALL

比較分析

次元 Dockerデフォルト CIS Level 1 CIS Level 2 Rootless Podman
root実行 はい いいえ いいえ いいえ いいえ
ケイパビリティ削減 なし drop ALL drop ALL+最小add 自動制限 自動制限
読み取り専用FS いいえ 推奨 強制 いいえ いいえ
Seccomp デフォルト デフォルト カスタム デフォルト デフォルト
AppArmor なし 推奨 強制 なし なし
イメージスキャン なし 推奨 強制 推奨 推奨
イメージ署名 なし なし 推奨 推奨 推奨
ネットワーク分離 なし 推奨 強制 推奨 推奨
リソース制限 なし 推奨 強制 推奨 推奨
セキュリティレベル

まとめ:Dockerコンテナセキュリティは単一技術ではなく、8層の防御深度システムです。イメージビルド段階のマルチステージビルドと脆弱性スキャンから、ランタイムのSeccomp/AppArmorポリシーとFalco監視まで、各層が攻撃面を縮小します。2026年のベストプラクティスは:デフォルト非root実行、読み取り専用ファイルシステム、最小ケイパビリティセット、イメージ署名検証、継続的脆弱性スキャンです。CIS Level 1ベースラインから始め、段階的にLevel 2にアップグレードし、最終的にRootlessデプロイを実現することをお勧めします。セキュリティに終点はなく、継続的な改善のみがあります。


オンラインツールおすすめ

  • JSONフォーマッター:/ja/json/format — Seccomp設定とDocker APIレスポンスのフォーマット
  • Base64エンコード/デコード:/ja/encode/base64 — Docker Registry認証トークンとSecretのエンコード/デコード
  • Curl to Code:/ja/dev/curl-to-code — Docker APIデバッグcurlをコードに変換

ブラウザローカルツールを無料で試す →

#Docker#容器安全#镜像扫描#Rootless#Seccomp#AppArmor#供应链安全#CIS基准