如何使用“&”创建Dockerfile到RUN命令?

时间:2018-09-13 23:53:04

标签: docker dockerfile

我在Dockerfile中有以下命令。每次创建新图像时都会执行该操作。问题是该命令失败,因为我在&中有一个Xvfb :99 &。有什么好的解决方法?添加引号没有帮助。

RUN set -ex \
&& apt-get update -yqq \
&& apt-get upgrade -yqq \
&& apt-get install -yqq --no-install-recommends \
    python3-pip \
    python3-requests \
    software-properties-common \
    python-software-properties \
    xvfb \
&& Xvfb :99 & \
&& export DISPLAY=:99 

这是确切的错误:/bin/sh: 1: Syntax error: "&&" unexpected

3 个答案:

答案 0 :(得分:6)

当尝试通过后台进程运行多个命令时,必须使用&将命令和()分组。
因此run语句应如下所示。

RUN set -ex \
&& apt-get update -yqq \
&& apt-get upgrade -yqq \
&& apt-get install -yqq --no-install-recommends \
    python3-pip \
    python3-requests \
    software-properties-common \
    python-software-properties \
    xvfb \
&& ( Xvfb :99 & ) \
&& export DISPLAY=:99

参考:Run multiple commands as bg in Linux

答案 1 :(得分:1)

您看到的错误是因为您在后台运行命令,并要求Shell根据后台命令的退出状态有条件地运行另一个命令。 Shell无法通过逻辑方式做到这一点。您可以在后台处理后删除&&,但是问题更大。

在Dockerfile中执行RUN命令的结果是在pid 1退出后文件系统发生了变化。在后台使用命令时,pid 1(您的shell)将立即退出(当它用完了要运行的命令时)。随着容器的终止,后台进程将被终止。当以pid 1运行的shell退出时,对shell状态的更改(如导出的变量)将丢失。

出于您的目的,您可能希望将后台进程移动到容器入口点的一部分。例如

RUN apt-get update -yqq \
 && apt-get install -yqq --no-install-recommends \
      python3-pip \
      python3-requests \
      software-properties-common \
      python-software-properties \
      xvfb \
 && rm -rf /var/lib/apt/lists/*
ENTRPOINT Xvfb :99 & \
    export DISPLAY=:99 \
 && some-command-that-needs-a-ui

请注意,我已经删除了apt-get upgrade,如果您需要在映像中升级软件包,那么我会使用较新的基本映像来完成。我通常将入口点设置为shell脚本,而不是像这样的长命令,您可能会发现将上面的内容移动到一个具有以下内容的entrypoint.sh会更容易:

#!/bin/sh
set -ex
Xvfb :99 &
export DISPLAY=:99
some-command-that-needs-a-ui

请注意,在这两个示例中,您都需要指定some-command-that-needs-a-ui。我不能说那是什么,因为您没有在问题中包括它。

答案 2 :(得分:-2)

我会尝试在其前面加上反斜杠“ \”