GitHub - kyagi/rod: REPLs On Docker を作っている中で Ammonite の起動が早くなるようにあらかじめライブラリをキャッシュさせておくため .ammonite/predef.sc にライブラリを追加したあとに echo exit | amm -s
を実行するようにしたところ、docker build 中に bash: /dev/tty: No such device or address
が出てビルドに失敗するようになってしまった。原因は amm がメッセージを吐き出す端末(tty)が見つからないことのようだ。REPL はそもそも人間とのインタラクティブなやりとりが想定されているのだから、至極当然な気もするが、このままでは Docker イメージが作れない。
Dockerfile
RUN echo exit | amm -s
$ docker build . (... snip ...) bash: /dev/tty: No such device or address bash: /dev/tty: No such device or address java.lang.RuntimeException: Nonzero exit value: 1 scala.sys.package$.error(package.scala:27) scala.sys.process.ProcessBuilderImpl$AbstractBuilder.slurp(ProcessBuilderImpl.scala:134) scala.sys.process.ProcessBuilderImpl$AbstractBuilder.$bang$bang(ProcessBuilderImpl.scala:104) ammonite.terminal.TTY$.stty(Utils.scala:118) ammonite.terminal.TTY$.init(Utils.scala:97) ammonite.terminal.Terminal$.x$1$lzycompute$1(Terminal.scala:41) ammonite.terminal.Terminal$.x$1$1(Terminal.scala:41) (... snip ...) ビルドが終わらない...
いろいろ悩んで、ぐぐって、試行錯誤したところ、script -c を使うことで回避することができた。これが今年の今まで一番のハック。╭( ・ㅂ・)و ̑̑ グッ !
$ man script (... snip ...) -c, --command command Run the command rather than an interactive shell. This makes it easy for a script to capture the output of a program that behaves differently when its stdout is not a tty. (... snip ...)
Dockerfile
RUN export TERM=vt100 && script -qfc 'echo exit | amm -s' && rm typescript
https://github.com/kyagi/rod/blob/master/Dockerfile#L63
$ docker build . (... snip ...) Successfully built 38b3611dc9b5