While trying to debug a RUN statements in my Dockerfile, I attempted to redirect output to a file in a bound volume (./mongo/log
).
To my surprise I was unable to create files via the RUN command, or to pipe the output of another command to a file using the redirection/appending (>
,>>
) operators. I was however able to perform the said task by logging in the running container via docker exec -ti mycontainer /bin/sh
and issuing the command from there.
Why is this behaviour happening? How can I touch file in the Dockerfile / redirect output to a file or to the console from which the Dockerfile is run?
Here is my Dockerfile:
FROM mongo:3.4
#Installing NodeJS
RUN apt-get update && \
apt-get install -y curl && \
curl -sL https://deb.nodesource.com/setup_6.x | bash - && \
apt-get install -y nodejs
#Setting Up Mongo
WORKDIR /var/www/smq
COPY ./mongo-setup.js mongo-setup.js
##for testing
RUN touch /var/log/node.log && /
node --help 2>&1 > /var/log/node.log
##this was the command to debug
#RUN node mongo-setup.js > /var/log/mongo-setup.log 2> /var/log/mongo-setup.error.log
Here an excerpt from my docker-compose.yml:
mongodb:
build:
context: ./
dockerfile: ./mongodb-dockerfile
container_name: smqmongodb
volumes:
- /var/lib/mongodb/data
- ./mongo/log/:/var/log/
- ../.config:/var/www/.config
ENTRYPOINT instructions are used to build Dockerfiles meant to run specific commands. The above Dockerfile uses an ENTRYPOINT instruction that echoes Hello, Darwin when the container is running.
The touch command in Docker creates the Dockerfile. Step 2: Add comments in case they are needed. Comments can be added using the # sign. Step 3: The very first line has to begin at the keyword FROM as it lets Docker know which base image the current image should be based on.
You are doing this during your build:
RUN touch /var/log/node.log && /
node --help 2>&1 > /var/log/node.log
The file /var/log/node.log
is created and fixed immutably into the resulting image.
Then you run the container with this volume mount:
volumes:
- ./mongo/log/:/var/log/
Whatever is in ./mongo/log/
is mounted as /var/log
in the container, which hides whatever was there before (from the image). This is the thing that's making it look like your touch
didn't work (even though it probably worked fine).
You're thinking about this backward - your volume mount doesn't expose the container's version of /var/log
externally - it replaces whatever was there.
Nothing you do in Dockerfile (build) will ever show up in an external mount.
Instead of RUN node mongo-setup.js > /var/log/mongo-setup.log 2> /var/log/mongo-setup.error.log
, within the container, what if you just say `RUN node mongo-setup.js'?
Docker recommends using docker logs
. Like so:
docker logs container-name
To accomplish what you're after (see the mongo setup logs?), you can split the stdout & stderr of the container by piping the separate streams: and send them to files:
me@host~$ docker logs foo > stdout.log 2>stderr.log
me@host~$ cat stdout.log
me@host~$ cat stderr.log
Also, refer to the docker logs documentation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With