Tuesday, October 21, 2025

Dockerで築く、不変でポータブルな開発基盤

「私のローカル環境では問題なく動いたのに…」—この言葉は、多くの開発者が一度は口にしたことがある、あるいは耳にしたことがあるであろう悲痛な叫びです。開発環境と本番環境の微妙な差異、依存ライブラリのバージョンの不一致、あるいはオペレーティングシステム固有の設定の違いが、予期せぬバグや動作不良の温床となってきました。この根深い問題を解決し、アプリケーション開発のあり方を根底から変革した技術、それがDockerです。

Dockerは、アプリケーションとその依存関係を「コンテナ」と呼ばれる軽量で独立した環境にパッケージングするプラットフォームです。これにより、開発者は自身のPCからステージング環境、そして本番サーバーに至るまで、どこでも全く同じように動作するアプリケーションを構築し、配布することが可能になります。本稿では、Dockerがなぜ現代のソフトウェア開発において不可欠なツールとなったのか、その根幹をなす概念から、実際にDockerfileを作成して独自のアプリケーションイメージを構築する具体的なプロセスまでを、深く掘り下げて解説します。

第1章: なぜ私たちはDockerを必要とするのか?

Dockerの真価を理解するためには、まずそれが解決しようとしている課題、すなわち従来の開発プロセスが抱えていた困難を理解する必要があります。

1.1 環境差異という名の悪夢

ソフトウェア開発は、多くの場合、複数の環境をまたいで行われます。開発者のローカルマシン(macOS, Windows, Linux)、共有のテスト環境、ステージング環境、そして最終的な本番環境。これらの環境は、OSのバージョン、インストールされているライブラリ、ネットワーク設定、環境変数など、無数の要素において微妙に、あるいは大きく異なる可能性があります。

  • 依存関係の地獄(Dependency Hell): プロジェクトAはライブラリXのバージョン1.0を要求し、プロジェクトBは同じライブラリXのバージョン2.0を要求する。一台のマシンにこれらを共存させることは、しばしば困難を極めます。
  • OSの差異: ファイルパスの区切り文字(/ vs \)、特定のシステムコールの有無、ライブラリのコンパイル方法など、OSの違いがアプリケーションの挙動に影響を与えることがあります。
  • 暗黙の依存: 開発者のマシンには「たまたま」インストールされていたツールやライブラリに、アプリケーションが気づかぬうちに依存してしまうケース。これが他の環境で動作しない原因となります。

これらの問題は、開発サイクルの遅延、デバッグの複雑化、そして最終的にはサービスの信頼性低下に直結します。

1.2 仮想マシン(VM)による解決策とその限界

この環境差異の問題に対する一つの古典的な解決策が、仮想マシン(VM)の利用でした。VMwareやVirtualBoxといったハイパーバイザー型の仮想化技術は、物理的なハードウェアの上に完全なゲストOSをエミュレートします。これにより、アプリケーションごとに独立したOS環境を丸ごと提供できるため、環境の分離と再現性は劇的に向上しました。

しかし、このアプローチにはいくつかの重大な欠点が存在します。

  • 重量級であること: 各VMは完全なOS(カーネル、システムライブラリ、ドライバなど)を内包するため、数ギガバイトから数十ギガバイトのディスク容量を消費します。メモリも同様に、ゲストOSを起動するだけで数百メガバイトから数ギガバイトを必要とします。
  • 起動が遅い: VMの起動は、物理的なコンピュータを起動するのと同様に、OSのブートプロセス全体を経るため、数分かかることも珍しくありません。
  • リソース効率の悪さ: 複数のVMを同一のホストマシンで実行する場合、それぞれのVMが独立してOSを稼働させるため、リソースの重複が大きく、ホストマシンの性能を最大限に引き出すことが困難です。

上の図が示すように、仮想マシンはハードウェアレベルでの仮想化であり、各々が独立したゲストOSを持つ構造です。これに対し、コンテナはOSレベルの仮想化であり、ホストOSのカーネルを共有します。このアーキテクチャの違いが、Dockerの持つ軽快さと効率性の源泉となっています。

1.3 コンテナ技術の登場:軽量、高速、ポータブル

