0

I would like to write a file into a Dockerfile. I don't want to import the file.

I would like the simplest solution, something like the solution that is not working. I would like to avoid to repeat many echo with each time the name of the file...

Thanks for help !

# 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 

Not working

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 

This is the image used by the Dockerfile above :

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
Kévin
  • 497
  • 10
  • 37

2 Answers2

1

Alternative solution

It would be better, when you define the file in "a normal way". So it is a lot easier to read.
You can pass the file into your container - see for example below.

supervisord.conf

[supervisord]
nodaemon=true

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

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

Dockerfile

# ...

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

# ...

Question

If you want to keep the file in dockerfile, then you could do something like this:

Dockerfile

# ...

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

The last backslash is for docker. The leading dollar-sign causes bash to interpret \n or \t, see How does the leading dollar sign affect single quotes in Bash?

Edit (for debian-image)

Debian react quite different, so you have to wrote:

# ...

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 

# ...

It is very ugly and I strongly recommend a encapsulated file.

akop
  • 5,981
  • 6
  • 24
  • 51
  • I want to keep the file in dockerfile, but you solution is not working on my side. I have edited my post, you can found what i tried – Kévin Feb 04 '21 at 10:25
  • I copied your code and changed the path (so I used it in busybox-image). Did you have `bash` installed in your image? Or why it don't work? – akop Feb 04 '21 at 10:28
  • The dockerfile is created without problem but services are not started when i do docker run Services are started properly with the example i said was working but not with yours :( – Kévin Feb 04 '21 at 10:30
  • Which image are you using? It would be nice if you provide a [minmal-reproducible-example](https://stackoverflow.com/help/minimal-reproducible-example). – akop Feb 04 '21 at 10:34
  • I updated the post, custom image based on debian:latest – Kévin Feb 04 '21 at 10:36
  • I found the problem and edited my answer. It should work, but please use a file. :) – akop Feb 04 '21 at 10:46
  • We have a specific usage that cannot let us use a file in the future. it's why i prefer to migrate everything into the dockerfile now. Will try your purpose – Kévin Feb 04 '21 at 10:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/228253/discussion-between-akop-and-kevin). – akop Feb 04 '21 at 10:48
0

In fact, the problem has nothing to do with Docker but with the way you're using the echo command.
If you use double-quote, the blank lines will be removed. To keep blank lines, you need to use simple quote (and remove the \ at the end of the lines).

You can try on your terminal :

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

# result
hello World

# With simple quote
$ echo 'Hello
> World'

#result
Hello
World

Marc ABOUCHACRA
  • 3,155
  • 12
  • 19
  • This is not allowed without the \ https://prnt.sc/y96dcl With \ at the end, the dockerfile run but container does not start services – Kévin Feb 04 '21 at 09:58