I was helping out a fellow colleague yesterday who was having some troubles handling a multiline echo statement within his Dockerfile. There are multiple ways in which you can create multiline Dockerfiles, the web is full of examples from using multiple echo statements (pretty ugly) to using heredocs which is easier to read and manage. The challenge was that he also wanted to substitute some variables into his multiline statement which apparently there were no examples online, at least neither of us could find.
Taking a closer look, I found that we can just leverage Bash's ANSI-C Quoting syntax $'string' to do what we want, which was actually something new to me as well. You can then pass in the variable like you normally would between the strings and that would give you the readability of heredocs and still be able to use Docker variables. I am sure there are other methods with more extensive escapes with single-ticks, but I also prefer a solution that is easy to read and use in case others need to manage it.
Here is a quick sample Dockerfile which demonstrates how this works:
FROM photon:1.0 ARG BASEURL="https://vmware.bintray.com/powershell" RUN echo $'[powershell]\n\ name=VMware Photon Linux 1.0(x86_64)\n\ baseurl='$BASEURL$'\n\ gpgcheck=0\n\ enabled=1\n\ skip_if_unavailable=True\n '\ >> /etc/yum.repos.d/powershell.repo CMD ["/bin/bash"]
Basically the echo statement has $'SOME-STRING'$VARIABLE$'SOME-STRING'
If we build and run this Docker image, we can see that we have properly substituted the BASEURL variable into our file as seen in the screenshot below.
docker build -t sample .
docker run --rm -it sample cat /etc/yum.repos.d/powershell.repo
I personally prefer to keep such logic within a separate script which the Dockerfile can reference, but I was also sympathetic to that fact that my colleague wanted to keep things simple and just have everything within the Dockerfile. I figure I would share this in case other comes across this problem as well as benefiting myself as I will probably forget in a months time 🙂