Dockerは、Linuxカーネルの持つ機能(特にNamespacesとControl Groups (cgroups))を利用して、プロセスレベルでの分離を実現します。これが「コンテナ」です。

  • Namespaces(名前空間): プロセスが見えるリソース(プロセスID、ネットワーク、マウントポイント、ホスト名など)を分離します。コンテナ内のプロセスは、まるで自分だけの独立したOS上で動いているかのように振る舞いますが、実際にはホストOS上の他のプロセスと並行して動作しています。
  • Control Groups (cgroups): プロセスグループが使用できるリソース(CPU、メモリ、ディスクI/Oなど)を制限・管理します。これにより、あるコンテナがホストマシンのリソースを使い果たしてしまうのを防ぎます。

この仕組みにより、コンテナはVMと比較して以下のような圧倒的な利点を持ちます。

  • 軽量性: コンテナはOSを内包せず、アプリケーションとそれに必要なライブラリやバイナリのみをパッケージングします。そのため、イメージサイズは数メガバイトから数百メガバイト程度に収まることが多く、ディスク容量を大幅に節約できます。
  • 高速な起動: OSのブートプロセスが不要なため、コンテナは通常、数秒、場合によってはミリ秒単位で起動します。これにより、迅速な開発・テストサイクルや、スケーリングの高速化が実現します。
  • 高い集積度: ホストOSのカーネルを共有するため、リソースのオーバーヘッドが非常に小さいです。結果として、一台のホストマシン上で、VMよりもはるかに多くのコンテナを同時に稼働させることが可能です。

Dockerは、この強力なコンテナ技術を、開発者が容易に利用できるツール群(コマンドラインインターフェース、デーモン、イメージフォーマットなど)として提供することで、コンテナの利用を大衆化し、DevOps文化の浸透を加速させる原動力となったのです。

第2章: Dockerの生態系を理解する:イメージ、コンテナ、レジストリ

Dockerを効果的に利用するためには、その中心的な構成要素である「イメージ(Image)」、「コンテナ(Container)」、そして「レジストリ(Registry)」の関係性を正確に理解することが不可欠です。これらの概念は、しばしばオブジェクト指向プログラミングにおけるクラスとインスタンスの関係に喩えられます。

2.1 Dockerイメージ:不変の設計図

Dockerイメージは、コンテナを作成するための設計図、あるいはテンプレートです。アプリケーションを実行するために必要なものすべて(コード、ランタイム、ライブラリ、環境変数、設定ファイルなど)を含む、読み取り専用のファイルシステムです。

イメージの最も重要な特徴の一つは、その階層構造(Layered Filesystem)です。イメージは、複数の読み取り専用レイヤーが積み重なって構成されています。例えば、Ubuntuのベースイメージの上に、Pythonのランタイムをインストールするレイヤー、次にアプリケーションの依存ライブラリをインストールするレイヤー、そして最後にアプリケーションのコードを追加するレイヤー、というように構築されます。

この階層構造は、いくつかの大きな利点をもたらします。

  • 効率性: 複数のイメージが共通のベースレイヤー(例: Ubuntu OS)を共有している場合、そのレイヤーはホストマシン上に一度だけ保存されます。これにより、ディスク容量を大幅に節約できます。イメージのダウンロードや転送も、既に存在するレイヤーはスキップされるため高速です。
  • 再利用性: 共通の基盤となるレイヤーを持つカスタムベースイメージを作成し、チーム内で共有することで、開発環境の標準化を促進できます。
  • バージョニング: アプリケーションのコードを更新した場合、変更されたコードのレイヤーだけが新しく作成されます。これにより、イメージのバージョン管理が容易になり、変更履歴の追跡も可能です。

もう一つの重要な特性は不変性(Immutability)です。一度ビルドされたイメージの内容は変更できません。イメージに変更を加えたい場合は、新しいレイヤーを追加して新しいイメージを作成する必要があります。この不変性が、開発から本番まで一貫した環境を保証する鍵となります。「一度ビルドすれば、どこでも動く(Build once, run anywhere)」というDockerの思想は、このイメージの不変性によって支えられています。

