【Docker】(1)Dockerの役割を初心者向けに解説|Windows・Linux両対応のコード生成を例にDockerfile・Image・Containerの違いを理解する

未分類

メタディスクリプション案

Dockerの役割を初心者向けにやさしく解説。WindowsとLinuxの両方で動くコード生成を例に、generate.py、Dockerfile、Image、Container、Volume、環境変数の違いと関係を整理します。

URLスラッグ案

/docker-role-code-generation-windows-linux-basics/


Dockerの役割を初心者向けに解説

Windows・Linux両対応のコード生成を例に、Dockerfile・Image・Containerの違いを理解する

はじめに

Docker を学び始めたとき、多くの人が同じところで引っかかります。

Docker は何をしているのか
Image と Container は何が違うのか」
Container はインスタンスなのか、場所なのか

このあたりが曖昧なままだと、Docker Compose、環境変数、ボリュームマウント、API キーの受け渡しまで全部がモヤモヤして見えてきます。

この記事では、Windows と Linux のどちらでも動かしたい超シンプルなコード生成ツールを題材にして、Docker の役割を整理します。
特に、次の点が自然に理解できるようにまとめます。

  • Docker はコード生成そのものではない
  • Image と Container の実体は何か
  • Container は「場所」なのか「インスタンス」なのか
  • Docker が Windows と Linux の差をどう吸収するのか

Dockerの役割をひとことで言うと

Docker の役割は、アプリを同じ条件で動かせるようにすることです。

たとえば、Python でコード生成ツールを作ったとします。
そのとき Docker を使わないと、こんなことが起こりがちです。

  • Windows では動くのに Linux では動かない
  • Python のバージョンが違う
  • 必要なライブラリが入っていない
  • パスの書き方が OS ごとに違う
  • 自分の PC では動くのに、他人の PC では動かない

Docker は、こうした違いを減らして、**「このアプリはこの環境で動かします」**という実行条件を箱ごとそろえてくれます。

つまり、Docker はコードを書く人でも生成する人でもなく、コードが安定して動く共通の実行環境を作る仕組みです。


まずは超シンプルなコード生成を作る

最初に、Docker の話をいったん横に置いて、単純な Python プログラムを見ます。
次の generate.py は、入力した関数名から Python コードを作るだけの最小例です。

generate.py

function_name = input("作りたい関数名を入れてください: ").strip()generated_code = f"""def {function_name}():
print("Hello from {function_name}")
"""print("\n--- 生成されたコード ---")
print(generated_code)with open("generated.py", "w", encoding="utf-8") as f:
f.write(generated_code)print("generated.py に保存しました。")

たとえば hello_app と入力すると、次のようなコードが出力されます。

def hello_app():
print("Hello from hello_app")

generate.pyコード生成を行うアプリ本体です。


Dockerfileとは何か

次に、その generate.py を Docker で動かすための設定を書きます。

Dockerfile

FROM python:3.12-slimWORKDIR /appCOPY generate.py /app/CMD ["python", "generate.py"]

これは次の意味です。

  • Python 3.12 が入った軽量な土台を使う
  • コンテナ内の作業場所を /app にする
  • generate.py/app にコピーする
  • コンテナ起動時に python generate.py を実行する

ここで重要なのは、Dockerfile は実行環境そのものではなく、実行環境を作るための設計書だということです。


Dockerfile・Image・Containerの関係

Docker の基本の流れは次の 1 行でかなり整理できます。

Dockerfile → build → Image → run → Container

この順番です。

  1. Dockerfile を書く
  2. docker build で Image を作る
  3. docker run で Container を起動する

この 3 つを混同しないことが、Docker 理解の第一歩です。


Imageとは何か

Image は、Container を作るための完成済みテンプレートです。

たとえると、

  • Dockerfile = 設計図
  • Image = 設計図どおりに作られたモデル
  • Container = そのモデルから実際に起動した実物

です。

ここでよくある疑問が、
「Image の実体はファイルなのか」
というものです。

結論から言うと、単純な 1 個のファイルではありません。

Dockerfile はテキストファイルですが、Image は Docker 内部に保存される

  • ファイルシステムのレイヤー
  • 設定情報
  • メタデータ

の集合です。

つまり Image は、「この環境はこういう中身です」という完成済みの静的テンプレートです。
動いてはいませんが、いつでも Container を起動できる準備ができた状態です。


Containerとは何か

Container は、Image から実際に起動された実行中の環境です。

ここで多くの人が感じる疑問がこれです。

Container はインスタンスなのか。
それとも場所なのか。

答えは、インスタンスと考えてよい。ただし、単なるオブジェクトのインスタンスより少し広い意味を持つです。

Container は、

  • Image をもとに起動される
  • 独立したファイルシステムを持つ
  • 独立した環境変数を持つ
  • 独立したプロセスとして動く

ので、Image の実行インスタンスとして理解するのが自然です。

一方で、「場所」と表現されることがあるのは、その中に /app のような作業ディレクトリがあり、ファイルやプロセスが隔離されて見えるからです。

つまり初心者向けには、

Container = 小さな独立した実行部屋

と覚えるとわかりやすいです。
少し正確に言うなら、

Container = Image をもとに起動された隔離済みの実行インスタンス

です。


Containerはフォルダなのか

これも非常によくある勘違いです。

Container はフォルダそのものではありません。
ただし、Container の中にはフォルダ構造があります。

たとえば今回の Dockerfile には、こうあります。

WORKDIR /app

