【初心者向け】Dockerコンテナへ入る方法と基本的なコマンド

はい、承知いたしました。【初心者向け】Dockerコンテナへ入る方法と基本的なコマンドについての詳細な解説記事を、約5000語で作成し、直接表示します。


【初心者向け】Dockerコンテナへ入る方法と基本的なコマンド

Dockerを使い始めた皆さん、こんにちは!

Dockerは、アプリケーションとその実行環境をまとめて「コンテナ」という軽量な箱に詰め込む技術です。このコンテナのおかげで、「自分の環境では動くのに、他の人の環境では動かない」といった問題を劇的に減らすことができます。

さて、Dockerを使っていると、たまに「コンテナの内部はどうなっているんだろう?」「このファイルはコンテナのどこに保存されているんだろう?」「コンテナ内で特定のコマンドを実行してみたい」と思うことがあるでしょう。

そんな時に必要になるのが、「実行中のDockerコンテナの内部に入って操作する」方法です。

この記事では、Docker初心者の方でも安心して理解できるよう、コンテナの基本的な考え方から、実行中のコンテナに「入る」ための最も一般的で強力なコマンドであるdocker execについて、その使い方、オプション、そしてコンテナ内で役立つ基本的なLinuxコマンドまでを、非常に詳細かつ分かりやすく解説します。

さあ、Dockerコンテナの世界を覗きに行きましょう!

1. Dockerの基本を簡単におさらい

詳細な解説に入る前に、Dockerの基本的な要素を簡単におさらいしておきましょう。これにより、なぜコンテナに入るという操作が必要になるのか、その背景がより明確になります。

1.1. イメージとコンテナの違い

Dockerの最も基本的な概念は「イメージ (Image)」と「コンテナ (Container)」です。

  • イメージ (Image): アプリケーションとその実行に必要なすべてのもの(コード、ランタイム、システムツール、ライブラリ、設定ファイルなど)をパッケージ化した、読み取り専用のテンプレートです。例えるなら、「家電製品の設計図」のようなものです。このイメージから、実際に動く「コンテナ」が作成されます。イメージはDocker Hubなどのコンテナレジストリから取得したり、Dockerfileという定義ファイルを使って自分で作成したりします。
  • コンテナ (Container): イメージから作成された、実行中のインスタンスです。イメージが設計図なら、コンテナは「設計図に基づいて実際に製造され、電源が入って動いている家電製品」です。コンテナは独立しており、ホストOSや他のコンテナから隔離されています。コンテナごとに独自のファイルシステム、プロセス空間、ネットワークインターフェースを持ちます。

つまり、イメージは「止まった状態の設計図や雛形」コンテナは「動いている実体」です。私たちがこれから「入る」のは、この「動いている実体」であるコンテナの内部です。

1.2. コンテナのライフサイクル

コンテナにはいくつかの状態があります。

  • Created: コンテナが作成されたが、まだ起動していない状態。
  • Running: コンテナが起動し、アプリケーションが実行されている状態。
  • Paused: 実行中のコンテナが一時停止された状態。
  • Exited: コンテナ内のメインプロセスが終了し、コンテナが停止した状態。
  • Dead: コンテナが削除されようとしている、あるいは削除に失敗した状態(あまり一般的な状態ではありません)。

私たちが「コンテナに入る」という操作を行うのは、基本的にコンテナがRunningの状態にあるときです。停止したコンテナ(Exited状態)には、後述するdocker execコマンドを使って入ることはできません(ただし、停止したコンテナからファイルを取り出すなどの操作は別の方法で可能です)。

1.3. コンテナの隔離性

Dockerコンテナの大きな特徴の一つは「隔離性 (Isolation)」です。各コンテナは、ホストOSや他のコンテナから一定レベルで隔離されています。

  • ファイルシステムの隔離: コンテナごとに独自のルートファイルシステムを持ちます。ホストOSのファイルシステムとは異なります(ただし、後述するVolumeを使えば共有も可能です)。
  • プロセス空間の隔離: コンテナ内で実行されるプロセスは、基本的にそのコンテナ内に閉じ込められています。ホストOSや他のコンテナのプロセスを直接操作することはできません(PID Namespaceによる隔離)。
  • ネットワークの隔離: コンテナごとに独自のネットワークスタックを持つことができます(Network Namespaceによる隔離)。ただし、ポートフォワーディングなどでホストOSや外部ネットワークと通信できるように設定するのが一般的です。
  • ユーザー管理の隔離: コンテナ内には独自のユーザーやグループが存在できます。ホストOSのユーザーとは異なります(User Namespaceによる隔離も可能ですが、デフォルトではホストと同じUID/GIDで実行されることが多いです)。

このように隔離されているからこそ、コンテナの内部を調査したり、一時的にコマンドを実行したりするために、「コンテナの内部に入る」という操作が必要になるのです。ホストOSから直接コンテナのファイルシステムをいじったり、コンテナ内のプロセスを管理したりするのは難しいからです。

2. なぜコンテナに入る必要があるのか?具体的な利用シナリオ

コンテナは基本的に、その中で実行されるべきアプリケーション(Webサーバー、データベース、バッチ処理など)が自動的に起動し、外部からのリクエストを処理したり、タスクを実行したりするように設計されます。理想的には、コンテナの内部に手動でログインして操作する必要はない方が望ましいとされています(「不変性 (Immutability)」の原則)。

