【無料ツール】画像をPDFに変換するPhotoPDF Appを公開しました!

【第4回】コンテナ構築を生成AIで極める:セキュアなDockerfileとdocker-compose.ymlの自動生成

記事内に広告が含まれています。

現代のインフラ環境において、アプリケーションの実行環境をカプセル化する「コンテナ技術(Docker / Podman)」は、開発から本番運用に至るまでのデファクトスタンダードです。環境への依存をなくし、デプロイを高速化するコンテナですが、その心臓部である Dockerfiledocker-compose.yml の記述品質が、システムのパフォーマンスとセキュリティに直結します。

「とりあえず動く」コンテナを作るのは簡単ですが、「イメージサイズが数GBに肥大化している」「root権限でプロセスが動いている」「不要なパッケージのキャッシュが残存している」といったアンチパターンを抱えたまま本番稼働しているケースが後を絶ちません。プロのインフラエンジニアには、マルチステージビルドや最小権限の原則を適用した「美しくセキュアなコード」が求められます。

本連載「Linuxエンジニアのための生成AI」第4回となる今回は、生成AIを利用して、ベストプラクティスに完全準拠した Dockerfiledocker-compose.yml を瞬時に生成するプロンプトエンジニアリングと、構築したコンテナの脆弱性を監査するテスト手法について徹底解説します。

コウ君

リナックス先生!最近、開発環境用にPHPとMySQLのDockerイメージを作ったんですが、イメージサイズが2.5GBもあって、起動も遅いんです。それに、セキュリティ診断ツールで「rootユーザーで実行されている」って警告が出ちゃって……。直すのが難しくて心が折れそうです。

リナックス先生

コウ君、それは典型的な「Fatコンテナ(肥満化コンテナ)」のアンチパターンね!レイヤー構造の理解や非root化のパーミッション調整は、人間が手作業でやると泥沼にハマりやすい領域よ。でも安心して。生成AIに「プロの制約」を課して書かせれば、サイズを数十分の一にしつつ、セキュリティも堅牢なDockerfileが一瞬で完成するわ!


[PR]

1. コンテナ構築における生成AIの圧倒的優位性

Infrastructure as Code (IaC) の一種である Dockerfiledocker-compose.yml は、Ansibleと同様に「宣言的」な性質を持ちつつも、Linuxカーネルの仕組み(名前空間、cgroups、オーバーレイファイルシステム)と密接に結びついています。この領域で生成AIを活用するメリットは計り知れません。

1-1. 複雑化するベストプラクティス(レイヤーとキャッシュ)の網羅

Dockerfileの各命令(RUN, COPY, ADD)は、それぞれ独立した「レイヤー(層)」を作成します。パッケージをインストールした後に別の RUN コマンドでキャッシュを削除しても、前のレイヤーにはキャッシュが残ったままとなり、結果としてイメージサイズが肥大化します。
生成AI(特にClaude 3.5 SonnetやGPT-4o)は、これらの方言や特性を深く学習しています。例えば「dnfのキャッシュを削除する」「複数のコマンドを && で繋いで1つのレイヤーにまとめる」といったベストプラクティスを、指示しなくても自律的に適用してくれます。

1-2. AlmaLinux 9(Podman)とDockerの互換性への対応

AlmaLinux 9をはじめとする最近のRHEL系ディストリビューションでは、Dockerデーモンを使用しない「Podman」が標準コンテナエンジンとして採用されています。PodmanはDockerとコマンドレベルの互換性(alias docker=podman)を持っていますが、ルートレス(非root)コンテナの実行など、セキュリティ面でより厳格な挙動を示します。
プロンプト内で「ターゲット環境はAlmaLinux 9であり、Podmanでの実行を前提とする」と明記することで、AIはパーミッションの競合を回避する堅牢なユーザー名前空間の設定を提案してくれます。

⚠️ プロの視点:マルチステージビルドの重要性
ビルド環境(コンパイラ等が含まれる重い環境)と、本番実行環境(最小限のランタイムのみ)を分離する「マルチステージビルド」は、現代のコンテナ運用において必須です。AIにこれを指示するだけで、GB単位のイメージが数十MBまで圧縮されることも珍しくありません。

2. セキュアで軽量なDockerfileを生成するプロンプト技術

AIに「良いDockerfile」を書かせるためには、コンテナ設計の「要件」だけでなく「守るべき規約」を厳格に言語化する必要があります。

2-1. 素人のプロンプト(アンチパターン)が生む悲劇

❌ 素人のプロンプト(失敗例)

PHPのWebアプリを動かすためのDockerfileを作って。

このプロンプトでは、AIは「とりあえず動く」ことを最優先し、公式の php:latest (Debianベースの巨大なイメージ)を使用し、rootユーザーでプロセスを実行し、開発用のデバッグツールまで詰め込んだ「Fatコンテナ」を出力します。これを本番環境にデプロイするのはセキュリティインシデントの元です。

