在 Dockerfile 中写入多行文件

Write multilines file in a Dockerfile

我想将文件写入 Dockerfile。 我不想导入文件。

我想要最简单的解决方案,比如不起作用的解决方案。 我想避免每次都重复多次回显文件名...

感谢帮助!

# This one is not working
RUN echo "[supervisord] \
    nodaemon=true \
    [program:ssh] \
    command=service ssh start \
    autorestart=true \
    [program:nginx] \
    command=service nginx start \
    autorestart=true" >> /etc/supervisor/conf.d/supervisord.conf 

# This one is working
# RUN echo '[supervisord]' >> /etc/supervisor/conf.d/supervisord.conf \
#     && echo 'nodaemon=true' >> /etc/supervisor/conf.d/supervisord.conf \
#     && echo '[program:ssh]' >> /etc/supervisor/conf.d/supervisord.conf \
#     && echo 'command=service ssh start' >> /etc/supervisor/conf.d/supervisord.conf \
#     && echo 'autorestart=true' >> /etc/supervisor/conf.d/supervisord.conf \
#     && echo '[program:nginx]' >> /etc/supervisor/conf.d/supervisord.conf \
#     && echo 'command=service nginx start' >> /etc/supervisor/conf.d/supervisord.conf \
#     && echo 'autorestart=true' >> /etc/supervisor/conf.d/supervisord.conf 

不工作

RUN echo $'[supervisord]\n\
    nodaemon=true\n\
    [program:ssh]\n\
    command=service ssh start\n\
    autorestart=true\n\
    [program:nginx]\n\
    command=service nginx start\n\
    autorestart=true' > /etc/supervisor/conf.d/supervisord.conf 

这是上面Dockerfile使用的镜像:

FROM debian:latest

# Run install with..
USER root


LABEL first_build="2021-01-28"


# Timezone Paris
ENV TZ Europe/Paris
RUN cp /usr/share/zoneinfo/Europe/Paris /etc/localtime

# Motd Dock'Ager
ADD var/motd.tar.gz /etc/update-motd.d/
COPY var/sources.list /etc/apt/sources.list

# SSH & Timezone & Munin
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections \
    && apt-get update \
    && apt-get upgrade -y && apt-get install -y \
        openssh-server \
        sudo \
        nano \
        zip \
        unzip \
        tar \
        nginx \
        munin \
        munin-node \
        munin-plugins-extra \
        figlet \
        ruby-full \
        curl \
        wget \
    && useradd -rm -d /home/test -s /bin/bash -g root -G sudo -u 1000 test \
    && echo 'test:test' | chpasswd \
    && echo 'root:root' | chpasswd \
    && cd /tmp \
    && wget https://github.com/busyloop/lolcat/archive/master.zip \
    && unzip master.zip \
    && cd lolcat-master/bin \
    && gem install lolcat \
    && sed -i '/pam_motd.so noupdate/s/^/#/g' /etc/pam.d/sshd \
    && chmod +x /etc/update-motd.d/* \
    && apt-get clean \
    && rm -rf /var/log/* \
    && rm -rf /var/lib/apt/lists/*

COPY var/sshd_config /etc/ssh/sshd_config

事实上,问题与 Docker 无关,而与您使用 echo 命令的方式有关。
如果您使用双引号,空行将被删除。要保留空行,您需要使用简单的引号(并删除行尾的 \)。

你可以在你的终端上试试:

# with double quote
$ echo "hello \
> World"

# result
hello World

# With simple quote
$ echo 'Hello
> World'

#result
Hello
World

备选方案

以“正常方式”定义文件会更好。所以它更容易阅读。
您可以将文件传递到您的容器中 - 请参见下面的示例。

supervisord.conf

[supervisord]
nodaemon=true

[program:ssh]
command=service ssh start
autorestart=true

[program:nginx]
command=service nginx start
autorestart=true

Docker 文件

# ...

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# ...

问题

如果您想将文件保存在 docker 文件中,那么您可以这样做:

Docker 文件

# ...

RUN echo $'test\n\
    abc\n\
    def' > test.txt
# ...

最后一个反斜杠是 docker。前导美元符号导致 bash 解释 \n\t,参见 How does the leading dollar sign affect single quotes in Bash?

编辑(针对 debian-image)

Debian 反应完全不同,所以你必须写:

# ...

RUN echo '[supervisord]\n\
nodaemon=true\n\
[program:ssh]\n\
command=service ssh start\n\
autorestart=true\n\
[program:nginx]\n\
command=service nginx start\n\
autorestart=true' > /etc/supervisor/conf.d/supervisord.conf 

# ...

非常难看,强烈推荐封装后的文件