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 ..." bashAnd 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 pythonBut 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?
4 Answers
I'd like to question your use-case. Why do you need to redirect stderr/stdout to a log file in the container? Merged stderr and stdout are available outside the container using "docker logs", and they can be redirected to a file (outside of the container.) More details can be found here
4Here's some info on a related use case: You want to redirect the output inside the container, which is running on Docker Cloud.
In my case, I'm executing a long-running data analysis script (Java) on Docker Cloud. Each container is supposed to write its own results file. I'm using the java:8-jre image and overwrite the 'Run command' with the following line:
bash -c "java -jar /code/analyzer.jar > /data/results-$RANDOM.txt"By using bash's $RANDOM variable, I can scale up the number of containers in Docker Cloud as much as I want, while still collecting the results individually.
You are looking for tee
LOGFILE="logthis.txt";
IMG_alpine="alpine:3.5";
docker run --rm \
--name alpine-hello \
--hostname alpine-hello \
"$IMG_alpine" \
uname -a | tee -a $LOGFILE
cat logthis.txt
Linux alpine-hello 4.8.14-docker-2 #1 SMP Tue Jan 10 15:35:02 UTC 2017 x86_64 Linux To use docker run in a shell pipeline or under shell redirection, making run accept stdin and output to stdout and stderr appropriately, use this incantation:
docker run -i --log-driver=none -a stdin -a stdout -a stderr ...e.g. to run the alpine image and execute the UNIX command cat in the contained environment:
echo "This was piped into docker" | docker run -i --log-driver=none -a stdin -a stdout -a stderr \ alpine cat - | xargs echo This is coming out of docker: emits:
This is coming out of docker: This was piped into docker