2.2 Dockerコンテナ:実行可能なインスタンス

Dockerコンテナは、Dockerイメージから作成された、実行中のインスタンスです。オブジェクト指向の比喩で言えば、イメージが「クラス」であれば、コンテナは「オブジェクト(インスタンス)」に相当します。一つのイメージから、いくつでも独立したコンテナを起動することができます。

コンテナが起動されるとき、Dockerは指定されたイメージの読み取り専用レイヤーの上に、新しく書き込み可能なレイヤー(コンテナレイヤー)を追加します。コンテナ内で実行されるアプリケーションがファイルを作成、変更、削除する際には、この最上位のコンテナレイヤーに対して書き込みが行われます。元のイメージレイヤーは一切変更されません。

この仕組みにより、以下の特性が生まれます。

  • 分離(Isolation): 各コンテナは自身のファイルシステム、ネットワーク、プロセス空間を持っています。あるコンテナで行われた変更が、他のコンテナやホストシステムに影響を与えることはありません(明示的に設定しない限り)。
  • 揮発性(Ephemeral): コンテナを削除すると、そのコンテナの書き込み可能レイヤーも一緒に破棄されます。つまり、コンテナ内で行われた変更は、コンテナの寿命とともに消えてしまいます。データを永続化したい場合は、後述するボリューム(Volume)などの仕組みを利用する必要があります。この揮発性は、ステートレスなアプリケーションの設計を促進し、クリーンな状態からの再起動を容易にします。

コンテナは、アプリケーションが実行されるための、隔離された軽量なランタイム環境そのものなのです。

2.3 Dockerレジストリ:イメージの保管庫

作成したDockerイメージを保存し、他者と共有するための場所がDockerレジストリです。これは、ソースコードを管理するGitリポジトリ(GitHubやGitLabなど)のDockerイメージ版と考えることができます。

最も有名で広く使われている公開レジストリがDocker Hubです。Docker Hubには、UbuntuやAlpine Linuxのような公式OSイメージ、PythonやNode.jsといった公式プログラミング言語イメージ、MySQLやRedisのようなデータベースやミドルウェアのイメージなど、膨大な数の公式・非公式イメージがホストされています。開発者はこれらの公開イメージをベースとして、自身のアプリケーションイメージを効率的に構築できます。

もちろん、企業内での利用や機密情報を含むイメージのために、プライベートなレジストリを構築することも可能です。Docker Hubにもプライベートリポジトリ機能がありますし、Amazon ECR (Elastic Container Registry), Google GCR (Google Container Registry), Azure ACR (Azure Container Registry) といったクラウドプロバイダーのサービスや、Harborのようなオンプレミスで構築できるオープンソースのレジストリも存在します。

開発ワークフローは通常、以下のようになります。

  1. Dockerfileを元にローカルでイメージをビルドする (docker build)。
  2. ビルドしたイメージをレジストリにプッシュする (docker push)。
  3. 本番サーバーや他の開発者が、レジストリからイメージをプルする (docker pull)。
  4. プルしたイメージからコンテナを起動する (docker run)。

この「ビルド → プッシュ → プル → 実行」というサイクルが、Dockerを中心としたCI/CD(継続的インテグレーション/継続的デリバリー)パイプラインの基本となります。

第3章: Dockerfile詳解:イメージ設計図をマスターする

Dockerイメージを自動的に構築するための手順を記述したテキストファイル、それがDockerfileです。Dockerfileは、イメージの再現性とバージョン管理を可能にする、Dockerの中核的な機能です。この章では、Dockerfileで頻繁に使用される主要な命令について、その役割とベストプラクティスを詳細に解説します。

Dockerfileは通常、以下のような構造を持っています。


# コメント
命令 引数
命令 引数
...

3.1 `FROM`: すべての始まりとなるベースイメージ

FROM命令は、Dockerfileの最初の命令でなければなりません(`ARG`を除く)。これは、これから作成するイメージの土台となる「ベースイメージ」を指定します。


FROM ubuntu:22.04

上記の例では、Docker Hubにある公式のUbuntu 22.04イメージをベースとしています。タグ(:22.04)を省略すると、デフォルトで:latestタグが使用されますが、これは予期せぬバージョンの変更を引き起こす可能性があるため、常に特定のバージョンタグを指定することが強く推奨されます。