しかし、現実の運用や開発においては、実行中のコンテナの内部に「入って」作業したい状況がいくつかあります。

  • デバッグとトラブルシューティング: これが最も一般的な理由でしょう。
    • アプリケーションがコンテナ内でエラーを出すが、ログだけでは原因が特定できない場合。
    • コンテナ内の特定の設定ファイルの内容を確認したい場合。
    • コンテナから外部のネットワークリソース(データベース、APIなど)に接続できるか確認したい場合(pingcurlコマンドを使う)。
    • コンテナ内で実行されているプロセスの状態(CPU使用率、メモリ使用量など)を確認したい場合。
    • 特定のパスにファイルが正しく配置されているか確認したい場合。
  • コンテナ内の環境調査:
    • イメージをビルドしたが、その中に特定のライブラリやツールが含まれているか確認したい場合。
    • コンテナ内のファイルシステム構造やディレクトリ構成を確認したい場合。
    • コンテナ内の環境変数を確認したい場合。
  • 一時的な操作:
    • 開発中やテスト中に、コンテナ内のデータベースに手動でデータを投入したり、特定のスクリプトを一時的に実行したりしたい場合。
    • コンテナ内のファイルシステムに一時的にファイルをコピーしたり、編集したりしたい場合(ただし、後述しますが、これは推奨されない操作であり、デバッグ目的などに限定すべきです)。
  • ワンオフのタスク実行:
    • コンテナイメージに梱包されている特定の管理コマンドやバッチ処理を、コンテナ起動時のメインプロセスとは別に実行したい場合。

このように、コンテナの内部状態を直接確認したり、一時的な操作を行ったりする際に、「コンテナに入る」という操作は非常に有効な手段となります。

3. コンテナに入る最も一般的な方法: docker execコマンド

実行中のDockerコンテナの内部に入るための最も一般的かつ推奨される方法は、docker execコマンドを使うことです。

3.1. docker execとは?

docker execコマンドは、実行中のコンテナ内で新しいコマンドを実行するために使われます。これは、そのコンテナが最初に起動されたときに実行されたメインプロセスとは別の、新しいプロセスとして実行されます。

例えるなら、動いているコンピュータ(コンテナ)に対して、SSHでログインするのではなく、「リモートからコマンドプロンプトやターミナルを開いて、そこに直接コマンドを打ち込む」ようなイメージです。そして、そのコマンドの標準入力、標準出力、標準エラー出力を、ホスト側のターミナルと接続することができます。

3.2. docker execの基本的な構文

docker execコマンドの基本的な構文は以下のようになります。

bash
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

  • [OPTIONS]: docker execコマンド自体の動作を制御するためのオプションです。後で詳しく説明します。
  • CONTAINER: コマンドを実行したい対象のコンテナを指定します。コンテナの「名前」または「コンテナID」のどちらかを使います。コンテナIDは長い文字列ですが、先頭の数文字(通常3~4文字)でも一意に特定できれば指定可能です。
  • COMMAND: コンテナの内部で実行したいコマンドを指定します。例えば、lspwdbashshなどです。
  • [ARG...]: COMMANDに渡す引数です。

3.3. 実行中のコンテナを確認する (docker ps)

docker execを使うには、まず対象のコンテナが実行中である必要があります。現在実行中のコンテナを確認するには、docker psコマンドを使います。

bash
docker ps

実行例:

bash
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 ubuntu:latest "bash" 5 minutes ago Up 5 minutes my-ubuntu-container
0123456789ab nginx:latest "nginx -g 'daemon of…" 10 minutes ago Up 10 minutes 80/tcp my-nginx-container

この出力から、実行中のコンテナの「コンテナID (CONTAINER ID)」、「イメージ名 (IMAGE)」、「実行中のコマンド (COMMAND)」、「作成からの時間 (CREATED)」、「状態 (STATUS)」、「公開ポート (PORTS)」、「コンテナ名 (NAMES)」などが確認できます。

docker execで対象を指定するには、CONTAINER ID(例: a1b2c3d4e5f6 やその一部)または NAMES(例: my-ubuntu-container)のどちらかを使います。コンテナ名は人間にとって分かりやすいので、可能であればコンテナ名を付けて起動し、それを使うのがおすすめです(docker run --name my-container ...)。

3.4. コンテナ内で単一のコマンドを実行する

まずは、コンテナの内部に入って対話的に操作するのではなく、単にコンテナ内で一度だけコマンドを実行してその結果を得る方法を見てみましょう。

例として、先ほどのmy-ubuntu-container(コンテナID a1b2c3d4e5f6)の中で、ルートディレクトリ (/) のファイル一覧を表示するls /コマンドを実行してみます。

コンテナ名を使う場合:
bash
docker exec my-ubuntu-container ls /

コンテナIDを使う場合(例: 先頭4文字):
bash
docker exec a1b2 ls /

実行すると、コンテナ内の / ディレクトリにあるファイルやディレクトリの一覧が表示されるはずです。

bash
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

