GenAIでDockerfileを作成する方法 

この進行中の Docker Labs GenAI シリーズ AI開発者ツールのエキサイティングな空間を探求します。 Dockerでは、誇大広告を使わずにオープンに探求できる広大な範囲があると信じています。 私たちは探索を共有し、開発者コミュニティとリアルタイムで協力します。 開発者はGitHub Copilotなどのオートコンプリートツールを採用し、チャットを使用していますが、AIツールには、ソフトウェアライフサイクル全体を通じて、より具体的なタスクやインターフェイスを支援する大きな可能性があります。 したがって、私たちの探求は広範囲になります。 私たちはオープンソースとしてリリースしますので、あなたも私たちと一緒にプレイし、探索し、ハックすることができます。

ジェネレーティブAIをより効果的に活用する方法を学ぶと、Dockerfileの生成に戻るタスクの1つに戻ります。 AIアシスタントにツールを装備できるからこそ、コンテンツ生成の問題をLLMとツールの間の相互作用として捉え直すことができるのでしょうか?

2400x1260 Docker Labs Genai

ChatGPT にプロジェクトの Dockerfile の作成を依頼すると、ChatGPT はあなたとの会話を開始し、プロジェクトから詳細を抽出するように求めます (図 1)。

chatgptとの会話のスクリーンショットは、「このプロジェクトのDockerfileを書いてもらえますか?」という質問から始まります。
図 1: ChatGPTにDockerfileの作成を手伝ってもらう。

ただし、アシスタントにツールを装備して、プロジェクトから直接この情報を抽出することもできます。 ユーザーに尋ねる代わりに、アシスタントがツールを要求することができます。

ツールの使用

ここでは、別のフレーミングを紹介します。 アシスタントが Dockerfile の作成を求められたときに、2 つの高レベルの指示をアシスタントに示してみましょう。

* First, analyze the project to determine how it should be built. 
* Once the analysis is complete, create a Dockerfile to build that project.

これらの新しいプロンプトに加えて、LLM には 2 つの関数定義も提供します。

[{"name": "analyze_project",
 "description": "Analyze a project to determine how it should be built"},
 {"name": "write_files",
  "description": "write a set of files to my project",
  "parameters": {...}}]

これら 2 つの機能により、アシスタントはユーザーのプロジェクトに直接 Dockerfile を書き込むのに十分な権限を持ちます。 残念ながら、ベストプラクティスがなければ、実際のDockerfileコンテンツは決して良くありません。 

これは、アシスタントがプロジェクトの種類を認識しているが、それ以外はあまり知らない場合に生成される Dockerfile の種類の例です。

# Use the official Node.js image from the Docker Hub
FROM node:14

# Create and change to the app directory
WORKDIR /usr/src/app

# Copy the package.json and package-lock.json files
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose the port your app runs on
EXPOSE 3000

# Define the command to run your app
CMD ["npm", "start"]

この例では、いくつかの標準的な Dockerfile オーサリングの問題を示しています。

  • 古い基本イメージを使用しています。
  • マルチステージビルドは採用していません。
  • キャッシュマウントなどの新しいDocker機能をスキップします。

では、どうすればいいのでしょうか? NPM プロジェクトの Dockerfile を作成するためのベスト プラクティスをいくつか抽出してみましょう。

Write Dockerfiles for NPM projects using three stages.  Do these three steps sequentially.
* the first node dependencies stage should be called "deps" 
  and it should fetch the runtime dependencies using npm ci
  with the --omit=dev flag.
* The second Dockerfile stage should be called build  and it should be based on the deps stage. 
  It should run npm ci and then npm build
* The third Dockerfile stage should select a base image 
  that is recommended by Scout and use that in the FROM line.
  This stage should do then do three things.
	1. it copies the node_modules directory from the deps stage.
    2. it copies the dist directory from the build stage.
    3. it then runs npm start

If you need to use a RUN statement containing npm ci always 
add the argument --mount=type=cache,target=/root/.npm to the RUN instruction.  
The --mount argument should be placed between the word RUN and the npm command.
This will cache the npm packages in the docker build cache and speed up the build process.
After selecting a base image, get a recommended tag. This recommendation will change over time but start with what is recommended now.

このコンテンツは、NPM プロジェクトのコンテキストで発生するすべての会話に含まれます。 また、3 つ目の関数も追加します。

[{"name": "docker_scout_tag_recommendation",
  "description": "get a recommended tag",
  "parameters": {...}}]

この記事を書いている時点では、アシスタントからの出力は次のとおりです。 この例では、アシスタントは GPT-4 モデルを使用していますが、他のローカル モデルでも同じ結果が得られています。

# Stage 1 - Downloading dependencies
FROM node:22-slim AS deps
WORKDIR /usr/src/app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm npm ci --omit=dev

# Stage 2 - Building application
FROM deps AS build
RUN --mount=type=cache,target=/root/.npm npm ci && npm build

# Stage 3 - Using a recommended base image from Scout
FROM node:22-slim
WORKDIR /usr/src/app
COPY --from=deps /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/dist ./dist
CMD [ "npm", "start" ]

これは大きな改善です。 この改善の基盤となる 3 つの入力を以下に示します。

  • アシスタントが使用するべきプロセスを固定する2つのトップレベルの指示:
