miltone
miltone

Reputation: 4721

launch a CAT command unix into Dockerfile

I would like to launch this vagrant command cat(run perfectly!) to provisionning my container with a Dockerfile :

# Configure Virtualenvwrapper.
RUN cat <<EOF >> /home/docker/.bashrc
# Virtualenvwrapper configuration.
export WORKON_HOME=\$HOME/.virtualenvs
export PROJECT_HOME=\$HOME/Devel
source /usr/local/bin/virtualenvwrapper.sh
EOF

But I have this error return when I launch my building image docker :

 ---> 40f9ed8e187d
Removing intermediate container 85f6c8536520
Step 69 : RUN cat <<EOF >> /home/docker/.bashrc
 ---> Running in dcbb3d441f79
 ---> 78acd9c2e5d5
Removing intermediate container dcbb3d441f79
Step 70 : EXPORT
Unknown instruction: EXPORT

What is the trick for run a cat command unix into image with Dockerfile ?

Upvotes: 30

Views: 81973

Answers (7)

David Riccitelli
David Riccitelli

Reputation: 7812

This is an example straight from Docker documentation:

# syntax=docker/dockerfile:1
FROM alpine
ARG FOO=bar
COPY <<-EOT /app/foo
    hello ${FOO}
EOT

https://docs.docker.com/engine/reference/builder/#example-creating-inline-files

Upvotes: 3

bhass1
bhass1

Reputation: 418

Update [08/03/2022]: As of dockerfile/dockerfile:1.4.0, the Here-Document support has been promoted from labs channel to stable. #2589.

You need to use Docker Buildkit by setting DOCKER_BUILDKIT=1 in your environment, set the syntax parser directive to use dockerfile/dockerfile:1.4.0, and swap the position of the here delimeter with cat. The rest is used like normal.

Dockerfile Example:

# syntax = docker/dockerfile:1.4.0

...

RUN <<EOF cat >> /home/docker/.bashrc
# Virtualenvwrapper configuration.
export WORKON_HOME=\$HOME/.virtualenvs
export PROJECT_HOME=\$HOME/Devel
source /usr/local/bin/virtualenvwrapper.sh
EOF

Prior to dockerfile/dockerfile:1.4.0, Here-Document syntax was supported in the labs channel dockerfile/dockerfile:1.3.0-labs release.

Simply replace version used in the syntax parser directive from the above example.


Prior to Docker BuildKit labs channel dockerfile/dockerfile:1.3.0-labs release, instead of using cat, try using echo instead!

Turn this shell cat example...

#!/usr/bin/env sh
cat <<EOF > /tmp/example.txt
line 1
line 2
line 3
EOF

... into this Dockerfile echo example!

RUN echo -e '\
line 1\n\
line 2\n\
line 3\
' > /tmp/example.txt

Note the pair of single quotes (') in the echo example.

Also note the -e flag for echo to support the escaped newlines (\n).

Caution: Unfortunately, the -e flag may or may not be required depending on the version of echo your image has installed. For example, the npm:16 image's echo does not require -e and actually will print the -e along with the single-quoted lines. On the other hand, the ubuntu:20.04 image's echo does require -e.

The same example could be written on one line as: RUN echo -e 'line 1\nline 2\nline 3' >> /tmp/example.txt, but I find the above example more readable.

To answer the OP's question, use this:

# Configure Virtualenvwrapper.
RUN echo -e '\
# Virtualenvwrapper configuration.\n\
export WORKON_HOME=\$HOME/.virtualenvs\n\
export PROJECT_HOME=\$HOME/Devel\n\
source /usr/local/bin/virtualenvwrapper.sh\
' >> /home/docker/.bashrc

Caution: The escape character can be redefined by the escape directive. If your Dockerfile has a different escape character set, you'll need to modify the examples accordingly.

Upvotes: 28

tripleee
tripleee

Reputation: 189477

If you want to avoid here-document syntax for some reason, printf is hugely more ergonomical than echo $'...' as well as portable to POSIX sh.

RUN printf '%s\n' > /home/docker/.profile \
    '# Virtualenvwrapper configuration.' \
    'export WORKON_HOME=$HOME/.virtualenvs' \
    'export PROJECT_HOME=$HOME/Devel' \
    'source /usr/local/bin/virtualenvwrapper.sh'

The single quotes prevent shell interpolation of variables; if you want to expand a variable, use double quotes (though then you'll need to backslash-escape any literal dollar sign, backtick, or backslash).

Upvotes: 0

Paul92
Paul92

Reputation: 137

You can also use below command in place of here document << inside a Dockerfile

RUN echo $'[kubernetes] \n\
name=Kubernetes \n\
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 \n\
enabled=1 \n\
gpgcheck=1 \n\
repo_gpgcheck=1 \n\
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg \n '\
> /etc/yum.repos.d/kubernetes.repo

Upvotes: 3

w1100n
w1100n

Reputation: 1668

Based on this comment to an issue posted on Github, this works:

RUN echo 'All of your\n\
multiline that you ever wanted\n\
into a dockerfile\n'\
>> /etc/example.conf

Upvotes: 33

Manuel Schmidt
Manuel Schmidt

Reputation: 2417

You can write it this way:

RUN echo "# Virtualenvwrapper configuration." >> /home/docker/.bashrc && \
    echo "export WORKON_HOME=\$HOME/.virtualenvs" >> /home/docker/.bashrc && \
    echo "export PROJECT_HOME=\$HOME/Devel" >> /home/docker/.bashrc && \
    echo "source /usr/local/bin/virtualenvwrapper.sh" >> /home/docker/.bashrc

Upvotes: 5

user2105103
user2105103

Reputation: 13095

Dockerfiles are not batch files. Every line/command is isolated and committed.

Just put the contents into a file and ADD/COPY it. If you need to customize it, SED it. Or if you really, really, really want to CAT into a file -- put it in a real batch file, then ADD/COPY it, then RUN it.

Also, less lines = less layers. 70 Steps? Yowzers.

Upvotes: 6

Related Questions