このように、docker execの後にコンテナ名/IDと実行したいコマンドを続けるだけで、コンテナ内部でコマンドを実行し、その標準出力結果をホスト側のターミナルで受け取ることができます。これは、コンテナ内の特定の設定ファイルを確認したいときなどに非常に便利です(例: docker exec my-container cat /app/config.yml)。

3.5. コンテナに入って対話的なシェルを起動する (-it オプション)

さて、本題である「コンテナの内部に入って、ターミナルで操作する」方法です。これには、docker execコマンドに-i-tという二つのオプションを組み合わせた-itオプションを使います。

  • -i (or --interactive): コンテナの標準入力 (STDIN) に接続します。これにより、ホスト側のターミナルからコンテナ内のコマンドにキーボード入力を送ることができるようになります。このオプションがないと、対話的なシェルを起動しても、何も入力できずにすぐに終了してしまいます。
  • -t (or --tty): 擬似端末 (pseudo-TTY) を割り当てます。これにより、ターミナルらしい表示(プロンプトの表示、カーソル移動、入力のエコーバックなど)が可能になります。このオプションがないと、入力も出力も味気ないテキストの羅列になり、シェルの操作が非常に難しくなります。

この二つを組み合わせた-itオプションを使うことで、まるでSSHでリモートサーバーにログインしたかのように、コンテナ内で対話的なシェル操作ができるようになります。

対話的なシェルとして最も一般的なのは、Linuxにおけるbashshといったシェルです。多くのコンテナイメージにはこれらのシェルが含まれています。

コンテナに入ってbashシェルを起動するコマンド:
bash
docker exec -it CONTAINER bash

または、コンテナにbashが入っていない場合はshを試します:
bash
docker exec -it CONTAINER sh

例として、my-ubuntu-containerbashで入ってみましょう。

bash
docker exec -it my-ubuntu-container bash

成功すると、ホスト側のターミナルの表示がコンテナ内のプロンプトに変わります。

bash
root@a1b2c3d4e5f6:/#

プロンプトの表示はコンテナの設定やシェルによって異なりますが、多くの場合、ユーザー名(ここではroot)やホスト名(コンテナIDの一部)、現在のディレクトリなどが表示されます。

これで、あなたはmy-ubuntu-containerという名前のコンテナの「内部」に入った状態です。ここで実行するコマンドは、すべてそのコンテナ内で実行されます。

3.6. コンテナ内での操作と終了

コンテナ内でシェルに入った後は、通常のLinuxターミナルと同じようにコマンドを実行できます。

  • ファイル一覧を表示: ls
  • 現在のディレクトリを表示: pwd
  • ディレクトリを移動: cd /app
  • ファイルの内容を表示: cat /etc/os-release
  • 環境変数を確認: env

コンテナ内での作業が終わったら、シェルを終了してホスト側のターミナルに戻る必要があります。シェルを終了するには、exitコマンドを入力するか、Ctrl + Dキーを押します。

bash
root@a1b2c3d4e5f6:/# exit
exit

exitを入力してエンターキーを押すと、コンテナ内のシェルプロセスが終了し、自動的にホスト側のターミナルに戻ります。

重要: docker exec -itで起動したシェルをexitで終了しても、元のコンテナ自体は停止しませんdocker execはコンテナ内で新しいプロセスを起動するだけなので、その新しいプロセス(この場合はシェル)が終了しても、コンテナのメインプロセスは影響を受けずに実行を続けます。コンテナを停止するには、別途docker stop CONTAINERコマンドが必要です。

4. docker execコマンドの様々な使い方とオプションの詳細

docker execコマンドには、さらに便利なオプションがいくつかあります。これらを使いこなすことで、より柔軟にコンテナ内部の操作を行うことができます。

4.1. 特定のユーザーとしてコマンドを実行する (-u)

コンテナ内で実行されるコマンドは、デフォルトではコンテナイメージで定義されたユーザー(多くの場合rootユーザー)として実行されます。しかし、セキュリティ上の理由や権限の問題から、特定のユーザーとしてコマンドを実行したい場合があります。そんなときは-uオプションを使います。

構文:
bash
docker exec -u USER CONTAINER COMMAND [ARG...]

USERには、ユーザー名(例: www-data)またはユーザーID(UID、例: 33)を指定します。グループID(GID)も一緒に指定する場合は、UID:GIDの形式で指定します(例: 1000:1000)。

例:my-ubuntu-container内で、UIDが1000のユーザーとして/homeディレクトリのファイル一覧を表示する。
bash
docker exec -u 1000 my-ubuntu-container ls /home

例:my-nginx-container内で、www-dataユーザーとして現在のユーザー名を表示する。
bash
docker exec -u www-data my-nginx-container whoami

このオプションは、コンテナ内のファイルの権限を確認したり、特定のユーザーの権限でしか実行できないコマンドを試したりする場合に役立ちます。ただし、指定したユーザーやUID/GIDがコンテナ内に存在しない場合はエラーになります。

4.2. 作業ディレクトリを指定する (-w)

docker execでコマンドを実行したり、シェルに入ったりする際、デフォルトの作業ディレクトリはコンテナイメージで定義されたワーキングディレクトリ(DockerfileのWORKDIR命令で指定)か、それがなければルートディレクトリ (/) になります。実行したいコマンドが特定のディレクトリに関連する場合、-wオプションで作業ディレクトリを指定すると便利です。

