どちらもコンテナでコマンドを実行できます。両方ともコンテナを取り外すことができます。
では、docker execとdocker attachの本当の違いは何ですか?
commit PR がドキュメントに追加されました:
注:このコマンド(
attach
)は、コンテナで新しいプロセスを実行するためのものではありません。docker exec
を参照してください。
「 Docker。実行済みコンテナ(run -d
)内でbash\sshを取得する方法? 」に対する答えは、違いを示しています。
(docker> = 1.3)
docker attach
を使用する場合、シェルのインスタンスを1つだけ使用できます。
したがって、コンテナのシェルの新しいインスタンスで新しいターミナルを開く場合は、単にdocker exec
を実行する必要があります。dockerコンテナーが
/bin/bash
コマンドを使用して開始された場合、attachを使用してアクセスできます。そうでない場合は、コンテナー内にbashインスタンスを作成するコマンドexecuteが必要ですexec
を使用します。
この問題 で述べたように:
- 添付は、コンテナ内で余分なものを実行するためではなく、実行中のプロセスに添付するためのものです。
- 「
docker exec
」は、シェルまたはその他のプロセスであっても、すでに開始されたコンテナで新しいことを実行するためのものです。
同じ問題が追加されます:
attach
は、特にLXCコマンドlxc-attach
(これはdocker exec <container> /bin/sh
に似ていますが、LXC固有です)のために適切な名前が付けられていませんが、 Dockerプロセスが開始されました。
プロセスによって、動作は異なる場合があります、たとえば、/bin/bash
にアタッチするとシェルが提供されますが、redis-serverにアタッチするとユーザーのようになります ' dはデーモン化せずにredisを直接開始しました。
/ bin/bashを使用してコンテナーを開始すると、コンテナーになりますPID 1であり、コンテナーのPID 1の内部に入るためにdocker attachが使用されます。 docker attach <container-id>は、コンテナの起動時に説明したように、PID 1であるため、bashターミナル内に移動します。コンテナを終了すると、コンテナが停止します。
一方、docker execコマンドでは、入力するシェルを指定できます。コンテナのPID 1には移動しません。これにより、bashの新しいプロセスが作成されます。 docker exec -it <container-id> bash。コンテナを終了しても、コンテナは停止しません。
nsenterを使用して、コンテナ内に入ることもできます。 nsenter -m -u -n -p -i -t <コンテナーのpid>コンテナーのPIDを見つけるには、docker inspect <container-id> | grep PID
注: -dフラグを使用してコンテナを起動した場合、attachまたはexecを使用して内部に入るために、コンテナを終了してもコンテナは停止しません。
Docker execは新しいコマンドを実行し、コンテナの環境で新しいプロセスを作成しますが、docker attachは、コンテナ内のメインプロセス(PID 1)の標準入力/出力/エラーを対応する現在の標準入力/出力/エラーに接続するだけですターミナル(コマンドの実行に使用しているターミナル)。
コンテナは隔離された環境であり、いくつかのプロセスが環境で実行されています。具体的には、コンテナには、ホストや他のコンテナから隔離された独自のファイルシステムスペースとPIDスペースがあります。 「docker run –it…」を使用してコンテナを起動すると、メインプロセスは擬似ttyとSTDINを開いたままにします。 ttyモードでアタッチすると、構成可能なキーシーケンスを使用してコンテナからデタッチ(および実行したまま)できます。デフォルトのシーケンスはCTRL-p CTRL-qです。 --detach-keysオプションまたは構成ファイルを使用して、キーシーケンスを構成します。 docker attachを使用して、切り離されたコンテナに再接続できます。
Docker execは、コンテナの環境内で、つまりコンテナのPIDスペースに属する新しいプロセスを開始するだけです。
たとえば、「docker run –dit XXX/bin/bash」を使用してコンテナを起動する場合、2つの異なるターミナルを使用してコンテナ(メインプロセス)に接続できます。一方の端末で入力している間、両方の端末が同じttyに接続されているため、もう一方の端末に表示されます。コンテナのメインプロセスにいることに注意してください。「exit」と入力すると、コンテナが終了します(したがって、detach-keysを使用してデタッチする)。両方の端末が終了しました。しかし、2つのターミナルで「docker exec –it XXX/bin/bash」を実行すると、コンテナ内で2つの新しいプロセスが開始され、それらは互いに関連せず、メインプロセスにも関連せず、安全に終了できます。
マイケル・サンが答えで述べたように
docker exec
は新しいコマンドを実行し、コンテナの環境で新しいプロセスを作成しますが、docker attach
はコンテナ内のメインプロセス(PID 1)の標準入力/出力/エラーを対応する標準入力に接続するだけです。現在の端末(コマンドの実行に使用している端末)の/ output/error。
私の答えは、上記の声明を検証し、より明確に理解できるようにすることに焦点を当てます。
ターミナルウィンドウを開き、docker run -itd --name busybox busybox /bin/sh
コマンドを実行します。このコマンドは、busybox
がまだ存在しない場合、イメージをプルします。次に、このイメージを使用して、busybox
という名前のコンテナーを作成します。
docker ps -a | grep busybox
コマンドを実行して、コンテナのステータスを確認できます。
docker top busybox
を実行すると、次のような出力が表示されます。
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
もちろん、PID
、PPID
およびその他の値はあなたの場合は異なります。 pstree
、top
、htop
などの他のツールやユーティリティを使用して、PID
およびPPID
のリストを表示できます。
PID
とPPID
は、プロセスIDと親プロセスIDを意味します。プロセスは、/bin/sh
コマンドを使用してコンテナを作成および開始したときに開始されました。ここで、コマンドdocker attach busybox
を実行します。これにより、コンテナの標準入力/出力/エラーストリームが端末に接続されます。
コンテナをアタッチしたら、sh
コマンドを実行してシェルセッションを作成します。 CTRL-p CTRL-q
シーケンスを押します。これにより、ターミナルがコンテナから切り離され、コンテナの実行が維持されます。 docker top busybox
を実行すると、リストに2つのプロセスが表示されます。
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
ただし、2つのプロセスのPPID
は異なります。実際、2番目のプロセスのPPID
は、最初のプロセスのPID
と同じになります。最初のプロセスは、作成したシェルセッションの親プロセスとして機能します。
次に、docker exec -it busybox sh
を実行します。コンテナ内に入ったら、コマンドdocker top busybox
を実行して、別のターミナルウィンドウでコンテナbusybox
の実行中プロセスのリストを確認します。このようなものが見えるはずです
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
root 7880 7451 0 11:45 pts/1 00:00:00 sh
1番目と3番目のプロセスのPPID
は同じです。これにより、docker exec
はコンテナの環境に新しいプロセスを作成し、docker attach
は標準の入力/出力/エラーを接続するだけです。現在の端末の対応する標準入力/出力/エラーに対応するコンテナ内のメインプロセス。