はじめに
コンテナ技術の普及に伴い、Dockerは多くの組織のインフラストラクチャに不可欠な存在となっています。しかし、その便利さと引き換えに、適切なセキュリティ対策が講じられていないと重大なリスクをもたらす可能性があります。本記事では、Dockerコンテナを安全に運用するためのベストプラクティスを解説し、実践的なセキュリティ対策を紹介します。
1. イメージのセキュリティ
公式イメージの使用
信頼できるソースからのイメージを使用することは、セキュリティの基本です。
# 公式イメージの使用例
docker pull ubuntu:20.04
docker pull nginx:stable
イメージの脆弱性スキャン
コンテナイメージに潜在的な脆弱性がないかを定期的にスキャンしましょう。
# Trivy を使用したイメージスキャンの例
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image nginx:latest
マルチステージビルドの活用
本番環境で必要のないビルドツールや依存関係をイメージから除外します。
# マルチステージビルドの例
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:14-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
USER node
CMD ["npm", "start"]
最小限のベースイメージの使用
Alpine LinuxやDistrolessなどの軽量イメージを使用して攻撃対象領域を減らします。
# Alpineベースイメージの例
FROM alpine:3.14
RUN apk add --no-cache python3 py3-pip
# ...以下略
2. コンテナの設定
非特権ユーザーでの実行
root権限でコンテナを実行することは避け、専用の非特権ユーザーを作成しましょう。
# Dockerfileでの非特権ユーザー設定
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
読み取り専用ファイルシステムの使用
可能な限り、コンテナのファイルシステムを読み取り専用にして、不正な書き込みやマルウェアの実行を防ぎます。
# 読み取り専用でコンテナを起動
docker run --read-only --tmpfs /tmp my-secure-app
Capabilities の制限
Dockerの特権を最小限に抑え、必要なCapabilitiesのみを付与します。
# 必要なCapabilitiesのみを付与する例
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE my-app
seccomp プロファイルの適用
システムコールを制限することで、コンテナからのホストシステムへのアクセスを制御します。
# seccompプロファイルを適用してコンテナを起動
docker run --security-opt seccomp=/path/to/seccomp/profile.json my-app
3. ネットワークセキュリティ
ネットワークの分離
コンテナ間の通信を制御するため、適切なネットワーク分離を実装します。
# カスタムネットワークの作成と適用
docker network create --driver bridge secure-network
docker run --network secure-network my-app
ポート公開の最小化
必要最小限のポートのみを公開し、露出面を減らします。
# 必要なポートのみを公開
docker run -p 443:8443 my-app
TLSの設定
Docker Daemonとの通信にTLSを使用して、通信を暗号化します。
# TLS証明書を使用したDockerデーモンの設定
dockerd \
--tlsverify \
--tlscacert=ca.pem \
--tlscert=server-cert.pem \
--tlskey=server-key.pem \
-H=0.0.0.0:2376
4. リソース制限の設定
メモリ制限
コンテナが使用できるメモリを制限し、DoS攻撃のリスクを軽減します。
# メモリ制限を設定してコンテナを起動
docker run --memory=512m --memory-swap=512m my-app
CPUの制限
CPUリソースの使用量を制限して、他のサービスへの影響を防ぎます。
# CPU使用率を制限してコンテナを起動
docker run --cpus=.5 my-app
PIDs制限
プロセス数を制限して、フォークボム攻撃などを防止します。
# 最大プロセス数を制限
docker run --pids-limit=100 my-app
5. ランタイムセキュリティ
AppArmor/SELinuxの活用
強制アクセス制御を実装して、コンテナの権限を厳密に制限します。
# AppArmorプロファイルを適用
docker run --security-opt apparmor=docker-default my-app
コンテナの定期的な更新
脆弱性に対応するため、コンテナイメージを定期的に更新しましょう。
# イメージの更新と再デプロイ
docker pull my-app:latest
docker-compose up -d --force-recreate
不変インフラの採用
コンテナに変更を加えるのではなく、新しいコンテナをデプロイする戦略を採用します。
6. 監視とログ管理
ログの一元管理
コンテナのログを外部のログ集約システムに転送して、セキュリティ監視を強化します。
# Fluentdを使用したログ転送の設定
docker run \
--log-driver=fluentd \
--log-opt fluentd-address=localhost:24224 \
my-app
コンテナの監視
リアルタイムで異常なアクティビティを検出するための監視システムを導入します。
# Prometheusとcadvisorを使用した監視設定
docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
--detach=true \
gcr.io/cadvisor/cadvisor:latest
継続的なセキュリティスキャン
実行中のコンテナに対して定期的なセキュリティスキャンを実施します。
# Anchoreを使用したスキャン例
docker run -d -p 8228:8228 -p 8338:8338 anchore/anchore-engine
anchore-cli image add my-app:latest
7. Docker Composeのセキュリティ設定
Docker Composeを使用する場合も、セキュリティ設定を適切に行います。
# docker-compose.ymlのセキュリティ設定例
version: '3.8'
services:
webapp:
image: my-webapp:latest
read_only: true
tmpfs:
- /tmp
security_opt:
- no-new-privileges:true
- apparmor:docker-default
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
user: "1000:1000"
networks:
- backend
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 1m
timeout: 10s
retries: 3
networks:
backend:
driver: bridge
8. CI/CDパイプラインでのセキュリティ統合
セキュリティチェックをCI/CDパイプラインに組み込んで、脆弱なコンテナがデプロイされるのを防ぎます。
# GitHubActionsでのセキュリティスキャン例
name: Docker Security Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build image
run: docker build -t my-app:${{ github.sha }} .
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
image-ref: 'my-app:${{ github.sha }}'
format: 'table'
exit-code: '1'
ignore-unfixed: true
severity: 'CRITICAL,HIGH'
9. セキュリティポリシーの実装
Content Trust (DCT) の有効化
署名済みイメージのみを使用するように設定します。
# Content Trustの有効化
export DOCKER_CONTENT_TRUST=1
docker pull nginx:latest
セキュリティポリシーの自動化
Open Policy Agent (OPA) などのツールを使用して、セキュリティポリシーを自動的に適用します。
# OPAによるポリシー適用の例
package docker.authz
default allow = false
allow {
input.User == "admin"
input.RequestMethod == "GET"
}
allow {
input.RequestPath == "/v1.40/containers/json"
input.RequestMethod == "GET"
}
10. 実践的なチェックリスト
最後に、以下のチェックリストを使用して、Dockerコンテナのセキュリティレベルを評価しましょう:
- 最小特権の原則を遵守しているか
- 最新のセキュリティパッチが適用されているか
- コンテナイメージに脆弱性がないか
- 非特権ユーザーでコンテナを実行しているか
- 機密データがコンテナ内に保存されていないか
- ネットワークアクセスが適切に制限されているか
- リソース制限が設定されているか
- セキュリティ監視が実装されているか
- CI/CDパイプラインにセキュリティスキャンが組み込まれているか
- コンテナオーケストレーション環境(Kubernetes等)のセキュリティ設定が適切か
まとめ
Dockerコンテナのセキュリティは、単一の対策だけでは確保できません。イメージの選択から設定、監視まで、多層的なアプローチが必要です。本記事で紹介したベストプラクティスを実践することで、コンテナ環境のセキュリティリスクを大幅に軽減し、より安全なアプリケーション運用が可能になります。
セキュリティは継続的なプロセスであることを忘れずに、定期的な評価と改善を行いましょう。最新のセキュリティ脅威に常に注意を払い、必要に応じて対策を更新することが重要です。
コメント