構文:
bash
docker exec -w WORKDIR CONTAINER COMMAND [ARG...]

例:my-app-container内で/appディレクトリを作業ディレクトリとしてlsコマンドを実行する。
bash
docker exec -w /app my-app-container ls

これは、docker exec my-app-container ls /appと似ていますが、-wを使うことで後続のコマンドがそのディレクトリを基準にするため、複雑なコマンドチェーンを実行する際に便利です。

例:/usr/local/binを作業ディレクトリとしてpwdを実行する。
bash
docker exec -w /usr/local/bin my-ubuntu-container pwd

出力は/usr/local/binとなります。

例:対話シェルに入る際に、最初から/var/logディレクトリにいたい場合。
bash
docker exec -it -w /var/log my-ubuntu-container bash

シェルに入ると、現在のディレクトリが/var/logになっているはずです。

4.3. 環境変数を設定する (-e)

コンテナ内で実行するコマンドに対して、一時的に環境変数を設定したい場合があります。これには-eオプションを使います。コンテナ起動時に設定された環境変数に加えて、ここで指定した環境変数がコマンド実行時のみ有効になります。

構文:
bash
docker exec -e KEY=VALUE [-e KEY2=VALUE2 ...] CONTAINER COMMAND [ARG...]

例:my-app-container内でDEBUG=trueという環境変数を設定して、特定のスクリプトを実行する。
bash
docker exec -e DEBUG=true my-app-container python /app/debug_script.py

例:シェルに入って環境変数を確認する際に、一時的に特定の変数を追加してみる。
bash
docker exec -it -e MY_VAR="hello world" my-ubuntu-container bash

シェルに入った後、echo $MY_VARを実行するとhello worldと表示されるはずです。envコマンドでも確認できます。

複数の環境変数を設定する場合は、-eオプションを複数回繰り返します。

4.4. バックグラウンドでコマンドを実行する (-d)

docker execコマンドはデフォルトではフォアグラウンドで実行され、指定したコマンドが終了するまでホスト側のターミナルを専有します。しかし、コンテナ内で時間のかかる処理やバックグラウンドで動かしたいプロセスを起動したい場合は、-dオプション(--detach)を使います。

構文:
bash
docker exec -d CONTAINER COMMAND [ARG...]

例:my-app-container内で、バックグラウンドでログ収集スクリプトを起動する。
bash
docker exec -d my-app-container /app/start_log_collector.sh

このコマンドを実行しても、ホスト側のターミナルはすぐに解放され、コンテナ内で指定したコマンドがバックグラウンドで実行されます。バックグラウンドで実行されたコマンドの出力は、デフォルトではコンテナの標準出力/標準エラー出力には表示されません。ログを確認したい場合は、別途docker logs CONTAINERコマンドを使う必要があります。

-dオプションは、シェルを対話的に起動するためには使用しません。対話的な操作には-itが必要です。

4.5. docker execで実行できないコマンドがあるのはなぜ?

docker execでコンテナ内に入ってコマンドを実行しようとした際に、「command not found」(コマンドが見つかりません)というエラーに遭遇することがよくあります。これは、コンテナイメージが必要最低限のファイルやツールだけを含むように作られていることが多いためです。

特に公式イメージや軽量なディストリビューション(Alpine Linuxなど)をベースにしたイメージでは、pingcurlvimtoppsなどの便利なツールがデフォルトでは含まれていないことがよくあります。

これは、コンテナイメージのサイズを小さく保ち、セキュリティリスクを減らすための意図的な設計です。イメージが大きいと、ダウンロードやデプロイに時間がかかりますし、含まれるソフトウェアが多いほど、脆弱性のリスクも高まります。

もし、デバッグやトラブルシューティングのために一時的に特定のツールが必要な場合は、コンテナ内でパッケージマネージャー(Debian/Ubuntuならapt、Alpineならapk、CentOS/RHELならyum/dnfなど)を使ってインストールすることも技術的には可能です。

例(Debian/Ubuntuベースのコンテナ内でpingをインストールする場合):
bash
docker exec -it my-ubuntu-container bash

シェルに入ってから:
bash
apt update
apt install iputils-ping

ただし、これはデバッグ目的などの一時的な手段としてのみ推奨されます。 コンテナ内で手動でソフトウェアをインストールして行った変更は、そのコンテナが停止・削除されると失われます。永続的な変更や、デプロイされるすべてのコンテナに含めたいツールは、Dockerfileに追記してイメージ自体を再ビルドするべきです。

docker execはあくまで「実行中のコンテナの状態を確認したり、一時的な操作をしたりするための窓」と捉えましょう。

5. コンテナ内で役立つ基本的なLinuxコマンド

docker exec -itでコンテナのシェルに入ることができたら、次は実際にコンテナ内部を探索したり、情報を収集したりする必要があります。コンテナは通常Linuxベースの環境なので、基本的なLinuxコマンドを知っていると非常に役立ちます。

ここでは、コンテナ内で特に頻繁に使うことになる基本的なLinuxコマンドを紹介します。前述のように、すべてのコマンドが利用できるとは限りません。

