- docker container exec + bash
- docker container attach
今回のコマンドの比較では、nginx
イメージを使用してコンテナが動いている状態で検証をします。
まず以下のコマンドを実行してnginx
が実行できる環境を用意します。
docker container run -itd --name test nginx
- -i : Interacte Shellを有効化
- -t : 疑似ターミナルを有効化
- -d : デタッチモードで起動
- –name {コンテナ名} : コンテナ名を設定
nginxコンテナを実行すると、すぐにhttpサーバーが起動して動作し続けます。
さらに、接続していない状態を再現するために、デタッチモードで起動しています。
まずは、正常にnginxコンテナが起動しているかを確認するためにdocker container ls
コマンドを実行して状態を確認します。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9139408cbcdd nginx "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 80/tcp test
STATUSがUp
になっていればOKです。
では、次の章から実際に手を動かしながら、2つのコマンドの違いを確認してみます。
章が切り替わるごとにこのセットアップの状態に戻すことでより比較がやりやすいと思います。
Dockerは通常何も設定をしないとフォアグラウンドモードでコンテナを実行します。
-dオプションを付けることでデタッチモード(バックグラウンドモード)でコンテナを実行できるので、サーバーのような裏で動いていてほしいコンテナに適したオプションになります。
docker container exec
コマンドは指定したコマンドをコンテナ内で実行させる
コマンドなので、このコマンドで、bashを実行するということは、以下のような特徴があるといえます。
- 新しいプロセスを開始: コンテナ内で新たに Bash シェルを起動します。
- 影響が少ない: コンテナのメインプロセスに影響を与えずに操作できます。
- 複数のセッションが可能: 同じコンテナ内で複数の Bash セッションを同時に開くことができます。
docker container exec -it test bash
このコマンドを実行することで、以下のような通常のbashの画面が表示されると思います。
この状態は、nginxのhttpサーバーは別のプロセスとして動いているので、Bashの画面が表示されても問題なく動き続けます。
root@9139408cbcdd:/#
確認のために、nginxのプロセスが動いているかservice nginx status
コマンドでチェックしてみます。
root@9139408cbcdd:/# service nginx status
nginx is running.
たとえ、exit
コマンドでプロセスを終了してもexecコマンドで起動したBashを終了させるだけなので、docker container ls
コマンドで確認できるようにhttpサーバープロセスは動き続けています。
root@9139408cbcdd:/# exit
exit
PS C:\Users\daiki\Desktop> docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9139408cbcdd nginx "/docker-entrypoint.…" About an hour ago Up About an hour 80/tcp test
- 安全性が高い: メインプロセスと独立したプロセスを開始するため、元のアプリケーションに影響を与えません。
- 柔軟性: 必要に応じて何度でも新しいセッションを開始できます。
- 特に大きなデメリットはありませんが、リソースの消費が微増する程度です。
docker attach
コマンドを使った場合は、既存のプロセスに対する接続になります。
- 既存のプロセスに接続: コンテナのメインプロセスの標準入出力に接続します。
すでに動いているnginxのコンテナにattachするコマンドは以下のコマンドになります。
(セットアップの状態からコマンドを実行します)
docker container attach test
このコマンドを実行すると、以下のようなサーバーの出力が表示されると思います。
2024/09/17 03:45:49 [notice] 41#41: signal 28 (SIGWINCH) received
2024/09/17 03:45:49 [notice] 39#39: signal 28 (SIGWINCH) received
2024/09/17 03:45:49 [notice] 40#40: signal 28 (SIGWINCH) received
2024/09/17 03:45:49 [notice] 38#38: signal 28 (SIGWINCH) received
2024/09/17 03:45:49 [notice] 36#36: signal 28 (SIGWINCH) received
2024/09/17 03:45:49 [notice] 37#37: signal 28 (SIGWINCH) received
2024/09/17 03:45:49 [notice] 35#35: signal 28 (SIGWINCH) received
2024/09/17 03:45:49 [notice] 32#32: signal 28 (SIGWINCH) received
2024/09/17 03:45:49 [notice] 33#33: signal 28 (SIGWINCH) received
コンテナ実行時にデタッチモード
にせずに起動したコンテナの表示と同じ表示がされます。
このことから、すでに起動していたhttpサーバーを動かしているプロセスにアタッチできたことが確認できます。
exit
を入力することで、プロセスを停止できるので、docker container ls
コマンドを使ってもコンテナが停止していることが確認できると思います。
これは、コンテナの停止を妨げていたdocekr container run
コマンドで起動したプロセスを終了したためコンテナがup状態を維持できなくなり停止したことを表しています。
- メインプロセスの監視: コンテナの標準出力やログをリアルタイムで確認できます。
- リソース効率: 新しいプロセスを起動しないため、追加のリソース消費がありません。
- 操作の制限: メインプロセスが対話的でない場合、入力を受け付けないことがあります。
- リスク: 誤ってメインプロセスを停止させてしまう可能性があります(例:
Ctrl + C
の入力)。 - 単一接続の制約: 一度に一つのターミナルからしか安定して接続できない場合があります。
- メインプロセスを中断せずに操作したい場合: コンテナ内で新しいコマンドを実行したいが、元のアプリケーションには影響を与えたくないとき。
- 対話的なシェルが必要な場合: コンテナ内でファイルを編集したり、デバッグ作業を行いたいとき。
- 複数のセッションを開きたい場合: 同時に複数のターミナルから操作したいとき。
- メインプロセスが対話的である場合: 例えば、コンテナ内で実行中のアプリケーションがシェルや REPL(Python のインタプリタなど)であるとき。
- リアルタイムでログや標準出力を確認したい場合: ただし、
docker logs -f
コマンドも同様の目的で使用できます。