Docker 入門

Docker run コマンド

1. docker run コマンドの徹底解剖

docker run コマンドは、非常に直感的な基本構文(Syntax)構造に従っています:

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

このコマンドを分解し、各コンポーネントを一つずつ紐解いていきましょう:

  • docker run: これはコンテナの作成と実行プロセスを起動するための基本コマンドです。
  • [OPTIONS] (オプション/パラメータ): これらのフラグは docker run コマンドの振る舞い(Behavior)を変更するために使用されます。Dockerは非常に豊富なオプションを提供しており、コンテナの設定をきめ細かく制御 (Control) できます。後ほど、最も頻繁に使用されるコアなオプションについて詳しく探求します。
  • IMAGE (イメージ): コンテナを作成する際のベースとなるイメージを指定します。「名前+タグ (Tag)」の形式(例:ubuntu:latestmy-app:1.0)で指定することも、イメージIDを直接使用することもできます。ローカルにそのイメージが存在しない場合、Dockerはデフォルトで設定されたイメージレジストリ(Registry、通常はDocker Hub)からプル (Pull) しようと試みます。タグを指定しない場合、Dockerはデフォルトで latest(最新版)タグを使用します。
  • [COMMAND] (コマンド): これはコンテナ起動後にコンテナ内部で実行されるコマンドです。ここで具体的なコマンドを指定しない場合、Dockerはイメージの Dockerfile で定義されたデフォルトコマンド(つまり CMD インストラクションで指定されたコマンド)を使用します。
  • [ARG...] (引数/パラメータ): これらは前の [COMMAND] に渡される追加のパラメータ (Parameter) です。

2. 必須の docker run パラメータオプション

docker run の強みは、その豊富なオプションにあります。以下では、最も重要なパラメータを深く掘り下げ、その使い方を完全にマスターできるように解説します:

2.1 -d または --detach (バックグラウンド実行)

このオプションは、コンテナをデタッチモード (Detached mode) で実行します。簡単に言えば、バックグラウンド (Background) での実行です。これは、Webサーバーやデータベース (Database) など、長時間の実行を必要とするアプリケーションにとって極めて重要です。

例:

docker run -d nginx:latest

このコマンドを実行すると、バックグラウンドで Nginx Webサーバーのコンテナが起動します。現在のターミナル (Terminal) にNginxの実行ログ (Log) が直接表示されることはありません。代わりに、Dockerは非常に長い一意のコンテナIDを返し、後続のコンテナ管理 (Management) にこのIDを使用できます。ログを確認したい場合は、docker logs <コンテナID> コマンドを使用します。

なぜ使用するのか?
デタッチモードを使用すると、コンテナが継続して実行されている間も、現在のターミナルウィンドウで他のコマンドを入力し続けることができます。大多数のサーバーサイド (Server-side) アプリケーションにおいて、これは必須の操作です。

2.2 -p または --publish (ポートマッピング)

このオプションは、ホストマシン (Host machine、あなたのPCやサーバー) とコンテナ間のポート (Port) をマッピング (Mapping) するために使用されます。コンテナ内部で実行されているサービスに外部の世界からアクセス (Access) させたい場合、このパラメータは不可欠です。

構文: -p ホストマシンのポート:コンテナ内のポート

例:

docker run -d -p 8080:80 nginx:latest

このコマンドは、ホストマシンの 8080 番ポートを、コンテナ内部の 80 番ポートにマッピングします。ホストマシンの 8080 番ポートに送信されたすべてのネットワークトラフィック (Network traffic) は、コンテナ内の 80 番ポートで実行されているNginxサーバーに自動的にフォワード (Forward) されます。起動後、ブラウザを開いて http://localhost:8080 にアクセスすると、Nginxのウェルカムページが表示されます。

高度な使い方: バインド (Bind) するホストマシン上の特定のIPアドレスを指定することもできます。例:-p 127.0.0.1:8080:80。このように設定すると、ホストマシン自身のみがそのコンテナにアクセスでき、外部ネットワークからはアクセスできなくなるため、セキュリティ (Security) が向上します。また、大文字の -P パラメータを使用すると、Dockerがコンテナ内の公開されているすべてのポートをランダムにマッピングします。

なぜ使用するのか?
コンテナはデフォルトで完全に分離されたネットワーク環境です。ポートマッピングは、コンテナに特定の窓を開け、外部からのリクエスト (Request) が内部のサービスを正確に見つけられるようにするようなものです。

2.3 -v または --volume (ボリュームマウント)

このオプションは、データボリューム (Data Volume) のマウント (Mount) を作成し、ホストマシンとコンテナ間でファイルやディレクトリを共有 (Share) できるようにするために使用されます。これは、データの永続化ストレージ (コンテナ削除時のデータ消失防止) や設定ファイルの共有において非常に重要です。

構文: -v ホストマシンのパス:コンテナ内のパス

例:

docker run -d -v /path/on/host:/path/in/container nginx:latest

このコマンドは、ホストマシン上の /path/on/host ディレクトリを、コンテナ内部の /path/in/container ディレクトリにマウントします。これら2つのディレクトリのいずれかでファイルに加えられた変更は、もう一方に即座にリアルタイムで同期 (Sync) されます。