* First, analyze the project to determine how it should be built. 
* Once the analysis is complete, create a Dockerfile to build that project.
  • Docker 固有のベスト プラクティスをまとめた Markdown コンテンツ。
  • 関数 (analyze_project, write_filesdocker_scout_tag_recommendation)。

ベストプラクティスを蒸留することは確かに簡単ではありませんが、少しでも大きな効果を上げることができます。それでも、これがコードテンプレートを使用するだけの改善と見なすことができるかどうかを知るのはまだ困難です。 私たちの継続的な調査は、ジェネレーティブAIがこれらのモデルを新しい知識、新機能、新しいプロジェクトタイプにより簡単に適応させるのに役立つかどうかに焦点を当てています。

会話ループ

ここでエージェント間で渡される実際のメッセージを確認することは有益です。 特に興味深いのは、アシスタントとツールエージェントの相互作用です。 交換の終わり近くで、 write_files ツールが無効なJSONファイルを渡されたと文句を言うという予期しない展開があります。 この場合、アシスタントは実際には無効なJSONを生成しており、ツールが文句を言うのは正しかったです。 ただし、アシスタントはこのエラーにも対応して、JSONを修正し、ツールを再度呼び出しました。 それは 台本にありませんでした

台本のない瞬間のもう一つの興味深い例は、アシスタントからの最後のメッセージです。 アシスタントは、タスクが完了したと正しく判断し、完了した作業とその理由の要約を生成します。

写し

制:

あなたは、プロジェクトの Dockerfile の作成を専門とするアシスタントです。 あなたは専門家であり、彼らのプロジェクトについて知っているので、推奨事項について明確にしてください。

利用者:

  • まず、プロジェクトを解析して、どのようにビルドすべきかを決定します。
  • 分析が完了したら、Dockerfile を作成してそのプロジェクトをビルドします。

助手:

[{:function {:arguments "{}" :name "analyze_project"}}]

ツール (analyze_project):

これはNPMプロジェクトです。

制:

NPM プロジェクトの Dockerfile は、3 つのステージを使用して記述します。 この3つのステップを順番に行う...

...

…(簡潔にするためにシステムプロンプトは除外されています)..

...

助手:

[{:function {:arguments "{
  \"repository\": \"node\"
}"
             :name "docker_scout_tag_recommendation"}}]

ツール (docker_scout_tag_recommendation):

22-スリム

助手:

[{:function {:arguments "{
  \"files\": [
    {
      \"path\": \"Dockerfile\",
      \"content\": `
# Stage 1 - the build process
FROM node:22-slim AS deps
WORKDIR /usr/src/app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm npm ci --omit=dev
# Stage 2 - the production environment
FROM deps AS build
RUN npm ci && npm run build
# Stage 3 - the production environment
FROM node:22-slim
WORKDIR /usr/src/app
COPY --from=deps /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/dist ./dist
CMD [ \"npm\", \"start\" ]`,
      \"executable\": false
    }
  ]
}"
             :name "write_files"}
  :id "call_6VVCLiXcIBNyEGPQwftR7xEV"}]

道具:

関数呼び出し write_files 失敗した呼び出しがゼロ以外のコードで終了しました (1): ゼロ以外のコードで終了した呼び出し (1): #error {\r\n :cause 予期しない文字 (''')

助手:

誤りをお詫び申し上げます。 もう一度試してみましょう。

[{:function {:arguments "{
  \"files\": [
    {
      \"path\": \"Dockerfile\",
      \"content\": \"FROM node:22-slim AS deps\\nWORKDIR /usr/src/app\\nCOPY package*.json ./\\nRUN --mount=type=cache,target=/root/.npm npm ci --omit=dev\\n\\nFROM deps AS build\\nRUN npm ci && npm run build\\n\\nFROM node:22-slim\\nWORKDIR /usr/src/app\\nCOPY --from=deps /usr/src/app/node_modules ./node_modules\\nCOPY --from=build /usr/src/app/dist ./dist\\nCMD [ \\\"npm\\\", \\\"start\\\" ]\",
      \"executable\": false
    }
  ]
}"
             :name "write_files"}}]

ツール (write_files):

1ファイルを書いた: Dockerfile

助手:

私はあなたのNPMプロジェクトのDockerfileを書きました。 プロジェクトフォルダにあります。 この Dockerfile は、多段階のビルド プロセスを使用して、Docker コンテナー内でアプリケーションを効率的にビルドして実行します。 最初のステージではランタイムの依存関係をフェッチし、2 番目のステージではアプリケーションをビルドし、最後のステージではアプリケーションを実行します。 さらにサポートが必要な場合はお知らせください。

概要

ジェネレーティブ AI アシスタントが Dockerfile コンテンツを生成する能力を向上させるために、ツールとスタック固有のベスト プラクティス コンテンツの両方を主要なイネーブラーとして特定しました。 これらの要素をジェネレーティブAIベースのアシスタントに組み込むことは、コードテンプレートの代替として機能します。 このアプローチにより、新しいプロジェクトタイプにより簡単に適応できるかどうかを引き続き評価しています。

いつものように、 公開リポジトリ をフォローして、お気軽にお問い合わせください。 このブログ記事で説明した内容はすべて、自分のプロジェクトで試すことができます。

Docker での取り組みの詳細については、 ニュースレターを購読してください。

さらに詳しく