How to run command during Docker build which requires a tty?

I have some script I need to run during a Docker build which requires a tty (which Docker does not provide during a build). Under the hood the script uses the read command. With a tty, I can do things like (echo yes; echo no) |

Without it I get strange errors I don’t completely understand. So is there any way to use this script during the build (given that its not mine to modify?)

  • How does docker0 bridge work internally inside the host?
  • Ping Docker Container from another machine in the network
  • How can I install lxml in docker
  • Dockerized MongoDB on Heroku?
  • Upgrading to docker 1.9 on Centos 7.1
  • how to setup continuos deployment from docker-hub to AWS ECS?
  • EDIT: Here’s a more definite example of the error:

    FROM ubuntu:14.04
    RUN echo yes | read

    which fails with:

    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

  • Tsung: client connection using port
  • spring cloud hystrix turbine amqp connection refused with docker
  • How to install jekyll to a Docker image?
  • Docker. How to resume downloading image when interrupted?
  • Cannot access port on host mapped to docker container port
  • How to change Azure Docker VM's docker certificate?
  • 3 Solutions collect form web for “How to run command during Docker build which requires a tty?”

    You don’t need a tty for feeding your data to your script . just doing something like (echo yes; echo no) | as you suggested will do. also please make sure you copy your file first before trying to execute it . something like COPY

    RUN <command> in Dockerfile reference:

    shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows

    let’s see what exactly /bin/sh is in ubuntu: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 is a symbolic link of dash, see read function in 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 function in dash:

    At least one variable must be specified.

    let’s see read function in 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.

    So I guess your script is start with #!/bin/bash or something else but not /bin/sh.

    Also, you can change your Dockerfile like below:

    FROM ubuntu:14.04
    RUN echo yes | read ENV_NAME


    Most likely you don’t need a tty. As the comment on the question shows, even the example provided is a situation where the read command was not properly called. A tty would turn the build into an interactive terminal process, which doesn’t translate well to automated builds that may be run from tools without terminals.

    If you need a tty, then there’s the C library call to openpty that you would use when forking a process that includes a pseudo tty. You may be able to solve your problem with a tool like expect, but it’s been so long that I don’t remember if it creates a ptty or not. Alternatively, if your application can’t be built automatically, you can manually perform the steps in a running container, and then docker commit the resulting container to make an image.

    I’d recommend against any of those and to work out the procedure to build your application and install it in a non-interactive fashion. Depending on the application, it may be easier to modify the installer itself.

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.