名前付きボリューム (Named Volumes): Dockerによって一元管理される「名前付きボリューム」を使用することもでき、これが公式に推奨されるデータの永続化方法です。まず、ボリュームを作成します:

docker volume create my-nginx-data

次に、このボリュームをマウントします:

docker run -d -v my-nginx-data:/usr/share/nginx/html nginx:latest

ここでは、名前付きボリューム my-nginx-data をコンテナ内の /usr/share/nginx/html にマウントしています。このコンテナが停止または削除されたとしても、このボリュームに保存されたデータは無傷のまま残ります。

読み取り専用マウント (Read-only Mount): コンテナにデータの読み取りのみを許可し、変更を禁止したい場合は、:ro (read-only) フラグを追加できます:-v /path/on/host:/path/in/container:ro

なぜ使用するのか?
コンテナ自体は「読んだら燃やす (使い捨て)」性質があり、コンテナを削除するとデータも消えてしまいます。ボリューム (Volumes) はデータを永続的に保存するメカニズム (Mechanism) を提供し、データベースの実行、設定ファイルの保存、またはデータを恒久的に保存する必要があるあらゆるアプリケーションにとって必須のスキルです。

2.4 -e または --env (環境変数)

このオプションは、コンテナ内部に環境変数 (Environment Variables) を設定するために使用されます。環境変数を介してアプリケーションを動的に設定することは、クラウドネイティブ (Cloud Native) 時代において最も標準的なアプローチです。

構文: -e 変数名=変数値

例:

docker run -d -e MYSQL_ROOT_PASSWORD=mysecretpassword mysql:latest

このコマンドは、MySQLデータベースコンテナを起動し、MYSQL_ROOT_PASSWORD という名前の環境変数を mysecretpassword に設定します。MySQLコンテナは起動時にこの変数を読み取り、rootユーザーのパスワードを指定された値に設定します。

複数の変数の設定: -e オプションを複数回使用して、複数の環境変数を同時にインジェクト (Inject) することができます:

docker run -d -e MYSQL_ROOT_PASSWORD=mysecretpassword -e MYSQL_DATABASE=mydatabase mysql:latest

なぜ使用するのか?
環境変数を使用すると、イメージ内部のコードや設定ファイルを変更することなく、外部からプログラムの振る舞いを変更できます。これにより、同一のイメージを開発 (Dev)、テスト (Test)、本番 (Production) といった異なる環境へ柔軟にデプロイ (Deploy) することが容易になります。

2.5 --name (コンテナのネーミング)

コンテナに覚えやすい名前 (Name) を指定します。このパラメータを指定しない場合、Dockerは形容詞と科学者の名前を組み合わせた面白い名前をランダムに生成します。意味のある名前を指定することで、管理が格段に楽になります。

例:

docker run -d --name my-nginx-container nginx:latest

コンテナ起動後、その名前は my-nginx-container になります。以降は、長く覚えにくいIDの代わりに、この名前を直接使用してコンテナの停止 (Stop)、起動 (Start)、またはインスペクト (Inspect) を行うことができます。

なぜ使用するのか?
意味のない英数字の羅列であるIDよりも名前の方が100倍覚えやすく、日々の運用保守 (Operations) の効率を劇的に向上させます。

2.6 --rm (自動削除)

コンテナが実行を停止して終了 (Exit) した際に、自動的にそのコンテナを削除します。これは、使い終わったらすぐ破棄し、状態を保持する必要のない「使い捨て」の一時的なコンテナにとって非常に有用です。

例:

docker run --rm ubuntu:latest /bin/bash -c "echo 'Hello, world!' && sleep 5"

このコマンドは ubuntu:latest イメージをベースにコンテナを起動し、テキストを出力して5秒間スリープするスクリプト echo 'Hello, world!' && sleep 5 を実行します。5秒後にスクリプトの実行が完了するとコンテナは自動的に終了し、--rm パラメータによってDockerは直ちにそれを綺麗にクリーンアップ (Clean up) します。

なぜ使用するのか?--rm は、システムに大量の不要な廃止コンテナが蓄積されるのを効果的に防ぎ、システムをクリーンに保ちます。

2.7 -it または --interactive --tty (インタラクティブモード)

これら2つのパラメータは通常セットで使用され、コンテナ内部にインタラクティブなコマンドラインターミナル (Command-line Terminal) を開きます。これは、問題のデバッグ (Debug) や、コンテナ内の環境を探索 (Explore) する際の神ツールです。

例:

docker run -it ubuntu:latest /bin/bash

このコマンドはUbuntuコンテナを起動し、そのままコンテナ内部のBashターミナルへと誘導します。これで、リモートのLinuxサーバーにログイン (Login) したかのように、その中で自由にコマンドを実行できるようになります。

なぜ使用するのか?-it は、コンテナのファイルシステム (File System) や実行中のプロセス (Process) と直接やり取りするためのウィンドウを提供し、障害のトラブルシューティング (Troubleshooting) や環境のテストにおいて最も頻繁に使用される手段です。

