Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker: RUN touch doesn't create file

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
like image 348
Philippe Hebert Avatar asked Jan 01 '17 01:01

Philippe Hebert


People also ask

Does docker build run entrypoint?

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.

What does touch Dockerfile do?

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.


2 Answers

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.

like image 173
Dan Lowe Avatar answered Oct 21 '22 16:10

Dan Lowe


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

like image 26
Socratees Samipillai Avatar answered Oct 21 '22 15:10

Socratees Samipillai