※本記事にはアフィリエイトリンクが含まれます。詳しくはプライバシーポリシー・広告掲載についてをご覧ください。
「DockerコンテナやKubernetesを本番環境で使っているが、セキュリティ対策が不十分かもしれない」と感じたことはありませんか?コンテナ技術は開発効率を大幅に向上させる一方、適切なセキュリティ設定を怠ると深刻な侵害につながります。本記事では、コンテナ環境の脅威モデルから始まり、Dockerfile・Kubernetes・イメージスキャン・ランタイム保護まで、実践的なセキュリティ対策を体系的に解説します。DevSecOpsを実践したいエンジニアや、コンテナ環境のセキュリティ強化を担当するセキュリティ担当者に向けた内容です。
コンテナ環境の脅威モデル
コンテナセキュリティを考えるうえで、まず攻撃者がどのような経路で侵入・被害を拡大させるかを理解することが重要です。
主要な攻撃ベクター
- 脆弱なベースイメージ: パッチ未適用のOSライブラリを含むイメージを使用することで、既知CVEを悪用される
- コンテナエスケープ: Dockerデーモンの設定ミスや特権コンテナ(
--privileged)により、ホストOSへの侵入が可能になる - サプライチェーン攻撃: 悪意のあるサードパーティイメージやパッケージの混入
- シークレット漏洩: Dockerfileや環境変数にハードコードされたAPIキー・パスワード
- ネットワーク横移動: コンテナ間通信の無制限許可による侵害の拡散
- 過剰な権限: 不要なLinux Capabilitiesやroot実行による特権昇格
攻撃の典型的な流れ
攻撃者は通常、①脆弱なアプリケーション経由でコンテナ内に初期侵入し、②コンテナ内での権限昇格を試み、③コンテナエスケープでホストを掌握し、④クラスタ全体への横移動を行います。各段階でのセキュリティ対策が求められます。
Dockerfileセキュリティベストプラクティス
rootlessコンテナの実装
デフォルトではDockerコンテナはrootユーザとして実行されます。これは、コンテナエスケープが発生した際にホストOSをroot権限で掌握されるリスクを意味します。必ず非rootユーザを指定しましょう。
# NG: rootで実行(デフォルト)
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y myapp
# OK: 非rootユーザを作成して実行
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y myapp \
&& useradd -r -u 1001 -g root appuser
USER appuser
ENTRYPOINT ["myapp"]
マルチステージビルドによる攻撃面の削減
マルチステージビルドを使用することで、ビルドツール(gcc、makeなど)を最終イメージから除外し、攻撃面を大幅に削減できます。
# ビルドステージ(ビルドツールを含む)
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o server .
# 実行ステージ(最小限のイメージ)
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app/server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]
distrolessイメージはシェルすら含まないため、攻撃者がコンテナ内に侵入しても有効なコマンドを実行できません。
読み取り専用ファイルシステム
コンテナのファイルシステムを読み取り専用にすることで、マルウェアの書き込みや設定ファイルの改ざんを防止できます。
# docker run時
docker run --read-only --tmpfs /tmp myapp
# docker-compose.yml
services:
app:
image: myapp
read_only: true
tmpfs:
- /tmp
- /var/run
シークレット管理の徹底
Dockerfileに認証情報をハードコードしてはいけません。ビルド時に使用するシークレットは--secretフラグで渡し、実行時はDocker SecretsやKubernetes Secretsを活用します。
# NG: Dockerfileに直書き
ENV DB_PASSWORD=mysecretpassword
# OK: ビルド時シークレット(Dockerfileに残らない)
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=db_password \
DB_PASSWORD=$(cat /run/secrets/db_password) && mysetup
Kubernetesセキュリティ設定
NetworkPolicyによる通信制御
KubernetesはデフォルトでPod間の全通信を許可しています。NetworkPolicyを設定し、必要な通信のみを明示的に許可する「ゼロトラスト」アプローチを採用しましょう。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# フロントエンドからバックエンドへの通信のみ許可
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
RBACによる最小権限の原則
Role-Based Access Control (RBAC) を適切に設定し、ServiceAccountに必要最小限の権限のみを付与します。cluster-admin権限の濫用は深刻なリスクです。
# 特定のnamespaceでのみPod読み取りを許可するRole
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: production
subjects:
- kind: ServiceAccount
name: monitoring-sa
namespace: production
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Pod Security Standards
Kubernetes 1.25以降、Pod Security Admission (PSA) が標準化されています。restrictedプロファイルを適用することで、特権コンテナ・ホストNamespace使用・特権昇格を一括で防止できます。
# namespaceにrestricted profileを適用
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/warn: restricted
SecurityContextの設定
apiVersion: v1
kind: Pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1001
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
コンテナイメージスキャン:TrivyとGrype
Trivyによる脆弱性スキャン
TrivyはAqua Securityが開発したオープンソースの脆弱性スキャナーです。OSパッケージ・言語パッケージ・設定ファイル・シークレットを包括的にスキャンできます。
# イメージスキャン
trivy image nginx:latest
# 重大度HIGHとCRITICALのみ表示
trivy image --severity HIGH,CRITICAL myapp:latest
# CI/CD組み込み(終了コードで合否判定)
trivy image --exit-code 1 --severity CRITICAL myapp:latest
# Dockerfile/設定ファイルスキャン(IaC)
trivy config ./k8s/
# シークレットスキャン
trivy fs --scanners secret .
Grypeによる補完スキャン
GrypeはAnchoreが提供するイメージスキャナーで、SBOMファイルからの脆弱性評価が得意です。Trivyと組み合わせて使用することで検出漏れを最小化できます。
# イメージスキャン
grype myapp:latest
# SBOMから脆弱性評価
syft myapp:latest -o cyclonedx-json > sbom.json
grype sbom:sbom.json
CI/CDパイプラインへの統合
スキャンはビルド時だけでなく、定期的にも実行することが重要です。依存ライブラリの新たなCVEは日々公開されます。
# GitHub Actions例
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1'
ランタイム保護:FalcoとSeccomp
Falcoによる異常検知
FalcoはCNCFのランタイムセキュリティツールで、Linuxカーネルのシステムコールを監視し、不審な挙動をリアルタイムで検知します。
# Helmでインストール
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
--namespace falco --create-namespace \
--set falco.jsonOutput=true \
--set falco.logLevel=info
# カスタムルール例(コンテナ内でのシェル実行を検知)
- rule: Shell spawned in container
desc: A shell was spawned in a container
condition: >
spawned_process and container
and shell_procs
and not user_known_shell_spawn_activities
output: >
Shell spawned in container
(user=%user.name container=%container.name
image=%container.image.repository shell=%proc.name)
priority: WARNING
Seccompプロファイルによるシステムコール制限
seccomp(Secure Computing Mode)は、コンテナが使用できるシステムコールをホワイトリスト方式で制限します。不要なシステムコールをブロックすることで、エクスプロイトの影響範囲を大幅に縮小できます。
# カスタムseccompプロファイル例(必要最小限のsyscallのみ許可)
{
"defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [
{
"names": ["read", "write", "open", "close", "stat",
"fstat", "mmap", "mprotect", "munmap",
"brk", "rt_sigaction", "rt_sigprocmask",
"ioctl", "access", "execve", "exit",
"wait4", "kill", "uname", "fcntl",
"gettimeofday", "getpid", "clone",
"socket", "connect", "accept", "sendto",
"recvfrom", "shutdown", "bind", "listen",
"getsockname", "getpeername", "setsockopt",
"getsockopt", "exit_group", "epoll_wait",
"epoll_ctl", "tgkill", "openat", "getdents64",
"set_robust_list", "futex", "nanosleep"],
"action": "SCMP_ACT_ALLOW"
}
]
}
コンテナセキュリティ実践チェックリスト
Dockerfileチェック項目
- ☑ 非rootユーザ(USER命令)を指定している
- ☑ マルチステージビルドでビルドツールを除外している
- ☑ distroless/alpineなど最小ベースイメージを使用している
- ☑
--no-cacheでパッケージキャッシュを含めない - ☑ シークレットをDockerfileにハードコードしていない
- ☑
.dockerignoreで不要ファイルを除外している - ☑ ベースイメージのダイジェスト(SHA256)をピン留めしている
Kubernetesチェック項目
- ☑ NetworkPolicyでPod間通信を制限している
- ☑ RBACで最小権限ServiceAccountを設定している
- ☑ Pod Security StandardsのrestrictedプロファイルをNamespaceに適用している
- ☑
allowPrivilegeEscalation: falseを設定している - ☑
readOnlyRootFilesystem: trueを設定している - ☑ 不要なCapabilitiesをすべてdropしている
- ☑ Secretsを環境変数ではなくボリュームマウントで渡している
- ☑ EtcdのSecret暗号化(Encryption at Rest)を有効化している
継続的セキュリティチェック項目
- ☑ CI/CDパイプラインにTrivyスキャンを組み込んでいる
- ☑ コンテナレジストリで定期スキャンを設定している
- ☑ Falcoでランタイム異常を監視している
- ☑ Kubernetes APIサーバの監査ログを有効化している
- ☑ コンテナイメージの署名(cosign/Notary)を実施している
おすすめセキュリティ対策ツール
本記事で紹介した対策を実施するうえで役立つ製品をご紹介します。
🛡️ まず今日から始めるなら:エンドポイント保護ソフトの導入
コンテナ環境のセキュリティ強化と並行して、開発端末・踏み台サーバへのエンドポイント保護も欠かせません。信頼性の高いセキュリティソフトの導入を強くお勧めします。
- ESET(イーセット) — 誤検知が少なく軽量。中小企業に人気のコスパ重視セキュリティソフト
- ウイルスバスター — 日本語サポートが充実。国産ソフトで中小企業導入実績多数
- Norton(ノートン) — 世界最大手のセキュリティベンダー。VPN機能も含む総合対策
※ 上記はアフィリエイトリンクです。料金・機能は各公式サイトで必ずご確認ください。
まとめ:コンテナセキュリティは多層防御で
- Dockerfileでは非root・マルチステージ・read-onlyを基本とする
- KubernetesはNetworkPolicy・RBAC・Pod Security Standardsで最小権限を徹底する
- TrivyやGrypeでCI/CDにスキャンを組み込み、既知CVEを継続的に排除する
- FalcoとSeccompでランタイムの異常行動を検知・ブロックする
- セキュリティは一度設定して終わりではなく、継続的な監視と改善が必要
コンテナ技術の普及に伴い、攻撃者も専門的な手法を用いるようになっています。本記事のチェックリストを参考に、自社のコンテナ環境のセキュリティ体制を見直してみてください。


コメント