このため、Container の中には /app という作業場所ができます。
また、COPY generate.py /app/ によって generate.py もそこに入ります。

この見え方のせいで、Container 全体がフォルダのように思えます。
しかし Container の本体はもっと広いもので、

  • Image の読み取り専用レイヤー
  • Container 専用の書き込みレイヤー
  • 起動中のプロセス
  • ネットワーク設定
  • 環境変数

を含んだ実行環境です。

なので、フォルダを含むが、Container 自体はフォルダではないという理解が正確です。


ImageとContainerの実体をひとつ深く理解する

ここを少しだけ具体的にすると、Docker が一気に見えやすくなります。

Image の実体

Image は Docker の内部に保存される読み取り専用のレイヤー集合です。
たとえば今回なら、そこには次のようなものが含まれます。

  • Python 3.12 の実行環境
  • 必要最小限の Linux ベース
  • /app/generate.py
  • 起動コマンド情報

Image は「完成済み」ですが、まだ動いていません。

Container の実体

Container は、その Image の上に書き込み可能な層を 1 枚追加して起動されたものです。
その中で実際に

  • python generate.py が動き
  • 入力を受け取り
  • generated.py を書き出し
  • プロセスとして存在する

という状態になります。

つまり、

  • Image = 静的なひな形
  • Container = 動的に動いている実体

です。


実際に動かしてみる

まずは Image を作ります。

docker build -t simple-codegen .

これは、カレントフォルダの Dockerfile をもとに simple-codegen という名前の Image を作るコマンドです。

次に Container を起動します。

docker run -it simple-codegen

すると、Image から 1 つの Container が起動し、その中で generate.py が実行されます。

つまり、この時点でやっていることは、

  • generate.py を直接動かしているのではなく
  • generate.py が入った Image から Container を起動し
  • その Container の中で generate.py を走らせている

という構造です。


生成されたファイルはどこに保存されるのか

この例では、generate.pygenerated.py を出力します。
では、そのファイルはどこにできるのでしょうか。

何も設定しなければ、Container の中です。

つまり、ホスト側の Windows や Linux のフォルダに、必ずしもそのまま見えるわけではありません。
そこで使うのが Volume マウント です。

Linux / macOS

docker run -it -v $(pwd):/app simple-codegen

Windows PowerShell

docker run -it -v ${PWD}:/app simple-codegen

これで、ホスト側の現在フォルダと、Container 内の /app がつながります。
すると、Container 内で作った generated.py がホスト側にも見えるようになります。

この仕組みを見ると、Container は単なるフォルダではなく、ホストとは別の実行環境でありながら、必要な部分だけ共有できる仕組みだとわかります。


WindowsとLinuxの両方で使える理由

Docker が便利なのは、ホスト OS が違っても、Container の中をかなり同じ状態にそろえられることです。

たとえば今回の例では、

  • Windows 上の Docker
  • Linux 上の Docker

のどちらで動かしても、Container の中は

  • Python 3.12
  • /app
  • generate.py

という同じ構成になります。

もちろんボリューム指定の細かい書き方など、外側には OS 差が少し残ります。
ただ、アプリ本体が動く核心部分を共通化できるのが Docker の大きな価値です。

つまり Docker は、Windows 用と Linux 用で別々に苦労する部分を減らして、アプリの本質に集中しやすくする仕組みです。


環境変数とAPIキーの理解にもつながる

Docker を使って LLM ベースのコード生成を動かすとき、よく OPENAI_API_KEY を使います。
このときも考え方は同じです。

Docker は API キーを勝手に探し回る魔法の仕組みではありません。
Docker は、ホスト側で用意した環境変数を Container に渡すだけです。

たとえば Compose では、次のように書きます。

services:
app:
build: .
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}

これは、ホスト側の OPENAI_API_KEY を Container 側にも渡す、という意味です。

ここでも Docker の役割は変わりません。
アプリ本体を作ることではなく、アプリが必要とする実行条件をそろえて受け渡すことです。


よくある誤解を最後に整理する

Docker を学び始めたばかりの段階では、次のような誤解が起こりやすいです。

Docker がコード生成している

違います。
コード生成しているのは generate.py のようなアプリ本体です。

Dockerfile がそのまま動く

違います。
Dockerfile は設計書で、まず Image に build されます。

Image はただのファイル

違います。
Docker 内部に保存されるレイヤーや設定情報の集合です。

Container はフォルダ

違います。
フォルダ構造を含む実行環境です。

Container は単なる場所

半分だけ正しいです。
作業場所はありますが、本質は 起動中の隔離された実行インスタンス です。


まとめ

Docker の役割は、コード生成ロジックそのものを担うことではなく、そのロジックを同じ条件で安定して動かすことです。

今回の例では、役割分担は次のとおりです。

  • generate.py
    コード生成を行うアプリ本体
  • Dockerfile
    そのアプリをどういう環境で動かすかを定義する設計書
  • Image
    設計書から作られた、静的な実行テンプレート
  • Container
    Image をもとに起動された、動的な実行環境

この 4 つが整理できると、Docker Compose、Volume、環境変数、API キー受け渡しまで一気につながって見えてきます。

最短で覚えるなら、次の 4 行で十分です。

  • generate.py はアプリ本体
  • Dockerfile は設計書
  • Image は実行テンプレート
  • Container は起動中の実行インスタンス

これが腹落ちすると、Docker はかなり扱いやすくなります。


コメント

タイトルとURLをコピーしました