'How to write commands with multiple lines in Dockerfile while preserving the new lines?
I want to write the following RUN command in the Dockerfile. But, docker is not preserving the new lines.
RUN echo "[repo] \
name = YUM Repository \
baseurl = https://example.com/packages/ \
enabled = 1 \
gpgcheck = 0" > /etc/yum.repos.d/Repo.repoxyz
I know that \ at the end of each line escapes the new line. But, is there any way that I can write multiple lines preserving the new line?
Solution 1:[1]
You can use what is called "ANSI-C quoting" with $'...'. It was originally a ksh93 feature but it is now available in bash, zsh, mksh, FreeBSD sh and in busybox's ash (but only when it is compiled with ENABLE_ASH_BASH_COMPAT).
As RUN uses /bin/sh as shell by default you are required to switch to something like bash first by using the SHELL instruction.
Start your command with $', end it with ' and use \n\ for newlines, like this:
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
Solution 2:[2]
I used printf. Writing all the text in one line using \n.
Executing:
RUN printf 'example \ntext \nhere' >> example.txt
inserts:
example
text
here
in example.txt
Solution 3:[3]
You can use:
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
This way you will have a quick way to check what the file contents are. You just need to be aware that you need to end every line with \ and insert the \n when needed.
Solution 4:[4]
I ended up using a combination of the examples listed above since the new line \n did not work with echo.
RUN printf 'example \n\
text \n\
here' >> example.txt
It produces the following, as expected:
example
text
here
Solution 5:[5]
May be it's help you ( 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
Solution 6:[6]
As of Docker 18.09 and Dockerfile syntax 1.4, Dockerfiles support heredocs (ie what you're looking for here) natively!
- Enable BuildKit, eg by setting
DOCKER_BUILDKIT=1. - Add this line to the top of your Dockerfile:
# syntax=docker/dockerfile:1.3-labs - Rewrite your heredoc like so:
COPY <<EOF /etc/yum.repos.d/Repo.repoxyz [repo] name = YUM Repository baseurl = https://example.com/packages/ enabled = 1 gpgcheck = 0 EOF
You can also use this to run multiple bash commands in a single RUN block, etc. More details: Docker blog post, Dockerfile syntax docs.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Forage |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | |
| Solution 5 | jen-soft |
| Solution 6 |
