docker attachから抜けるにはCtrl+P、Ctrl+Q

  • Docker

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

結論

docker attach で入ったコンテナを、停止させずに抜けるには Ctrl+P → Ctrl+Q の順で押す。

Ctrl を押しっぱなしにして P を押し、そのまま Q を押す、という2ストロークの操作。Ctrl+P,Q のように1回のキー入力で済むわけではない。

なぜCtrl+Cではダメなのか

docker attach で繋いだ状態で Ctrl+C を押すと、そのシグナル(SIGINT)はホスト側の端末ではなく、コンテナ内のメインプロセス(PID 1)にそのまま転送される。

つまり Ctrl+C はターミナルから抜ける操作ではなく、コンテナのメインプロセスを止める操作になる。フォアグラウンドで動いているアプリケーションが SIGINT を受けて終了する作りであれば、そのままコンテナが停止する。

「デタッチ=コンテナを動かしたまま抜ける」ことをしたいなら、Ctrl+C ではなく Ctrl+P, Ctrl+Q を使う必要がある。

detach-keysはカスタマイズできる

Ctrl+P, Ctrl+Q はデフォルトのキー組み合わせであって、固定ではない。docker attach や docker run の --detach-keys オプションで変更できる。

docker attach --detach-keys="ctrl-a" コンテナ名

こうするとデタッチのキーが Ctrl+A 1つになる。Ctrl+P, Ctrl+Q が他の用途(bashの履歴補完やreadlineのキーバインドなど)と被って誤爆する場合は、ここを変えておくと事故が減る。

~/.docker/config.json に detachKeys を設定しておけば、毎回オプションを付けなくても全体のデフォルトを変えられるらしい(実機で設定ファイル経由の挙動までは未確認)。

docker execでは同じ操作は効かない

docker exec -it で入ったシェルは、コンテナのメインプロセスとは別の独立したプロセスとして動いている。そのため Ctrl+P, Ctrl+Q を押しても何も起きない(bashにそのまま渡されるだけ)。

exec で入ったシェルから素直に抜けたいなら exit かCtrl+Dで良い。この場合はコンテナのメインプロセスには影響しない。

ただし、exec で入った先でフォアグラウンドの長時間処理を動かしてしまった場合、それを止めずに抜ける手段は標準では用意されていない。そういうケースでは tmux や screen をコンテナ内に入れておいて、その中でセッションをデタッチする方が現実的。

注意点

  • Ctrl+P, Ctrl+Q が効くのは docker attach で入った場合のみ
  • docker exec -it で入ったシェルではこのショートカットは効かない
  • Ctrl+C はデタッチではなく、コンテナ内メインプロセスへのシグナル送信になるので注意