web-dev-qa-db-ja.com

Docker内で変化するターミナルのDocker行数

次の動作を変更する方法を知りたいです。私の端末に28行があるとしましょう。次に、次のコマンドを使用します。

$ tput lines # my terminal
28
$ docker run  --rm  -it ubuntu:16.04 tput lines  # docker container
24  ## WHY??
$ docker run  --rm  -it ubuntu:16.04 bash # docker container inside command
root@810effa2777c:/# tput lines
28

ご覧のとおり、すべての結果が28であるべき場合でも、docker run --rm -it ubuntu:16.04 tput linesとしてコンテナを呼び出すと、常に24私の端末のサイズにもかかわらず。これは、ubuntuコンテナだけでなく、debian(docker run --rm -it debian tput lines)でも試しましたが、同じ結果が得られています24。

これの目的は、ターミナルの行を考慮に入れる mdp presentation tool を使用することです。実装が失敗したとき、他の人の docker implementation を試しましたが、同じエラーが発生しました。

これが画像のエラーです。

Docker number of lines in terminal changing inside docker

誰がそれが何であり、どのようにこれを解決できるのか考えていますか?

34
silgon

2018年9月の更新:docker 18.06に同じ問題があるかどうかを確認します( not should 、後に moby/moby issue 33794 、および moby/moby issue 35407 および PR 3717218.06リリースノート )の一部。


2016年:

buntu Dockerfile に含まれるもの:

CMD ["/bin/bash"]

つまり、デフォルトのENTRYPOINTsh -cです(そして、shセッションでは tputterminfoを使用するため、tput lineはうまく機能しないと思います。その画像のbashのみに設定される可能性のあるデータベース)

ENTRYPOINTbash -cで上書きして、それがうまく機能するかどうかを確認できます。

ただし、コマンドラインからは機能しません。

docker run --entrypoint /bin/bash --rm  -it ubuntu:16.04 -i -c 'tput lines'
24

カスタム画像を定義するオプションをチェックします。

FROM ubuntu:16.04
ENTRYPOINT ["/bin/bash", "-c"]

ただし、結果は同じです。

docker run --rm  -it u 'tput lines'
24

ただし、これは「機能」します。

FROM ubuntu:16.04
ENTRYPOINT [ "/bin/bash" ]

と:

docker@default:/c/Users/vonc/prog/testsu$ docker run --rm  -it u -i -c 'ls; tput lines'
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
48

同じコマンドが時々24を返すので、同期の問題があるかもしれません。

実際、次のalwaysは、「ではなく」を返します。

FROM ubuntu:16.04
ENTRYPOINT [ "/bin/bash", "-l", "-i", "-c" ]

docker run --rm  -it u -c 'sleep 0.1; ls; tput lines'
48

OP silgonコメント内 を提案します:

docker run --rm -it --entrypoint /bin/bash ubuntu:16.04 -c "sleep 0.1 && tput lines"

As BMitch コメント

スリープの成功を考えると、ドッカーは実行中のコマンドでコンテナーを起動し、一度起動すると、クライアントは実行中のコンテナーにアタッチします。通常、数ミリ秒かかるもの。

それは私に別のアイデアを与えました:

docker@default:/c/Users/vonc/prog/testsu$ 
docker run --entrypoint='/bin/bash' --name ub -d -it ubuntu:16.04
  0d9b8783afbb5e3ff4232da071d3f357985351ea1ce4d142bf6617ac456fb76b
docker@default:/c/Users/vonc/prog/testsu$ 
d attach ub
  root@0d9b8783afbb:/# tput lines
  48
  root@0d9b8783afbb:/# exit
exit
docker@default:/c/Users/vonc/prog/testsu$ drmae
0d9b8783afbb5e3ff4232da071d3f357985351ea1ce4d142bf6617ac456fb76b

接続されたセッション内のtput linesは正常に機能します。
drmaeエイリアスで、「 古いおよび使用されていないDockerイメージを削除する方法 」を参照してください)


thajeztah 追加 コメント内

コンテナが作成され、デフォルト(80x24)で開始され、その後(-itの場合)セッションがアタッチされます。
セッションは端末のサイズを指定しています。