2.8 --network (ネットワーク接続)

コンテナを特定のDockerネットワーク (Docker Network) に接続します。Dockerネットワークを使用すると、異なるコンテナ間で相互に通信 (Communicate) できるようになります。

例:

# まず、カスタムネットワークを作成する
docker network create my-network

# webコンテナを起動し、そのネットワークに参加させる
docker run -d --name web --network my-network nginx:latest

# dbコンテナを起動し、そのネットワークに参加させる
docker run -d --name db --network my-network mysql:latest

このコードは my-network という名前のネットワークを作成し、webdb の両方のコンテナをこのネットワーク内に配置します。驚くべきことに、これらは相手のコンテナ名をホスト名 (Hostname) として使用して通信できるようになります(例:web コンテナ内部のコードは、db という名前を直接使用してデータベースコンテナに接続できます)。

なぜ使用するのか?
Dockerネットワークは、異なるアプリケーションを分離 (Isolate) し、コンテナ間の相互アクセスを安全に管理するためのメカニズムを提供します。第4モジュールでDockerネットワークについてさらに深く解説します。

2.9 --restart (再起動ポリシー)

このオプションは、コンテナの再起動ポリシー (Restart Policy) を定義します。コンテナ内のプログラムが予期せずクラッシュ (Crash) したり終了したりした際に、Dockerがどのように振る舞うべきかを指示します。

よく使われるオプション値:

  • no: 何が起きても絶対に自動再起動しません(これがデフォルト値です)。
  • on-failure: コンテナがゼロ以外のステータスコード(異常なエラーを示す)で終了した場合にのみ再起動します。
  • always: コンテナが終了した理由(正常な終了を含む)に関わらず、常に無条件で再起動します。Dockerサービスの起動時にコンテナが停止していた場合も、自動的に立ち上げられます。
  • unless-stopped: コマンドによって手動で停止されない限り、終了するたびに再起動を試み続けます。

例:

docker run -d --restart always nginx:latest

このコマンドで起動したNginxコンテナは「不死身」になったようなものであり、どのような理由でダウンしても、Dockerは即座にそれを再起動します。

なぜ使用するのか?
再起動ポリシーは、オンラインアプリケーションの高可用性 (High Availability, HA) を保証するための重要な手段であり、プログラムがクラッシュしたりサーバーが再起動したりしても、サービスがオンラインであり続けることを確実にします。

3. 総合実践演習

さて、これまで学んださまざまなオプションを組み合わせて、実際のプロダクション (Production) シナリオで docker run がどのように威力を発揮するかを見てみましょう。

3.1 永続化とカスタム設定を備えた Redis コンテナの実行

docker volume create redis-data

docker run -d --name my-redis \
  -p 6379:6379 \
  -v redis-data:/data \
  -e REDIS_PASSWORD=mysecretpassword \
  --restart unless-stopped \
  redis:latest redis-server --requirepass mysecretpassword

解説:

  1. redis-data という名前の永続化データボリュームを作成しました。
  2. バックグラウンドモード (-d) で my-redis (--name) という名前のRedisコンテナを実行します。
  3. ホストマシンの 6379 番ポートをコンテナ内の 6379 番ポートにマッピングします (-p)。
  4. 作成したばかりのボリュームを、コンテナ内部のデータ専用保存ディレクトリである /data にマウントします (-v)。
  5. 万が一に備えて環境変数をインジェクトします (-e)。
  6. 手動で停止されない限り自動的に再起動するよう設定しました (--restart unless-stopped)。
  7. 最後に、コンテナ内のデフォルトコマンドに追加のパラメータを渡し、Redisサーバーを起動させると同時にパスワード認証を強制的に有効化しています (redis-server --requirepass mysecretpassword)。

3.2 Python Web アプリの実行 (ポートマッピング + 環境変数)

まず、極めてシンプルなPython Webアプリケーションのソースコードを記述します(app.py として保存):

from flask import Flask
import os

app = Flask(__name__)

@app.route("/")
def hello():
    name = os.environ.get('NAME', 'World')
    return f"Hello, {name}!"

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

次に、対応する Dockerfile(このアプリをどのようにパッケージングするかを定義)を記述します:

FROM python:3.9-slim-buster
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
ENV FLASK_APP=app.py
CMD ["flask", "run", "--host=0.0.0.0"]

依存関係のリストファイル requirements.txt を作成します:

Flask

さあ、あなた独自のイメージのビルド (Build) を開始しましょう:

docker build -t my-python-app .

最後に、奇跡の瞬間を目の当たりにしてください。コンテナを実行します:

docker run -d --name my-app -p 5000:5000 -e NAME=Docker my-python-app

このコマンドは、あなたが先ほど書いたPythonプログラムをバックグラウンドで実行し、サービスポート 5000 をホストマシンにマッピングし、環境変数 -e NAME=Docker を介して見事にコードの出力ロジック (Logic) を変更しました。ブラウザを開いて http://localhost:5000 にアクセスすると、画面にはカスタマイズされた "Hello, Docker!" が表示されるはずです。