【Docker入門】イメージとコンテナの違いから始める:最小ハンズオンで“環境差ゼロ”を体感する

はじめに

Docker は「アプリを動かすための環境ごと、ひとつの箱にまとめる」ための仕組みです。開発中は動いたのに本番で動かない、チームメンバーの PC ごとに Node や Python のバージョンが違ってつらい、DB だけローカルに入れるのが面倒……こうした“環境差”の問題を、かなりの割合で片づけてくれます。

ただ、Docker は「コマンドを覚えたら終わり」ではありません。イメージとコンテナの違い、レイヤーという保存の仕方、ネットワークやボリュームの考え方、ログの扱い、セキュリティの基本。ここを理解しておくと、トラブル対応も設計も一気にラクになります。

この記事は、Docker を初めて触る人が「仕組みを理解しながら、最小の手数で動かせる」ことを狙った入門です。構成は「座学→ハンズオン→まとめ→次のステップ」。ハンズオンはコピペで進められますが、各手順の意味が分かるように解説も厚めにしています。

座学

1) Dockerが得意なこと:環境差の吸収と“動く状態”の配布

アプリは、コードだけでは動きません。ランタイム(Node/Python/Java)、OS 由来の依存(証明書、フォント、glibc 等)、ネイティブライブラリ(画像処理や DB ドライバ)、設定ファイル、起動コマンド……これらの組み合わせが “環境” です。

Docker はこの環境を イメージ(image) という形に固め、どこでも同じ状態で実行できるようにします。つまり Docker の価値は「同じものを、同じように動かす」再現性にあります。

  • 開発 → テスト → 本番に渡すとき
  • チームで同じ環境を共有するとき
  • CI で毎回同じ条件でビルド/テストするとき
  • 過去バージョンを確実に再現したいとき

このあたりが主戦場です。

2) “設計図”と“実体”:イメージとコンテナを混ぜない

  • イメージ:実行環境の“設計図+材料”。基本は不変(immutable)として扱う
  • コンテナ:イメージを元に起動した“実体”。動いているプロセス(停止・削除・再作成が前提)

ここで重要なのは、「コンテナは使い捨て」という前提です。コンテナの中に手作業で設定変更を積み上げると、再現不能の“手作り環境”になります。変更は Dockerfile に戻してイメージを作り直す、データは ボリュームに逃がす。この癖がつくと運用が一気に安定します。

3) 速さの正体:レイヤーとキャッシュを味方にする

Docker のイメージは、1 枚の巨大ファイルではなく、複数のレイヤーでできています。Dockerfile の各ステップ(例:RUN、COPY)がレイヤーを作り、同じ手順ならキャッシュが効きます。

  • 依存インストール(変化が少ない)を上に置く
  • アプリのソース(変化が多い)を下に置く

という順序を守るだけでも、ビルド時間は体感で変わります。入門の時点でも「なぜ Dockerfile の書き方で速度が変わるのか」を知っておくと、後で詰まりにくいです。

4) どこでも同じものを動かす:Registryという“イメージ置き場”

イメージはローカルだけでなく、registry(例:Docker Hub、ECR、GCR、GHCR)に置けます。これにより

  • CI でビルド → registry に push
  • サーバで pull → run

という配布パターンが成立します。配布単位が「ソースコード」ではなく「動作保証済みのイメージ」になるのが、Docker を導入する大きな意味です。

5) “つながる”の基本:ポート公開と名前解決の考え方

Docker には複数のネットワークモードがありますが、入門で押さえるべき感覚はシンプルです。

  • コンテナは基本的に“隔離された世界”で動く
  • 外部(PC)からアクセスさせたいときは ポート公開(-p) が必要
  • コンテナ同士は 同じネットワークにいると名前解決で通信できる(Compose だと特に楽)

そして「localhost の罠」。コンテナ内の localhost はそのコンテナ自身です。ローカルで動いている API(例:Go のローカル API)にコンテナから繋ぐときは、そのまま localhost を叩いても届きません(ハンズオンで扱います)。

6) 消えて困るものは外へ:ボリュームでデータを永続化する

