2026年8月10日
2026年8月10日
Dockerセキュリティのベストプラクティス
はじめに
Dockerはアプリケーション配布のデファクトスタンダードになった一方で、デフォルト設定のまま運用すると特権コンテナ・古いベースイメージ・公開ポートなど、攻撃面が広がりやすい仕組みでもあります。コンテナはホストカーネルを共有するため、root権限で動くコンテナの脆弱性がそのままホスト侵害につながる可能性もあります。
本記事では、Dockerをサーバーで本番運用する際に最低限押さえておきたいセキュリティ設定を、イメージビルド・コンテナ実行・デーモン・ネットワークの4つの観点から具体例とともに紹介します。
「Dockerfileの書き方」「docker runのオプション」「daemon.jsonのチューニング」を順に整えることで、CIS Docker Benchmarkの主要項目をクリアできるレベルを目指します。
症状・背景
- ベースイメージに既知CVEが含まれており放置されている
- コンテナがroot権限で動作し、ホストの
/をbindマウントしている - Docker APIソケットが認証なしで外部公開されている
- ログにcryptojackerなど不審なコンテナの痕跡がある
手順・設定方法
ステップ1: 最小・最新のベースイメージを使う
攻撃面を減らすため、できる限り小さく新しいイメージを採用します。
# 公式のslim/alpine系イメージを利用
docker pull python:3.12-slim
# Trivyで既知の脆弱性をスキャン
trivy image --severity HIGH,CRITICAL python:3.12-slim
# docker scoutでも同様にスキャン可能
docker scout cves python:3.12-slim
ステップ2: Dockerfileで非rootユーザーを使う
コンテナ内のプロセスをroot以外で動かします。
# Dockerfile例: 非rootユーザー作成
cat > Dockerfile <<'EOF'
FROM node:20-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --chown=app:app . .
USER app
CMD ["node", "server.js"]
EOF
# ビルドして実行ユーザーを確認
docker build -t myapp:secure .
docker run --rm myapp:secure id
ステップ3: 実行時のCapability・権限を制限
docker runのセキュリティオプションで権限を絞り込みます。
# 不要なCapabilityを全て削除し必要なものだけ追加
docker run -d --name web \
--cap-drop=ALL --cap-add=NET_BIND_SERVICE \
--read-only --tmpfs /tmp \
--security-opt no-new-privileges \
-p 8080:8080 myapp:secure
# 特権モード(--privileged)は原則禁止
# やむを得ず使う場合は影響範囲を把握すること
# ホストのdocker.sockをマウントしない(DooD回避)
# 必要ならsysbox等を検討
ステップ4: デーモン・ネットワークの設定
Dockerデーモン側でもセキュリティを強化します。
# /etc/docker/daemon.json でlive-restoreやログサイズ制限を設定
sudo tee /etc/docker/daemon.json > /dev/null <<'EOF'
{
"live-restore": true,
"userland-proxy": false,
"no-new-privileges": true,
"log-driver": "json-file",
"log-opts": {"max-size": "10m", "max-file": "3"}
}
EOF
# 設定反映
sudo systemctl restart docker
# 2375/tcpなど平文APIは絶対に公開しない
sudo ss -tlnp | grep -E "2375|2376"
注意事項
--privilegedや--pid=host、--network=hostは本当に必要な場合のみ使用し、利用理由をドキュメント化します- ホストのDockerソケット(
/var/run/docker.sock)をマウントしたコンテナはホストのroot権限と等価です - イメージのタグは
latestではなく明示的なバージョン・ダイジェスト(@sha256:...)で固定します - secretは環境変数ではなく Docker secrets や外部Vaultで管理し、
docker inspectに残らないようにします
まとめ
1. 最小ベースイメージ: alpine/slim系を選び、Trivy・docker scoutで定期スキャン
2. 非rootで動かす: Dockerfileに USER を明記し、コンテナ内rootを避ける
3. 権限を絞る: --cap-drop=ALL + no-new-privileges + --read-only を基本に
4. デーモン強化: daemon.json でログ制限・live-restore・userland-proxy無効化
5. API公開禁止: 2375/tcp 平文APIは絶対に外部公開しないこと
関連記事: