I want to do some simple logging for my server which is a small Flask app running in a Docker container.
Here is the Dockerfile
# Dockerfile FROM dreen/flask MAINTAINER dreen WORKDIR /srv # Get source RUN mkdir -p /srv COPY perfektimprezy.tar.gz /srv/perfektimprezy.tar.gz RUN tar x -f perfektimprezy.tar.gz RUN rm perfektimprezy.tar.gz # Run server EXPOSE 80 CMD ["python", "index.py", "1>server.log", "2>server.log"]
As you can see on the last line I redirect stderr and stdout to a file. Now I run this container and shell into it
docker run -d -p 80:80 perfektimprezy docker exec -it "... id of container ..." bash
And observe the following things:
The server is running and the website working
There is no /srv/server.log
ps aux | grep python
yields:
root 1 1.6 3.2 54172 16240 ? Ss 13:43 0:00 python index.py 1>server.log 2>server.log root 12 1.9 3.3 130388 16740 ? Sl 13:43 0:00 /usr/bin/python index.py 1>server.log 2>server.log root 32 0.0 0.0 8860 388 ? R+ 13:43 0:00 grep --color=auto python
But there are no logs... HOWEVER, if I docker attach
to the container I can see the app generating output in the console.
How do I properly redirect stdout/err to a file when using Docker?
Redirect Docker Logs to File Since Docker merges stdout and stderr for us, we can treat the log output like any other shell stream. To redirect the current logs to a file, use a redirection operator. To send the current logs and then any updates that follow, use –follow with the redirection operator.
The output you receive will be similar to the one you see in the image above. The container will run the process and then stop. No other output will display inside the terminal session. Note: Running Docker privileged containers is also one of the most commonly used run commands.
The ENTRYPOINT instruction looks almost similar to the CMD instruction. However, the main highlighting difference between them is that it will not ignore any of the parameters that you have specified in the Docker run command (CLI parameters).
Using ENTRYPOINT or CMDBoth ENTRYPOINT and CMD are essential for building and running Dockerfiles—it simply depends on your use case. As a general rule of thumb: Opt for ENTRYPOINT instructions when building an executable Docker image using commands that always need to be executed.
When you specify a JSON list as CMD
in a Dockerfile
, it will not be executed in a shell, so the usual shell functions, like stdout and stderr redirection, won't work.
From the documentation:
The exec form is parsed as a JSON array, which means that you must use double-quotes (
"
) around words not single-quotes ('
).Unlike the shell form, the exec form does not invoke a command shell. This means that normal shell processing does not happen. For example,
CMD [ "echo", "$HOME" ]
will not do variable substitution on$HOME
. If you want shell processing then either use the shell form or execute a shell directly, for example:CMD [ "sh", "-c", "echo", "$HOME" ]
.
What your command actually does is executing your index.py
script and passing the strings "1>server.log"
and "2>server.log"
as command-line arguments into that python script.
Use one of the following instead (both should work):
CMD "python index.py > server.log 2>&1"
CMD ["/bin/sh", "-c", "python index.py > server.log 2>&1"]
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