コンテナのサイズ変更TTY API」を参照してください。

 DEBU[0244] Calling POST /v1.25/containers/c42fd5c4eb79c06fd7f9912b8359022f7d93887afbb33b57a67ed8bb7bfee4‌​3a/resize?h=46&w=221 

詳細については、 docker issue 2545 を参照してください。
に関連しています 問題10341「コンテナの作成または開始は、高さ/幅のパラメータを受け入れる必要があります」Aleksa Sarai(cyphar) を追加(2016年9月):

これは実際にruntime-spec内で再びポップアップしました( opencontainers/runtime-spec PR 56 )。
基本的に、Windowsは最初の起動時にコンソールサイズを設定する機能を必要とするため、すべてのプラットフォームに追加する可能性があります


OP silgonapi/client/container/run.go のコードを指します:

// Telling the Windows daemon the initial size of the tty during start makes
// a far better user experience rather than relying on subsequent resizes
// to cause things to catch up.
if runtime.GOOS == "windows" {
    hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = dockerCli.GetTtySize()
}

論理的な質問:

linuxでもこのプロパティを使用し、その値を使用して初期コンソールサイズを設定するのは理にかなっていますか?

Kenfe-MickaëlLaventure(mlaventure があり、新しいパッチが Docker 1.1 になります。

16
VonC

更新

次のコマンドでgoinsideコマンドラインツールをインストールできます。

Sudo npm install -g goinside

そして、適切な端末サイズのドッカーコンテナ内に移動します。

goinside docker_container_name

Goinsideの背後にあるロジック

@ VonC answer のおかげで、~/.profileに入れたシンプルなbashスニペットでこの問題の解決策が得られました

goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
export -f goinside

これで、ターミナルサイズの問題なしに、ドッカーコンテナ内に移動できます。

$ goinside containername


goinside関数を使用する前に、source ~/.profileを覚えておいてください


bashでオートコンプリートを有効にする

(以下のコメントのいずれかで共有されているため)goinsideのオートコンプリートを有効にする場合は、.profileでこのスニペットを使用できます。

goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
_goinside(){
    COMPREPLY=( $(docker ps --format "{{.Names}}" -f name=$2) );
}
complete -F _goinside goinside;
export -f goinside;

zshで自動補完を有効にする

zshをデフォルトの端末として使用している場合は、~/.zshrcファイル内でこのスニペットを使用できます。

autoload bashcompinit
bashcompinit
goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
_goinside(){
    COMPREPLY=( $(docker ps --format "{{.Names}}" -f name=$2) );
}
complete -F _goinside goinside;
export goinside;
45
Soorena

行の問題に遭遇することなくコンテナ内でbashを実行する良い方法は here

docker exec -e COLUMNS="`tput cols`" -e LINES="`tput lines`" -ti container bash
3
NotSoShabby

sh対terminfoに関するコメントは、ほとんど無関係です。関連する部分(与えられた答えでは明確ではない)は、コマンドの実行方法です。 tputは、次の順序で3つの機能をチェックします( setupterm を使用):

  1. terminfoデータベースの端末のサイズ(多くの説明ではこの情報は提供されませんが、TERM=xterm24by80)、
  2. オペレーティングシステムから情報を取得できる場合の実際の行数(つまり現在のウィンドウサイズ
  3. LINESおよびCOLUMNS環境変数。

対話型シェルcouldなしで実行されるコマンドは、現在のウィンドウサイズを取得できない方法で実行されます。たとえば、それはssh-tオプション)。また、DockerがLINESおよびCOLUMNS変数を設定することは(無意味ですが)可能です。

動作を説明するには、ケース(1)または(3)のいずれかで十分です。時間遅延や人種を導入しても、それはできません。

1
Thomas Dickey
1
Nico Toub

バージョンDocker version 18.06.1-ce, build e68fc7aでテストしました。同じ問題があるようです。ただし、 github issue の人の1人が 実用的な回避策 を示しました。

docker run --rm -it -e COLUMNS=$COLUMNS -e LINES=$LINES -e TERM=$TERM -it ubuntu:16.04 tput lines
1
silgon