5.1. ファイルシステム関連

  • ls:ディレクトリの内容(ファイルやサブディレクトリ)を一覧表示します。
    • ls:現在のディレクトリの内容を表示。
    • ls -l:詳細情報(パーミッション、所有者、サイズ、更新日時など)付きで一覧表示。
    • ls -a:隠しファイル(.で始まるファイル)も含めて一覧表示。
    • ls /app:特定のディレクトリの内容を表示。
  • cd:カレントディレクトリを変更します。
    • cd /app/appディレクトリに移動。
    • cd ..:一つ上の親ディレクトリに移動。
    • cd:ホームディレクトリ(通常、コンテナでは/root/)に移動。
  • pwd:現在の作業ディレクトリのパスを表示します。
  • cat:ファイルの内容を表示します。
    • cat /etc/os-release:OSのバージョン情報を表示。
    • cat /app/config.json:アプリケーションの設定ファイルの内容を表示。
  • head:ファイルの先頭部分を表示します。
    • head -n 10 /var/log/app.log:ログファイルの最初の10行を表示。
  • tail:ファイルの末尾部分を表示します。ログファイルのリアルタイム監視によく使われます。
    • tail /var/log/app.log:ログファイルの最後の部分を表示。
    • tail -f /var/log/app.log:ログファイルが追記されるのをリアルタイムで表示(終了するにはCtrl + C)。
  • less / more:ファイルの内容をページごとに表示します。大きなファイルを扱う際に便利です。
    • less /var/log/large_app.log
    • lessmoreでファイルを開いた後、スペースキーで次のページ、qキーで終了します。
  • grep:ファイルの中から特定の文字列を検索します。
    • cat /var/log/app.log | grep "ERROR":ログファイルから”ERROR”を含む行を抽出。
    • grep -r "search_string" /app/appディレクトリ以下で”search_string”を再帰的に検索。
  • find:指定した条件に合うファイルやディレクトリを検索します。
    • find /app -name "*.log"/app以下で拡張子が.logのファイルを検索。
  • du:ファイルやディレクトリのディスク使用量を確認します。
    • du -sh /app/appディレクトリの合計サイズを人間が読める形式で表示。
  • df:ファイルシステムのディスク空き容量を確認します。
    • df -h:ディスク全体の空き容量などを人間が読める形式で表示。
  • mkdir:新しいディレクトリを作成します。
  • touch:空のファイルを作成したり、既存ファイルのタイムスタンプを更新したりします。
  • cp:ファイルやディレクトリをコピーします。
  • mv:ファイルやディレクトリを移動または名前変更します。
  • rm:ファイルやディレクトリを削除します。
    • rm myfile.txt:ファイルを削除。
    • rm -r mydir:ディレクトリとその中身を再帰的に削除(注意! 誤って重要なファイルを削除しないように十分注意してください)。

これらのコマンドは、コンテナ内のファイル構成を確認したり、ログファイルを読んだり、設定ファイルの内容を一時的に確認したりするのに不可欠です。

5.2. プロセス管理関連

コンテナ内でアプリケーションプロセスが正しく起動しているか、リソースを消費しすぎていないかなどを確認するのに使います。

  • ps:実行中のプロセスを一覧表示します。
    • ps aux:コンテナ内のすべてのユーザーのすべてのプロセスを詳細に表示。このコマンドで、コンテナのメインプロセス(多くの場合、docker runで指定したコマンド)や、docker execで起動したシェルプロセス、その他の子プロセスなどが確認できます。
  • top:システムのプロセス情報やリソース使用状況(CPU、メモリなど)をリアルタイムで表示します。
    • 多くの軽量イメージには含まれていないため、必要に応じてインストールが必要な場合があります。
  • kill:指定したプロセスにシグナルを送ります(プロセスの終了など)。
    • kill 123:PIDが123のプロセスにTERMシグナル(デフォルト)を送って終了させようとする。
    • kill -9 123:PIDが123のプロセスを強制終了する(あまり推奨されないが、応答しない場合に使う)。
    • ps auxなどでプロセスのPIDを確認してから使用します。

5.3. ネットワーク関連

コンテナが外部ネットワークや他のサービスと正しく通信できるかを確認するのに使います。

  • ping:指定したホストとの間のネットワーク接続を確認します。
    • ping google.com:インターネット上のホストとの接続を確認。
    • ping 172.17.0.1:ホストOSのDockerネットワークインターフェース(デフォルトの場合)との接続を確認。
  • curl / wget:URLを指定してリソースを取得します。Webサービスへの接続確認などに使います。
    • curl http://localhost/:コンテナ内で動作しているWebサーバーにアクセス。
    • curl http://another-service-container-name:8080/:他のコンテナ内のサービスにアクセス(Dockerネットワークによる名前解決が必要)。
    • curl https://api.example.com/:外部のAPIにアクセス。
  • netstat:ネットワーク接続、ルーティングテーブル、インターフェース統計などを表示します。
    • netstat -tulnp:TCP/UDPポートでListenしているプロセスを表示(-pはroot権限が必要なことが多い)。
  • ip:ネットワークインターフェースやルーティングを設定・表示するコマンド(ifconfigの後継)。
    • ip a:ネットワークインターフェースとそのIPアドレスを表示。
    • ip r:ルーティングテーブルを表示。