DB のデータやアップロードファイルなど、消えると困るものはコンテナの中に置かず、**ボリューム(volume)**として外に出します。

  • コンテナは削除してよい
  • データはボリュームに残る
  • 再起動・再作成が容易になる

この分離ができると、運用が“壊れにくい”方向に寄ります。

7) ログの王道:標準出力に出して集約しやすくする

Docker の世界では、アプリのログは原則 stdout/stderr に出すのが王道です。コンテナ内部のファイルにログを溜めると、取り回しが難しくなります。まずは標準出力に出して、必要に応じてログドライバやログ基盤へつなぐ方がスムーズです。

ハンズオン

ここでは「コンテナを動かす」「イメージを作る」「データを残す」「ネットワークの感覚を掴む」の 4 本立てで進めます。Mac/Windows/Linux いずれも Docker Desktop もしくは Docker Engine が入っている前提です。

0) 準備:Docker が使えるか確認

docker version
docker info
  • docker version がクライアント/サーバ両方表示されればOK
  • Cannot connect to the Docker daemon が出たら、Docker Desktop 起動や service 起動が必要です

1) まずは「動かす」:Hello コンテナ

docker run --rm hello-world
  • run は「イメージを取得して(無ければ pull)、コンテナを起動する」
  • --rm は「停止したらコンテナを自動削除」
  • ここで “動かせた” ことがまず大事です

次に、実際に Web サーバを起動してみます。

docker run --rm -p 8080:80 nginx:alpine
  • -p 8080:80 は「ホストの 8080 → コンテナの 80」に転送
  • ブラウザで http://localhost:8080 にアクセスして Nginx の画面が出れば成功
  • 停止は Ctrl + C

2) 観察:コンテナとイメージの状態を把握する

別ターミナルで、起動中の状態を見ます。

docker ps
docker images
  • ps は稼働中のコンテナ
  • images はローカルにあるイメージ

次に、コンテナの中を少し覗きます。

docker ps
docker exec -it <container_id> sh

コンテナ内で:

uname -a
ls -la /
exit

3) 自作イメージ:最小の Web を Dockerfile で作る

ディレクトリ構成:

docker-intro/
  Dockerfile
  index.html

index.html

<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title>Docker Intro</title>
  </head>
  <body>
    <h1>Docker 入門ハンズオン</h1>
    <p>自作イメージで配布できる状態になりました。</p>
  </body>
</html>

Dockerfile

FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html

ビルドして起動:

docker build -t my-nginx:1.0 .
docker run --rm -p 8080:80 my-nginx:1.0

4) ボリューム:コンテナを消してもデータを残す

docker volume create demo-data
docker run --rm -it -v demo-data:/data alpine sh

コンテナ内:
echo "hello volume" > /data/hello.txt
cat /data/hello.txt
exit

再起動して残っているか確認:
docker run --rm -it -v demo-data:/data alpine sh
cat /data/hello.txt
exit

5) ネットワークの罠:コンテナからローカルの Go API を叩く

  • コンテナ内の localhost は“コンテナ自身”
  • PC 上で動く Go API(例:localhost:9000)は、コンテナから見ると別世界

Mac/Windows(Docker Desktop)

ホストへは host.docker.internal が使えることが多いです。

docker run --rm alpine sh -c "apk add --no-cache curl && curl -sS http://host.docker.internal:9000/health"

Linux(一般的な選択肢)

環境によって host.docker.internal が無い場合があります。その場合は

  • --network host(Linux で有効なことが多い)
  • ホストの IP を指定
  • Go API もコンテナ化して同一ネットワークで繋ぐ(再現性が高い)

のいずれかが現実解です。

まとめ

Docker 入門で一番大事なのは、便利なコマンドを暗記することよりも、設計の前提を身体に入れることです。

  • イメージは実行環境を固めたもの、コンテナはその実体
  • コンテナは基本 使い捨て。変更は Dockerfile に戻す
  • データはボリュームに逃がし、コンテナと分離する
  • 外部公開は ポート公開(-p) が必要
  • コンテナからホストの localhost は見えない(ネットワークの罠)
  • ログはまず 標準出力に出すのが基本


投稿日

カテゴリー:

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です