如何在Docker构建期间运行命令,这需要一个tty?

时间:2015-10-14 23:39:41

标签: linux docker tty dockerfile

我需要在Docker构建期间运行一些需要tty的脚本(Docker在构建期间不提供)。在脚本下,脚本使用read命令。 使用 tty,我可以执行(echo yes; echo no) | myscript.sh之类的内容。

没有它我会得到一些我不完全理解的奇怪错误。那么有没有办法在构建期间使用这个脚本(假设它不是我的修改?)

编辑:这是错误的更明确的例子:

FROM ubuntu:14.04
RUN echo yes | read

失败了:

Step 0 : FROM ubuntu:14.04
 ---> 826544226fdc
Step 1 : RUN echo yes | read
 ---> Running in 4d49fd03b38b
/bin/sh: 1: read: arg count
The command '/bin/sh -c echo yes | read' returned a non-zero code: 2

3 个答案:

答案 0 :(得分:0)

您不需要tty来将数据提供给脚本。只是像你建议的那样做(echo yes; echo no) | myscript.sh之类的事情。另外,请确保在尝试执行文件之前先复制文件。像COPY myscript.sh myscript.sh

这样的东西

答案 1 :(得分:0)

RUN <command>参考中的

Dockerfile

  

shell表单,该命令在shell中运行,默认情况下是Linux上的/ bin / sh -c或Windows上的cmd / S / C

让我们看看ubuntu中的/bin/sh究竟是什么:14.04:

$ docker run -it --rm ubuntu:14.04 bash
root@7bdcaf403396:/# ls -n /bin/sh
lrwxrwxrwx 1 0 0 4 Feb 19  2014 /bin/sh -> dash

/ bin / sh是dash的符号链接,请参阅read中的dash函数:

$ man dash
...
read [-p prompt] [-r] variable [...]
            The prompt is printed if the -p option is specified and the standard input is a terminal.  Then a line
            is read from the standard input.  The trailing newline is deleted from the line and the line is split as
            described in the section on word splitting above, and the pieces are assigned to the variables in order.
            At least one variable must be specified.  If there are more pieces than variables, the remaining pieces
            (along with the characters in IFS that separated them) are assigned to the last variable.  If there are
            more variables than pieces, the remaining variables are assigned the null string.  The read builtin will
            indicate success unless EOF is encountered on input, in which case failure is returned.

            By default, unless the -r option is specified, the backslash ``\'' acts as an escape character, causing
            the following character to be treated literally.  If a backslash is followed by a newline, the backslash
            and the newline will be deleted.
...
read中的

dash功能:

  

必须至少指定一个变量。

让我们在read中看到bash函数:

$ man bash
...
read  [-ers]  [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name...]
If  no names are supplied, the line read is assigned to the variable REPLY.  The return code is zero,
              unless end-of-file is encountered, read times out (in which case the  return  code  is  greater  than
              128), or an invalid file descriptor is supplied as the argument to -u.
...

所以我猜您的脚本myscript.sh是以#!/bin/bash或其他内容开头但不是/bin/sh

此外,您可以更改Dockerfile,如下所示:

FROM ubuntu:14.04
RUN echo yes | read ENV_NAME

<强>链接:

答案 2 :(得分:-1)

很可能你不需要tty。正如对问题的评论所示,即使提供的示例也是未正确调用read命令的情况。 tty会将构建转换为交互式终端进程,这不能很好地转换为可以从没有终端的工具运行的自动构建。

如果你需要tty,那么你可以在分配包含伪tty的进程时使用openpty的C库调用。您可以使用像expect这样的工具来解决您的问题,但是它已经很久了,我不记得它是否创建了一个ptty。或者,如果您的应用程序无法自动构建,您可以在正在运行的容器中手动执行这些步骤,然后docker commit生成的容器以生成图像。

我建议不要使用其中任何一个,并制定程序来构建应用程序并以非交互方式安装它。根据应用程序的不同,修改安装程序本身可能更容易。