これらのネットワークツールは、コンテナが想定通りに通信できているか、ファイアウォールやネットワーク設定に問題がないかなどをデバッグする際に非常に役立ちます。

5.4. その他

  • env:コンテナ内で設定されているすべての環境変数を表示します。アプリケーションの動作が環境変数に依存している場合などに確認します。
  • whoami:現在ログインしているユーザー名を表示します。
  • id:現在のユーザーとグループのIDを表示します。
  • echo:文字列を表示します。環境変数の内容などを確認するのに使います(例: echo $PATH)。

これらの基本的なLinuxコマンドは、コンテナ内部の状態を理解し、問題を診断するための強力なツールとなります。使い慣れていない方は、ぜひこの機会に少しずつ慣れていくことをお勧めします。

6. コンテナへの他のアクセス方法(execとの比較)

docker execはコンテナに入る最も一般的で柔軟な方法ですが、コンテナとやり取りする方法は他にもいくつか存在します。それらを簡単に紹介し、execとの違いを明確にしておきましょう。

6.1. docker attach

docker attach CONTAINERコマンドは、実行中のコンテナのメインプロセスの標準入力、標準出力、標準エラー出力に「アタッチ(接続)」します。

  • execとの違い:
    • docker execはコンテナ内で新しいプロセス(例: bashシェル)を起動しますが、docker attachはコンテナ起動時に指定された元のメインプロセスに接続します。
    • docker attachで接続したシェルなどでexitしたり、Ctrl + Cなどでメインプロセスに割り込みシグナルを送ったりすると、コンテナ自体が停止してしまう可能性が高いです。これは、多くの場合コンテナのメインプロセスが終了すると、Dockerエンジンがそのコンテナも停止させるためです。
    • docker execで起動したプロセスが終了しても、元のコンテナはそのまま実行を続けます。
    • docker attachは、コンテナが標準入力/出力を使ってユーザーと対話するように設計されている場合に有効ですが、多くの一般的なアプリケーションコンテナ(Webサーバーなど)はバックグラウンドで動作し、標準入力をほとんど使用しないため、attachしても何も起こらないか、あるいは危険な場合があります。
    • docker execの方が、既存のコンテナの実行を妨げずに内部コマンドを実行できるため、より安全で汎用的な方法です。

初心者の方にとっては、docker exec -itを使って新しいシェルを起動し、作業が終わったらexitするのが、コンテナを意図せず停止させてしまうリスクが少なく、推奨される方法です。docker attachは、コンテナの起動プロセス自体をデバッグしたいような、より限定的なケースで使用されます。

6.2. docker logs

docker logs CONTAINERコマンドは、実行中または停止したコンテナの標準出力 (stdout) および標準エラー出力 (stderr) に出力されたログを表示します。

  • execとの違い:
    • docker logsはコンテナの出力を参照するだけであり、コンテナの内部に入ってコマンドを実行するものではありません。
    • コンテナがエラーを出力している場合など、そのログを確認してデバッグの手がかりを得るために使用します。
    • -fオプションを付けると、新しいログが追加されるたびにリアルタイムで表示することができます(tail -fコマンドに似ています)。

これはコンテナの状態を把握するために非常に重要なコマンドですが、「コンテナに入る」操作とは異なります。

6.3. docker cp

docker cp <ローカルパス> <コンテナ名>:<コンテナパス> または docker cp <コンテナ名>:<コンテナパス> <ローカルパス> コマンドは、ホストOSとコンテナ間でファイルをコピーするために使用します。

  • execとの違い:
    • docker cpもコンテナのファイルシステムとやり取りするコマンドですが、コンテナの内部に入ってシェルを操作するものではありません。
    • コンテナ内の特定の設定ファイルを取り出してホスト側で編集したい場合や、ホスト側のファイルをコンテナ内に配置したい場合などに使います。

docker execでコンテナ内に入ってcatでファイル内容を確認したり、vi/nanoで編集したりすることも可能ですが、複雑な編集が必要な場合や、ファイルをまとめてやり取りしたい場合はdocker cpの方が便利なことがあります。

7. コンテナ操作時の注意点とベストプラクティス

docker execを使ってコンテナ内部を操作できることは非常に強力ですが、いくつか注意すべき点や推奨されるプラクティスがあります。これらを理解しておくことで、予期せぬ問題を防ぎ、Dockerのメリットを最大限に活かすことができます。

7.1. コンテナは使い捨て(Ephemeral)であるという原則

Dockerコンテナは、「使い捨て(Ephemeral)」であるように設計・運用されるのが理想的です。これは、必要になればいつでも停止・削除し、同じイメージから新しいコンテナを起動すれば、完全に同じ状態のものが再現されるべきだという考え方です。

この原則に基づくと、実行中のコンテナ内部に手動で入って行った変更(ファイルの追加/編集、ソフトウェアのインストール、設定変更など)は、そのコンテナが停止・削除されると失われてしまいます。次に同じイメージから新しいコンテナを起動しても、手動で行った変更は引き継がれません。

