如何在 Dockerfile 编写多行命令,同时保留新行?

我想在 Dockerfile 中编写下面的 RUN 命令。

RUN echo "[repo] \
name            = YUM Repository \
baseurl         = https://example.com/packages/ \
enabled         = 1 \
gpgcheck        = 0" > /etc/yum.repos.d/Repo.repoxyz

我知道每行末尾的 \会转义新行。但是,有没有可能我可以写多行保留新的行?

113945 次浏览

您可以在 $'...'中使用所谓的“ ANSI-C 引用”。它最初是一个 < strong > ksh93 特性,但是它现在在 Bash,zsh,mksh,FreeBSD sh忙碌盒的灰烬中都可用(但是只有在使用 ENABLE _ ASH _ BASH _ COMPAT 编译它时才可用)。

作为 RUN 默认使用 /bin/sh作为 shell,您需要首先使用 SHELL 指令切换到类似 bash 的命令。

$'开始命令,以 '结束命令,并对换行符使用 \n\,如下所示:

SHELL ["/bin/bash", "-c"]


RUN echo $'[repo] \n\
name            = YUM Repository \n\
baseurl         = https://example.com/packages/ \n\
enabled         = 1 \n\
gpgcheck        = 0' > /etc/yum.repos.d/Repo.repoxyz

使用 printf允许单个 RUN 命令输出多行文本,使用 \n插入换行符。

执行:

RUN printf 'example\ntext\nhere' >> example.txt

附录:

example
text
here

到文件 example.txt

你可使用:

RUN echo -e "\
[repo] \n\
name            = YUM Repository \n\
baseurl         = https://example.com/packages/ \n\
enabled         = 1 \n\
gpgcheck        = 0\
" > /etc/yum.repos.d/Repo.repoxyz

这样,您将有一个快速的方法来检查文件内容是什么。您只需要知道,您需要以 \结束每一行,并在需要时插入 \n

也许这对你有帮助(https://github.com/jen-soft/pydocker)

[ Dockerfile.py ]

from pydocker import DockerFile  # sudo pip install -U pydocker


d = DockerFile(base_img='debian:8.2', name='jen-soft/custom-debian:8.2')


d.RUN_bash_script('/opt/set_repo.sh', r'''
cat >/etc/apt/sources.list <<EOL
deb     http://security.debian.org/ jessie/updates main
deb-src http://security.debian.org/ jessie/updates main
EOL
apt-get clean && apt-get update
''')


d.EXPOSE = 80
d.WORKDIR = '/opt'
d.CMD = ["python", "--version"]


# d.generate_files()
d.build_img()


# sudo wget -qO- https://get.docker.com/ | sh


python Dockerfile.py
docker images

我最终使用了上面列出的示例的组合,因为新的代码行 \n不能与 echo一起工作。

RUN printf 'example \n\
text \n\
here' >> example.txt

正如预期的那样,它产生了以下结果:

example
text
here

您可以多次执行 RUN 来完成您的文件:

RUN echo "[repo]" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "name            = YUM Repository" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "baseurl         = https://example.com/packages/" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "enabled         = 1" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "gpgcheck        = 0" >> /etc/yum.repos.d/Repo.repoxyz

这可能不是最佳解决方案,因为它为每个 RUN 命令创建了一个新层。尽管如此,每个层的大小将与您所做的更改一样大,在这种情况下,它的顺序是字节(第一个 RUN 层应该是7字节)。

这个解决方案的好处是可以使用所有的 shell。

从 Docker 18.09和 Dockerfile 语法1.4开始, Dockerfiles 本地支持这里的 docs (即您在这里寻找的东西) !

  1. 启用 BuildKit ,例如通过设置 DOCKER_BUILDKIT=1
  2. 将这一行添加到 Dockerfile 的顶部:
    # syntax=docker/dockerfile:1.3-labs
    
  3. 像这样重写你的异端邪说:
    COPY <<EOF /etc/yum.repos.d/Repo.repoxyz
    [repo]
    name            = YUM Repository
    baseurl         = https://example.com/packages/
    enabled         = 1
    gpgcheck        = 0
    EOF
    

您还可以使用它在单个 RUN块中运行多个 bash 命令,等等。