2-2. 現場で使える実践的プロンプト・テンプレート

⭕ プロのプロンプト(成功例)

あなたはプロのインフラエンジニア・SREです。
以下の要件を満たし、本番環境(Production)での稼働に耐えうる堅牢な `Dockerfile` を作成してください。

【対象アプリケーション】
- PHP 8.2 (PHP-FPM) で稼働するカスタムWebアプリケーション
- ホストOS(コンテナの稼働環境): AlmaLinux 9 (Podman環境)

【コーディング制約・ベストプラクティス(厳守事項)】
1. ベースイメージは公式の軽量イメージ(例: `php:8.2-fpm-alpine` または `almalinux:9-minimal`)を使用すること。
2. マルチステージビルドを採用し、Composerの依存関係インストール用ステージと、本番実行用ステージを分離すること。
3. セキュリティのため、コンテナ内のプロセスは必ず非rootユーザー(例: `www-data` や `appuser`)で実行すること。
4. `RUN` コマンドは極力連結し、パッケージマネージャーのキャッシュ(例: `dnf clean all` や `apk cache clean`)は同一レイヤー内で必ず削除し、イメージサイズを最小化すること。
5. コンテナのタイムゾーンを「Asia/Tokyo」に設定すること。
6. 出力はDockerfileのコードのみとし、各行の意図をコメントアウトで分かりやすく記述すること。
リナックス先生

プロンプトの肝は「マルチステージビルドの強制」と「非rootユーザー(最小権限)の指定」、そして「キャッシュの同一レイヤ削除」よ。この3つを明記するだけで、AIから出力されるコードの品質がジュニアレベルからシニアレベルに跳ね上がるわ!

2-3. PHP-FPM環境の最適化Dockerfile出力例と解説

上記の「プロのプロンプト」をClaude 3.5 Sonnet等の優秀なLLMに入力した場合、以下のような高品質なDockerfileが出力されます。

# ==========================================
# Stage 1: Build (Composerによる依存関係の解決)
# ==========================================
FROM composer:2.7 AS builder

WORKDIR /app
# 依存関係のキャッシュを有効活用するため、まずはcomposerファイルのみをコピー
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist

# ソースコード全体をコピーし、オートローダーを最適化
COPY . .
RUN composer dump-autoload --optimize

# ==========================================
# Stage 2: Production (本番実行環境)
# ==========================================
FROM php:8.2-fpm-alpine