デバッグや一時的な確認のためにdocker execを使うのは全く問題ありませんが、永続化したい設定変更や、デプロイされるすべてのコンテナに適用したい変更は、Dockerfileを修正して新しいイメージをビルドし、そのイメージを使ってコンテナを起動するようにしましょう。

  • 良い例: 「このイメージにはpingコマンドが含まれていないから、デバッグのために一時的にapt install iputils-pingでインストールしてみよう」
  • 悪い例: 「この設定ファイル、コンテナの中で直接編集すれば開発環境では動くようになるな。よし、本番環境でも毎回docker execで入ってこのファイルを編集しよう」 → これはアンチパターンです。設定ファイルはVolumeを使って外部からマウントするか、Dockerfileの中でイメージに含めるか、環境変数で渡すなどの方法をとるべきです。

7.2. データの永続化にはVolumeを使用する

コンテナが停止・削除されても保持しておきたいデータ(データベースのデータ、ユーザーがアップロードしたファイル、ログファイルなど)は、コンテナの内部ファイルシステムに直接書き込むのではなく、Docker VolumeまたはBind Mountを使用すべきです。

  • Volume: Dockerが管理する特別な領域にデータを保存する方法。コンテナのライフサイクルから独立しており、複数のコンテナ間で共有することも可能です。
  • Bind Mount: ホストOS上の特定のディレクトリをコンテナ内のディレクトリにマウントする方法。ホストOS上のファイルやディレクトリをコンテナから直接アクセス・操作できます。

docker execでコンテナ内部を操作している際に、もし永続化されたいデータがあるディレクトリ(例: /var/lib/mysql, /app/uploadsなど)をいじりたい場合は、それがVolumeやBind Mountとしてマウントされている場所であることを意識しましょう。その場所への変更は、コンテナが削除されても失われません(ただし、マウント元のVolumeやホストディレクトリを削除しない限り)。

逆に、/tmpやアプリケーションコードが配置されている場所など、Volumeとしてマウントされていない場所への変更はコンテナ削除時に失われます。

7.3. セキュリティへの考慮

docker execは、実行中のコンテナ内で任意のコマンドを実行できてしまうため、強力であると同時に注意が必要です。

  • 本番環境での利用: 本番環境で稼働中のコンテナに対して安易にdocker execを実行するのは、意図しない変更を加えてサービスに影響を与えたり、セキュリティリスクを生んだりする可能性があるため、慎重に行うべきです。必要な場合でも、どのような操作を行うか事前に計画し、監査ログが残るように設定することが推奨されます。
  • root権限: デフォルトでは、コンテナ内で実行されるコマンドはrootユーザーとして実行されることが多いです。root権限での操作は、コンテナ内部のシステムに大きな影響を与える可能性があるため、特に注意が必要です。必要に応じて-uオプションで権限の低いユーザーを指定することを検討しましょう。
  • 不要なツールの削除: デバッグのために一時的にインストールしたツールは、作業が終わったらアンインストールするか、あるいはそもそもデバッグ用の専用イメージを用意することを検討しましょう。本番運用するイメージには、必要最低限のツールのみを含めるのがセキュリティ上のベストプラクティスです。

7.4. シェルコマンドの互換性 (bash vs sh)

多くのLinuxディストリビューションではデフォルトのシェルとしてbashが使われていますが、Alpine Linuxのような軽量ディストリビューションをベースにしたコンテナイメージでは、より軽量なash(多くの場合/bin/shとしてリンクされている)がデフォルトのシェルとして使われていることがあります。

bashsh(またはash)は互換性がありますが、bash固有の機能(例えば、bash独自のシェルスクリプト構文や、コマンド履歴の高度な機能など)を使おうとすると、shではエラーになることがあります。

docker exec -it CONTAINER bashでエラーになる場合は、コンテナにbashがインストールされていない可能性が高いので、代わりにdocker exec -it CONTAINER shを試してみてください。