ベースイメージの選択は、最終的なイメージのサイズ、セキュリティ、含まれるツールセットに大きな影響を与えます。

  • `ubuntu`, `debian`, `centos`: フル機能のOSイメージで、デバッグ用のツールなどが豊富に含まれていますが、サイズは大きめです。
  • `alpine`: 超軽量なLinuxディストリビューションで、セキュリティを重視した設計になっています。イメージサイズを最小限に抑えたい場合に最適ですが、標準Cライブラリとしてmusl libcを使用しているため、glibcに依存する一部のソフトウェアとの互換性問題が発生することがあります。
  • `slim`: Debianベースのイメージで、不要なパッケージを削ぎ落としたものです。`alpine`ほどの軽量さはありませんが、互換性を保ちつつサイズを削減したい場合に良い選択肢となります。
  • `scratch`: 空のイメージです。Go言語などで静的コンパイルされた単一のバイナリを配置するような、究極にミニマルなイメージを作成する際に使用されます。

3.2 `RUN`: コマンドの実行とレイヤーの生成

RUN命令は、イメージのビルドプロセス中にシェルコマンドを実行します。主に、パッケージのインストール、ディレクトリの作成、スクリプトの実行などに使用されます。


RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*

ここで重要なのは、Dockerfile内の各命令(特に`RUN`, `COPY`, `ADD`)が、新しいイメージレイヤーを生成するという点です。レイヤー数を無駄に増やすと、ビルド時間やイメージサイズが増加する原因となります。

