Redirigir la salida de comandos en docker


Quiero hacer un registro simple para mi servidor, que es una pequeña aplicación Flask que se ejecuta en un contenedor Docker.

Aquí está el 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"]

Como se puede ver en la última línea redirijo stderr y stdout a un archivo. Ahora corro este contenedor y shell en él

docker run -d -p 80:80 perfektimprezy
docker exec -it "... id of container ..." bash

Y observa las siguientes cosas:

El servidor se está ejecutando y el sitio web funciona

No hay /srv/server.log

ps aux | grep python rendimientos:

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

Pero no hay registros... SIN EMBARGO, si I docker attach al contenedor puedo ver la aplicación generando salida en la consola.

¿Cómo puedo redirigir correctamente stdout/err a un archivo cuando uso Docker?

Author: Dreen, 2016-01-06

3 answers

Cuando se especifica una lista JSON como CMD en un Dockerfile, no se ejecutará en un shell, por lo que las funciones habituales del shell, como la redirección stdout y stderr, no funcionarán.

De la documentación :

La forma exec se analiza como una matriz JSON, lo que significa que debe usar comillas dobles (") alrededor de palabras, no comillas simples (').

A diferencia del shell form, el exec form no invoca un shell de comandos. Esto significa que la cáscara normal el procesamiento no ocurre. Por ejemplo, CMD [ "echo", "$HOME" ] no hará sustitución de variables en $HOME. Si quieres procesar el shell entonces usa el formulario shell o ejecuta un shell directamente, por ejemplo: CMD [ "sh", "-c", "echo", "$HOME" ].

Lo que su comando realmente hace es ejecutar su script index.py y pasar las cadenas "1>server.log" y "2>server.log" como argumentos de línea de comandos en ese script python.

Use uno de los siguientes en su lugar (ambos deben trabajo):

  1. CMD "python index.py > server.log 2>&1"
  2. CMD ["/bin/sh", "-c", "python index.py > server.log 2>&1"]
 32
Author: helmbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-06 12:38:26

Solo un complemento, cuando se utiliza docker-compose , también podría intentar:

command: bash -c "script_or_command > /path/to/log/command.log 2>&1"

 5
Author: Jing Li,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-18 10:14:19

Para usar docker run en una canalización de shell o bajo redirección de shell, haciendo que run acepte stdin y la salida a stdout y stderr apropiadamente, use este encantamiento:

docker run -i --log-driver=none -a stdin -a stdout -a stderr ...

Por ejemplo, para ejecutar la imagen alpine y ejecutar el comando UNIX cat en el entorno contenido:

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: 

Emite:

This is coming out of docker: This was piped into docker
 1
Author: Daniel S. Sterling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-03 18:35:45