【Docker使えるようになりたい】【#6 exec vs attach】実行中のコンテナに接続する2つの方法を比較

はじめに

  • 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を使って接続する場合

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 コマンドで接続する場合

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 の入力)。
  • 単一接続の制約: 一度に一つのターミナルからしか安定して接続できない場合があります。

どちらを使うべきか?

docker exec が適している場合

  • メインプロセスを中断せずに操作したい場合: コンテナ内で新しいコマンドを実行したいが、元のアプリケーションには影響を与えたくないとき。
  • 対話的なシェルが必要な場合: コンテナ内でファイルを編集したり、デバッグ作業を行いたいとき。
  • 複数のセッションを開きたい場合: 同時に複数のターミナルから操作したいとき。

docker attach が適している場合

  • メインプロセスが対話的である場合: 例えば、コンテナ内で実行中のアプリケーションがシェルや REPL(Python のインタプリタなど)であるとき。
  • リアルタイムでログや標準出力を確認したい場合: ただし、docker logs -f コマンドも同様の目的で使用できます。

コメントを残す

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

CAPTCHA