# タイムゾーンの設定と必要なPHP拡張のインストール(キャッシュは即時削除)
RUN apk add --no-cache tzdata \
    && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
    && echo "Asia/Tokyo" > /etc/timezone \
    && apk del tzdata \
    && docker-php-ext-install pdo_mysql opcache \
    && rm -rf /tmp/* /var/cache/apk/*

WORKDIR /var/www/html

# Stage 1でビルドした成果物のみを本番イメージにコピーし、所有権を非rootに変更
COPY --from=builder --chown=www-data:www-data /app /var/www/html

# 非rootユーザー (www-data) に切り替え
USER www-data

# FPMポートの公開
EXPOSE 9000

CMD ["php-fpm"]
コウ君

おおっ!ComposerのコンテナとPHP-FPMのコンテナが AS builder で明確に分かれてる!これなら最終的なイメージにはComposer自体やビルドツールが含まれないから、サイズが劇的に小さくなるし、攻撃されるリスクも減りますね。USER www-data でしっかり非root化もされてる!

3. 複数コンテナのオーケストレーション(docker-compose.yml)の自動生成

単一のDockerfileが完成したら、次はWebサーバー(Nginx)、アプリケーション(PHP-FPM)、データベース(MySQL / MariaDB)を連携させる docker-compose.yml の作成です。

3-1. ネットワーク分離とボリューム永続化の要件定義

データベースのデータ永続化や、コンテナ間のネットワーク分離も、AIに要件として渡すことで正確に構成してくれます。

プロンプト例:

上記で作成したPHP-FPMのDockerfileを用いて、以下の構成の `docker-compose.yml` を作成してください。
1. Nginxコンテナ (port: 80)
2. PHP-FPMコンテナ (先ほどのDockerfileをビルド)
3. MySQL 8.0コンテナ
【制約】
- MySQLのデータは名前付きボリューム(Named Volume)で永続化すること。
- NginxとPHPは「frontend-network」、PHPとMySQLは「backend-network」に属するようにネットワークを分離し、NginxからMySQLへ直接アクセスできないようにすること。
- DBのパスワード等の機密情報は、`.env` ファイルから読み込む設定(`${DB_PASSWORD}`)にすること。

3-2. Healthcheckと依存関係(depends_on)の厳格化

コンテナの起動順序はインフラの永遠の課題です。「DBが立ち上がる前にアプリが起動してコネクションエラーになる」現象を防ぐため、AIが生成したコードには強力な healthcheck が組み込まれます。

# AIが出力するdocker-compose.ymlの抜粋(MySQLとPHPの連携部)
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
    networks:
      - backend-network
    volumes:
      - db-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  app:
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      mysql:
        condition: service_healthy # 単なる起動ではなく、DBの準備完了を待つ
    networks:
      - frontend-network
      - backend-network

condition: service_healthy を付与することで、DBがリクエストを受け付けられる状態になって初めてアプリケーションコンテナが起動します。AIはこうしたオーケストレーションの作法も熟知しています。

4. AI生成コンテナのコード監査とセキュリティテスト

AIが出力した Dockerfiledocker-compose.yml をそのままデプロイするのではなく、第3回のAnsible編と同様に「システム的な監査」を通すプロセスが不可欠です。

4-1. HadolintによるDockerfileの静的解析

Hadolint は、Dockerfileのベストプラクティスを検証するための静的解析ツール(リンター)です。AlmaLinux 9環境でAIの出力をチェックしましょう。

# Hadolintのコンテナを使ってDockerfileをチェック
podman run --rm -i docker.io/hadolint/hadolint < Dockerfile

もし「DL3018: Pin versions in apk add. Instead of `apk add ` use `apk add =`(パッケージのバージョンを固定せよ)」といった警告が出た場合、そのメッセージをAIにフィードバックし、「Hadolintの警告を修正して」と指示するだけで、自律的にコードを改善してくれます。

4-2. Trivyによるコンテナイメージの脆弱性(CVE)スキャン

Dockerfileが完成し、イメージをビルドした後は、Aqua Security社が提供するオープンソースの脆弱性スキャナ「Trivy」を使用して、OSパッケージやライブラリに既知の脆弱性(CVE)が含まれていないか検査します。

# Trivyのインストールとイメージのスキャン
sudo dnf install -y https://github.com/aquasecurity/trivy/releases/download/v0.48.0/trivy_0.48.0_Linux-64bit.rpm

# ビルドしたイメージのスキャン(CRITICAL, HIGHのみを表示)
trivy image --severity HIGH,CRITICAL my-php-app:latest

ここで脆弱性が発見された場合は、ベースイメージのタグを新しいものに変更するか、パッケージのアップデートコマンドをDockerfileに追記するようAIに指示を出します。

⚠️ セキュリティの絶対原則とコンプライアンス
AIは常に最新の脆弱性データベースを持っているわけではありません(学習データのカットオフ日があるため)。したがって、AIに「脆弱性のないコードを書いて」と頼むだけでは不十分です。「AIが書き、Trivyが監査し、エンジニアが承認する」という多層的な防御(Defense in Depth)プロセスを構築してください。

5. 第4回の総まとめと次回予告

本記事では、生成AIを用いてベストプラクティスに完全準拠した Dockerfiledocker-compose.yml を自動生成するプロンプト技術と、HadolintやTrivyを用いたコンテナのセキュリティ監査手法について解説しました。

コンテナの最適化(マルチステージビルドや非root化)は、記法が複雑で手作業ではエラーになりやすい領域ですが、要件を正確にプロンプト化することで、AIは完璧なアシスタントとして機能します。出力されたコードをそのまま信じるのではなく、静的解析ツールと組み合わせて品質を担保する「AI駆動のIaC運用」をぜひ現場に取り入れてみてください。

次回の【第5回】生成AIを用いたZabbix/Prometheus監視アラートの自動解析とインシデント対応では、インフラ運用において最もストレスフルな「深夜のアラート対応」をテーマに、監視ツールから飛んでくる難解なエラーメッセージをAIに自動解析させ、解決策の一次切り分けを自動化する実践的なスクリプトを構築します。お楽しみに!

▼ 【コンテナのテスト・ビルド環境を構築しよう】 ▼

Podman/Dockerを快適に動かす
「高コスパおすすめVPS」

VPSランキングを見る

最新のコンテナ技術を活かして飛躍
「ITエンジニア専門転職」

転職エージェントを見る

[PR]

💡 サーバー構築やコマンドの練習には、VPSが圧倒的におすすめです

手元のパソコンや大切なメイン環境で検証を行うと、設定ミスでシステムを壊してしまったり、不要なパッケージが溜まって動作が不安定になるリスクがあります。

もしあなたが実務レベルのスキルを最短で身につけたいのであれば、月額ワンコインから使えて、失敗しても数分で初期状態にリセットできるVPS(仮想専用サーバー)を利用するのが、プロも実践する最も確実で安全な学習方法です。

▼ プロも推奨するVPS環境はこちら ▼

生成AI活用
linux工房をフォローする

コメント