在 Docker 下安装时是否可以回答对话框问题?

在使用 apt-get 安装一些软件包时,是否有可能以某种方式回答以对话框的形式出现的问题?

例如,我试图用以下方法设置一个包含 mail-stack-delivery包的容器:

FROM ubuntu


RUN apt-get install -y mail-stack-delivery

然而,dockerfile 在构建时会产生几十个错误,这些错误类似于:

debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7, <> line 11.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:

根据我的理解,我只是不能对对话框做出反应,但是有没有什么方法可以让我提前传递一个参数来回答每个问题呢?我知道它只是更改了一些配置,所以我可以在事后进行安装,但是最好让安装脚本进行安装,这样一切都可以正确设置。

45805 次浏览

As usual, a little more searching found the answer.

The answer is debconf-set-selections. Manpage: http://manpages.ubuntu.com/manpages/oneiric/en/man1/debconf-set-selections.1.html

To find the options that can be set use debconf-get-selections on a system that already has the package installed. You'll need to install debconf-utils for the second command.

You should set DEBIAN_FRONTEND=noninteractive as an envvar. In most cases this will at least make it so the installation doesn't error out.

Also as @Azdle mentioned, using debconf-set-selections will let you set specific items.

See the discussion here: https://github.com/docker/docker/issues/4032. In short, setting ENV DEBIAN_FRONTEND noninteractive is not recommended as it persists in the final image, even when running something like docker run -i -t ... bash. Therefore it is recommended either to omit DEBIAN_FRONTEND and live with the warning, or specify it explicitly for each command e.g. RUN DEBIAN_FRONTEND=noninteractive apt-get install -y -q package.

Fortunately, the new ARG directive sets variables that only live during the build so a more elegant solution is now possible that's specified in the DockerFile yet does not persist in the final image: ARG DEBIAN_FRONTEND=noninteractive.

This is working solution:

ARG DEBIAN_FRONTEND=noninteractive

ENV DEBIAN_FRONTEND noninteractive didn't work for me

neither did ARG DEBIAN_FRONTEND=noninteractive

RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections did

EXAMPLE With Success:

echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
sudo apt-get install -y -q <package name>

The reason why ENV DEBIAN_FRONTEND=noninteractive (or the legacy syntax ENV DEBIAN_FRONTEND noninteractive) sometimes works and sometimes does not has to do with the usage of sudo. By default sudo ignores the environment of the current user and uses a clean one. This can be controlled via the sudo --preserve-env flag. Obviously adding this to every sudo invocation is cumbersome, but it is easy to make the entire system for every user non-interactive by adding the environment variable to the /etc/environment file of the operating system.

RUN set -a \
&& eval "$(sudo tee --append /etc/environment <<<'DEBIAN_FRONTEND=noninteractive')" \
&& set +a \
&& sudo apt-get update \
&& sudo apt-get install mail-stack-delivery

Quickly dissecting the important snippet in isolation:

# export every variable that follows
set -a


# appends the given string to the `/etc/environment` file as root
# tee prints its input to standard out
# eval interprets the output of tee
eval "$(sudo tee --append /etc/environment <<<'DEBIAN_FRONTEND=noninteractive')"


# stop exporting everything
set +a

It was mentioned before the DEBIAN_FRONTEND=noninteractive should not be set in such a global fashion. This depends on what the intend of your image is. If it is meant for automation and not for humans then it is totally fine to set it globally.