ベストプラクティス:

  • 関連するコマンドは&&を使って一つの`RUN`命令にまとめ、レイヤー数を削減します。
  • パッケージをインストールした後は、apt-get cleanrm -rf /var/lib/apt/lists/*(Debian/Ubuntu系の場合)を実行して、キャッシュファイルを削除し、レイヤーサイズを小さく保ちます。

3.3 `COPY`と`ADD`: ホストからファイルを追加する

COPY`命令は、ホストマシン(ビルドコンテキスト)からイメージ内のファイルシステムにファイルやディレクトリをコピーします。


# 'app'ディレクトリをコンテナ内の'/app'にコピー
COPY app/ /app/

ADD命令も同様の機能を持ちますが、加えて2つの機能があります。

  1. URLをソースとして指定すると、ファイルをダウンロードしてコピーします。
  2. 圧縮ファイル(tar, gzip, bzip2など)をソースとして指定すると、自動的に展開してコピーします。

これらの追加機能は便利に見えますが、挙動が不透明になることがあります(例えば、意図せず展開されてしまうなど)。そのため、Dockerの公式ドキュメントでは、単純なファイルコピーには`ADD`よりも`COPY`の使用が推奨されています。URLからのダウンロードは`RUN wget`や`RUN curl`を、展開は`RUN tar`を使う方が、Dockerfileの意図が明確になります。

3.4 `WORKDIR`: 作業ディレクトリの指定

WORKDIR命令は、その後に続く`RUN`, `CMD`, `ENTRYPOINT`, `COPY`, `ADD`命令が実行される作業ディレクトリを指定します。毎回絶対パスを指定する手間を省き、Dockerfileを読みやすく、メンテナンスしやすくします。


WORKDIR /app

# これ以降の命令は/appディレクトリを基準に実行される
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

CMD ["python3", "main.py"]

もし指定したディレクトリが存在しない場合、`WORKDIR`は自動的にそのディレクトリを作成します。

3.5 `EXPOSE`: ポートの公開(ドキュメンテーション)

EXPOSE命令は、コンテナが実行時にリッスンするネットワークポートをDockerに通知します。これはあくまでドキュメンテーション(メタデータ)としての意味合いが強く、この命令だけでは実際にホストマシンからそのポートにアクセスできるようにはなりません。


# このコンテナはポート8000でサービスを提供することを意図している
EXPOSE 8000

実際にポートを公開するには、`docker run`コマンド実行時に`-p`または`-P`フラグを使用する必要があります。


# ホストのポート8080をコンテナのポート8000にマッピング
docker run -p 8080:8000 my-app-image

3.6 `CMD`と`ENTRYPOINT`: コンテナ起動時に実行されるコマンド

CMDと`ENTRYPOINT`は、コンテナが起動する際にデフォルトで実行されるコマンドを定義しますが、その挙動には重要な違いがあり、多くの初学者が混乱するポイントです。

`CMD`

CMDは、コンテナのデフォルトの実行コマンドを提供します。主な目的は、イメージを実行可能にするためのデフォルトのコマンドを設定することです。

CMD`には3つの形式がありますが、Exec形式が推奨されます。


# Exec形式 (推奨)
CMD ["executable","param1","param2"]

# Shell形式 (シェルを介して実行されるため、意図しない挙動の可能性)
CMD command param1 param2

CMDで指定されたコマンドは、`docker run`コマンドで引数を渡すことで簡単に上書きできます。


# Dockerfile: CMD ["python3", "app.py"]
# ↓
# `docker run my-image` で実行すると `python3 app.py` が実行される
# `docker run my-image ls -l` で実行すると `ls -l` が実行され、CMDは無視される

`ENTRYPOINT`

ENTRYPOINTは、コンテナを特定の実行ファイルのように振る舞わせるために使用されます。ENTRYPOINT`で指定されたコマンドは、`docker run`で渡された引数を自身の引数として受け取ります。


# Exec形式 (推奨)
ENTRYPOINT ["executable","param1"]

例を見てみましょう。


ENTRYPOINT ["echo", "Hello"]
CMD ["World"]

# `docker run my-image` -> "Hello World" を出力 (ENTRYPOINT + CMD)
# `docker run my-image Docker` -> "Hello Docker" を出力 (CMDが上書きされ、ENTRYPOINTの引数になる)

ENTRYPOINT`自体を上書きすることも可能ですが、`--entrypoint`フラグが必要です。

使い分けのベストプラクティス

  • `CMD`を使う場合: イメージの主な目的が単一のコマンドを実行することであり、そのコマンドを`docker run`で簡単に変更できるようにしたい場合。(例: `CMD ["rails", "server"]`)
  • `ENTRYPOINT`を使う場合: イメージを特定のコマンドのラッパーとして機能させたい場合。コンテナが常に同じ実行可能ファイルで起動し、`docker run`の引数はその実行可能ファイルへの引数として扱われるようにしたい場合。(例: `ENTRYPOINT ["/usr/bin/my-cli"]`)
  • 両方を組み合わせる場合: `ENTRYPOINT`で実行ファイルを固定し、`CMD`でそのデフォルトの引数を指定する。これが最も柔軟で強力なパターンです。

第4章: 実践 - Python Webアプリケーションのコンテナ化

理論を学んだところで、実際に簡単なPython Flask Webアプリケーションをコンテナ化するプロセスを通して、これまでの知識を統合してみましょう。

4.1 アプリケーションの準備

まず、以下のような構成のシンプルなプロジェクトを準備します。


my-flask-app/
├── app.py
├── requirements.txt
└── Dockerfile

`app.py`: "Hello, Docker!" と表示するだけのWebサーバーです。


from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello, Docker!\n"

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

注意:host='0.0.0.0'と指定することが重要です。これにより、コンテナの外部(Dockerネットワーク)からのアクセスを受け付けるようになります。デフォルトの127.0.0.1では、コンテナ内部からしかアクセスできません。

`requirements.txt`: プロジェクトの依存ライブラリを記述します。


Flask==2.2.2

4.2 Dockerfileの作成

次に、このアプリケーションをコンテナ化するための`Dockerfile`を作成します。


# 1. ベースイメージの選択
# Python 3.10 のスリムバージョンをベースにする
FROM python:3.10-slim

# 2. 作業ディレクトリの設定
WORKDIR /app

# 3. 依存関係のインストール (ソースコードのコピーより先に)
# requirements.txt を先にコピーしてインストールすることで、
# アプリケーションコードが変更されても、依存関係が変わらなければ
# このレイヤーはキャッシュが利用され、ビルドが高速になる
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 4. ソースコードのコピー
COPY . .

# 5. ポートのドキュメンテーション
EXPOSE 5000

# 6. コンテナ起動時のコマンド
CMD ["python", "app.py"]

このDockerfileには、ビルドを効率化するための重要なテクニックが含まれています。依存関係のインストール(`pip install`)を、アプリケーションコードのコピー(`COPY . .`)より先に行っている点です。Dockerはビルド時にレイヤーキャッシュを利用します。もしアプリケーションコード(`app.py`)だけを変更した場合、`requirements.txt`は変更されていないため、`COPY requirements.txt .`と`RUN pip install ...`のレイヤーはキャッシュが再利用され、ビルド時間が大幅に短縮されます。

4.3 イメージのビルド

Dockerfileの準備ができたら、`docker build`コマンドを使ってイメージをビルドします。プロジェクトのルートディレクトリ(`my-flask-app/`)で以下のコマンドを実行します。


docker build -t my-flask-app:1.0 .
  • -t my-flask-app:1.0: 作成するイメージに名前(my-flask-app)とタグ(1.0)を付けます。<repository>:<tag>という形式です。タグはバージョニングに非常に重要です。
  • .: ビルドコンテキストのパスを指定します。ここではカレントディレクトリを指し、Dockerfileやコピー対象のファイル(`app.py`など)がこのディレクトリから検索されます。

ビルドが成功すると、Dockerは各ステップに対応するレイヤーを作成し、最終的に`my-flask-app:1.0`という名前のイメージがローカルに保存されます。docker imagesコマンドで確認できます。


$ docker images
REPOSITORY       TAG     IMAGE ID       CREATED         SIZE
my-flask-app     1.0     a1b2c3d4e5f6   5 seconds ago   120MB

第5章: コンテナのライフサイクル管理

イメージをビルドしたら、次はそのイメージからコンテナを起動し、管理する方法を学びます。ここでは、日常的に使用する基本的なDockerコマンドを紹介します。

5.1 コンテナの起動: `docker run`

docker run`は、イメージから新しいコンテナを作成して起動する、最も基本的なコマンドです。非常に多くのオプションがありますが、ここでは必須のものを中心に解説します。


docker run -d -p 8080:5000 --name web-server my-flask-app:1.0

このコマンドを分解してみましょう。

  • `-d` (`--detach`): コンテナをバックグラウンドで実行します(デタッチモード)。これを付けないと、コンテナのログがフォアグラウンドで表示され続け、ターミナルを占有します。
  • `-p 8080:5000` (`--publish`): ポートのマッピングを行います。<host-port>:<container-port>の形式で、この例ではホストマシンのポート8080へのアクセスを、コンテナ内のポート5000に転送します。これにより、ブラウザでhttp://localhost:8080にアクセスすると、コンテナ内のFlaskアプリケーションに応答が届きます。
  • `--name web-server`: コンテナに人間が識別しやすい名前を付けます。名前を付けないと、Dockerがランダムな名前(例: `quirky_einstein`)を自動的に割り当てます。
  • `my-flask-app:1.0`: 起動するコンテナの基となるイメージを指定します。

コマンド実行後、コンテナIDが出力され、コンテナはバックグラウンドで稼働を開始します。

5.2 実行中のコンテナの確認: `docker ps`

現在実行中のコンテナのリストを表示するには、`docker ps`(または`docker container ls`)コマンドを使用します。


$ docker ps
CONTAINER ID   IMAGE                COMMAND             CREATED          STATUS          PORTS                    NAMES
a9b8c7d6e5f4   my-flask-app:1.0     "python app.py"     2 minutes ago    Up 2 minutes    0.0.0.0:8080->5000/tcp   web-server

停止しているコンテナも含めてすべてのコンテナを表示したい場合は、`-a`(`--all`)オプションを追加します。


docker ps -a

5.3 コンテナのログ確認: `docker logs`

バックグラウンドで実行中のコンテナの標準出力を確認するには、`docker logs`コマンドを使用します。


docker logs web-server

-f`(`--follow`)オプションを付けると、`tail -f`のようにログをリアルタイムで追跡できます。


docker logs -f web-server

5.4 コンテナの停止と再開

実行中のコンテナを停止するには`docker stop`を、停止したコンテナを再開するには`docker start`を使用します。


# コンテナを停止 (猶予期間を与えて正常終了を試みる)
docker stop web-server

# コンテナを再開
docker start web-server

5.5 コンテナの削除: `docker rm`

不要になったコンテナを削除するには`docker rm`を使用します。コンテナは停止している状態でなければ削除できません。実行中のコンテナを強制的に削除したい場合は、`docker stop`と`docker rm`を組み合わせるか、`docker rm -f`を使用します。


# 停止しているコンテナを削除
docker rm web-server

# 実行中のコンテナを強制的に削除
docker rm -f web-server

停止しているすべてのコンテナを一括で削除する便利なコマンドもあります。


docker container prune

5.6 実行中のコンテナ内でのコマンド実行: `docker exec`

デバッグなどの目的で、実行中のコンテナの中に入ってシェルを操作したい場合があります。その際に使用するのが`docker exec`です。


docker exec -it web-server /bin/bash
  • `-i` (`--interactive`): 標準入力を開いたままにします。
  • `-t` (`--tty`): 疑似ターミナルを割り当てます。

この-itオプションの組み合わせにより、対話的なシェルセッションが可能になります。コマンドを実行すると、コンテナ内のbashプロンプトが表示され、コンテナのファイルシステムを自由に探索したり、コマンドを実行したりできます。セッションを終了するには`exit`と入力します。

第6章: 次のステップへ - Dockerエコシステムの展望

ここまでで、Dockerの基本的な概念からイメージの作成、コンテナの管理までの一連の流れを学びました。これはDockerの世界への第一歩に過ぎません。実際のアプリケーション開発では、複数のコンテナが連携して動作する、より複雑なシステムを構築する必要があります。

Docker Compose: 複数のコンテナの協調

Webアプリケーションは通常、Webサーバー、データベース、キャッシュサーバーなど、複数のサービスで構成されます。これらのサービスを個別のコンテナとして定義し、それらの連携(ネットワーク設定、依存関係など)を一つのYAMLファイル(`docker-compose.yml`)で宣言的に管理できるツールがDocker Composeです。

Docker Composeを使えば、`docker-compose up`という単一のコマンドで、アプリケーション全体を構成するすべてのコンテナを起動、連携させることができます。これにより、開発環境の構築が劇的に簡素化されます。

Kubernetes: 本番環境でのコンテナオーケストレーション

本番環境で多数のコンテナを運用する場合、手動での管理は現実的ではありません。コンテナのデプロイ、スケーリング、自己修復、ネットワーク管理などを自動化するためのプラットフォームがコンテナオーケストレーションツールであり、その事実上の標準となっているのがKubernetes (K8s) です。

Kubernetesは、複数のサーバー(ノード)をクラスターとして束ね、その上にコンテナを効率的に配置・管理します。サービスに障害が発生した場合の自動的な再起動や、トラフィックの増減に応じたコンテナ数の自動調整(オートスケーリング)など、大規模で可用性の高いシステムを運用するための高度な機能を提供します。Dockerの知識は、Kubernetesを学ぶ上での必須の基礎となります。

結論: 開発の未来を形作るコンテナ技術

Dockerは、単なる仮想化技術の一つではありません。それは、アプリケーションのパッケージング、配布、実行の方法を標準化し、開発者と運用者の間の壁を取り払う、DevOps文化を推進するための強力な触媒です。「ビルドすれば、どこでも動く」というコンテナのポータビリティは、開発サイクルの高速化、インフラのコード化(Infrastructure as Code)、そしてマイクロサービスアーキテクチャの実現を可能にしました。

本稿で解説したDockerの基本概念、Dockerfileの記述方法、そしてコンテナの管理手法は、現代のソフトウェアエンジニアにとって必須のスキルセットです。この知識を基盤として、ぜひ自身のプロジェクトにDockerを導入し、その計り知れない恩恵を体験してください。コンテナの世界は奥深く、Docker ComposeやKubernetesといった、さらに広大なエコシステムがあなたを待っています。


0 개의 댓글:

Post a Comment