また、docker execで実行するコマンドがシェルスクリプトである場合、そのスクリプトがどのシェルを想定して書かれているか(スクリプトの先頭にある#!/bin/bash#!/bin/shといったShebang行で示されることが多い)を確認し、適切なコマンドで実行することが重要です。

8. よくある疑問とトラブルシューティング

docker execを使う上で、初心者の方が遭遇しやすい疑問や問題点について解説します。

Q1: Error: No such container: <container_name_or_id> と表示される。

原因: 指定した名前またはIDのコンテナが見つかりません。
対策:
1. コンテナ名またはIDが正確か確認してください。コピー&ペースト時のミスなどが考えられます。
2. 対象のコンテナが実行中か確認してください。docker psコマンドを実行し、リストに表示されているか、STATUSがUp ...となっているか確認します。docker execは実行中のコンテナに対してのみ使用できます。停止したコンテナの場合は、docker ps -aで存在は確認できますが、execはできません。

Q2: Error: OCI runtime exec failed: exec failed: unable to start container process: exec: "<command>": executable file not found in $PATH: unknown と表示される。

原因: コンテナ内で指定したコマンドが見つかりません。これは、コマンドがコンテナにインストールされていないか、コマンドがPATH環境変数に含まれていないディレクトリにある場合に発生します。
対策:
1. コマンド名にタイプミスがないか確認してください。
2. そのコマンドが本当にコンテナイメージに含まれているか確認してください。多くの軽量イメージには基本的なコマンドしか含まれていません(前述の「docker execで実行できないコマンドがあるのはなぜ?」を参照)。
3. コンテナ内でシェルに入り(例: docker exec -it <container> sh)、手動でそのコマンドを実行できるか試してみてください。もしインストールされていない場合は、「apt install」などで一時的にインストール可能か試すか、Dockerfileを修正してイメージに含めることを検討してください。
4. コマンドがPATHに含まれていない可能性もゼロではありません。コマンドのフルパスを指定して実行してみてください(例: /usr/local/bin/mytool)。

Q3: the input device is not a TTY または cannot enable tty mode on non tty input と表示される。

原因: -tまたは-iオプションが不足しているか、正しく使われていません。特に、対話的なシェル(bash, shなど)を起動しようとしているのに-itオプションを付けていない場合に発生します。
対策: 対話的な操作を行いたい場合は、必ず-itオプションを付けてください。例えば、docker exec -it my-container bash のようにします。

Q4: Error: No such image: <image_name> と表示される。

原因: これはdocker runコマンドなど、イメージを操作する際のエラーです。docker execはコンテナを操作するコマンドであり、直接イメージ名を指定することはありません。コンテナ名やコンテナIDを正しく指定しているか確認してください。

Q5: コンテナ内のファイルシステムへの変更が、コンテナを再起動したら元に戻ってしまう。

原因: これがDockerのコンテナの使い捨て原則です。VolumeやBind Mountとしてマウントされていない、コンテナの書き込み可能なレイヤーへの変更は、コンテナが削除されると失われます。再起動の場合は通常は失われませんが、イメージから再作成(停止してdocker rm後、docker run)すると失われます。
対策: 永続化したいデータや設定は、Docker VolumeまたはBind Mountを使用してください。コンテナ内で手動で行った変更を次回起動時にも反映させたい場合は、その変更内容をDockerfileに反映させて新しいイメージをビルドするのが正しいアプローチです。

Q6: シェルに入った後、特定のディレクトリやファイルが見つからない。

原因:
1. カレントディレクトリが想定と違う場所になっている可能性があります。pwdコマンドで現在のディレクトリを確認してください。
2. ファイルやディレクトリが、コンテナの想定されるパスとは別の場所に配置されている可能性があります。findコマンドで検索してみるか、イメージのDockerfileを確認してファイルがどこにコピーされているか確認してください。
3. VolumeやBind Mountが正しく設定されていない、あるいは空のVolumeがマウントされてしまい、本来そこにあるべきファイルが見えない状態になっている可能性があります。docker inspect CONTAINER_NAMEコマンドでVolumeの設定を確認してください。

これらのトラブルシューティングのヒントは、問題解決の糸口となるはずです。エラーメッセージをよく読み、何が問題なのかを理解しようとすることが重要です。

9. まとめ

この記事では、Dockerコンテナの内部に入るための最も一般的で強力なツールであるdocker execコマンドについて、初心者向けに詳細に解説しました。

  • なぜコンテナに入るのか? デバッグ、環境調査、一時的な操作など、実行中のコンテナの内部状態を確認・操作したい場合に必要になります。
  • docker execの基本: docker exec CONTAINER COMMAND [ARG...]の構文で、実行中のコンテナ内で新しいコマンドを実行します。
  • 対話的なシェル: -itオプション(-i-tの組み合わせ)を使うことで、コンテナ内でbashshなどの対話的なシェルを起動し、自由にコマンドを実行できるようになります。
  • 便利なオプション: -u(ユーザー指定)、-w(作業ディレクトリ指定)、-e(環境変数設定)、-d(バックグラウンド実行)など、状況に応じた使い分けが可能です。
  • コンテナ内の基本コマンド: ls, cd, pwd, cat, grep, ps, top, ping, curl, envなど、基本的なLinuxコマンドを知っているとコンテナ内部の調査が効率的に行えます。ただし、軽量イメージでは多くのコマンドが含まれていないことがある点に注意が必要です。
  • 他のアクセス方法: docker attach(メインプロセスへの接続)、docker logs(ログ参照)、docker cp(ファイルコピー)などがありますが、コンテナの内部を操作するにはdocker execが最も汎用的で安全です。
  • 注意点: コンテナは使い捨てであるという原則を忘れず、永続化したい変更はDockerfileやVolumeで行うべきです。docker execはデバッグや一時的な操作に限定的に使用し、本番環境での安易な利用は避けましょう。

docker execコマンドは、Dockerを使った開発や運用において非常に頻繁に利用される強力なツールです。最初はその使い方に戸惑うかもしれませんが、この記事で解説した基本的な使い方とオプション、そしてコンテナ内での基本的なLinuxコマンドを組み合わせることで、ほとんどのシナリオに対応できるようになります。

これで、皆さんはDockerコンテナの「黒い箱」だった内部を、自在に探索し、必要な情報を引き出し、一時的な作業を行えるようになりました。コンテナの中身が「見える」ようになることで、Dockerに対する理解もより深まり、トラブルシューティングの能力も格段に向上するはずです。

ぜひ実際に手を動かして、色々なコンテナでdocker exec -itを試してみてください。どんなファイルがあるのか、どんなプロセスが動いているのか、探検してみるのが一番の学習方法です。

Happy Containerizing!

コメントする

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

上部へスクロール