Je souhaite effectuer une journalisation simple pour mon serveur, qui est une petite Flask exécutée dans un conteneur Docker.
Voici le 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"]
Comme vous pouvez le voir sur la dernière ligne, je redirige stderr et stdout vers un fichier. Maintenant, je lance ce conteneur et Shell dedans
docker run -d -p 80:80 perfektimprezy
docker exec -it "... id of container ..." bash
Et observez les choses suivantes:
Le serveur est en marche et le site Web fonctionne
Il n'y a pas /srv/server.log
ps aux | grep python
donne:
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
Mais il n'y a pas de journaux ... CEPENDANT, si je docker attach
au conteneur, je peux voir l’application générer une sortie dans la console.
Comment rediriger correctement stdout/err vers un fichier lorsque Docker est utilisé?
Lorsque vous spécifiez une liste JSON sous la forme CMD
dans un Dockerfile
, elle ne sera pas exécutée dans un shell. Par conséquent, les fonctions habituelles du shell, telles que la redirection stdout et stderr, ne fonctionneront pas.
De la documentation :
Le formulaire exec est analysé comme un tableau JSON, ce qui signifie que vous devez utiliser des guillemets doubles (
"
) autour de mots autres que des guillemets simples ('
).Contrairement au formulaire Shell, le formulaire exec n'invoque pas de commande Shell. Cela signifie que le traitement Shell normal ne se produit pas. Par exemple,
CMD [ "echo", "$HOME" ]
ne fera pas de substitution de variable sur$HOME
. Si vous souhaitez un traitement Shell, utilisez le formulaire Shell ou exécutez-le directement, par exemple:CMD [ "sh", "-c", "echo", "$HOME" ]
.
Ce que fait réellement votre commande, c'est en exécutant votre index.py
script et transmission des chaînes "1>server.log"
et "2>server.log"
comme arguments de ligne de commande dans ce python script .
Utilisez plutôt l'un des éléments suivants (les deux devraient fonctionner):
CMD "python index.py > server.log 2>&1"
CMD ["/bin/sh", "-c", "python index.py > server.log 2>&1"]
Juste un complément, en utilisant docker-compose, vous pouvez également essayer:
command: bash -c "script_or_command > /path/to/log/command.log 2>&1"
Utiliser docker run
dans un pipeline Shell ou sous une redirection Shell, pour que run
accepte stdin et affiche les sorties stdout et stderr de manière appropriée, utilisez cette incantation:
docker run -i --log-driver=none -a stdin -a stdout -a stderr ...
par exemple. pour exécuter l'image Alpine
et exécuter la commande UNIX cat
dans l'environnement contenu:
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:
émet:
This is coming out of docker: This was piped into docker