Jak przekierować dzienniki kontenerów Dockera do pojedynczego pliku?

111

Chcę przekierować wszystkie dzienniki mojego kontenera docker do pojedynczego pliku dziennika, aby je przeanalizować. próbowałem

docker logs container > /tmp/stdout.log 2>/tmp/stderr.log

ale to daje log w dwóch różnych plikach. Już próbowałem

docker logs container > /tmp/stdout.log

ale to nie zadziałało.

KETAN PATIL
źródło

Odpowiedzi:

137

Nie ma potrzeby przekierowywania dzienników.

Docker domyślnie przechowuje dzienniki w jednym pliku dziennika. Aby sprawdzić ścieżkę pliku dziennika, uruchom polecenie:

docker inspect --format='{{.LogPath}}' containername

/var/lib/docker/containers/f844a7b45ca5a9589ffaa1a5bd8dea0f4e79f0e2ff639c1d010d96afb4b53334/f844a7b45ca5a9589ffaa1a5bd8dea0f4e79f0e2ff639c1d010d96afb4b53334-json.log

Otwórz ten plik dziennika i przeanalizuj.

jeśli przekierowujesz logi, otrzymasz tylko dzienniki przed przekierowaniem. nie będzie można zobaczyć dzienników na żywo.

EDYTOWAĆ:

Aby zobaczyć dzienniki na żywo, możesz uruchomić poniższe polecenie

tail -f `docker inspect --format='{{.LogPath}}' containername`

Uwaga:

Ten plik dziennika /var/lib/docker/containers/f844a7b45ca5a9589ffaa1a5bd8dea0f4e79f0e2ff639c1d010d96afb4b53334/f844a7b45ca5a9589ffaa1a5bd8dea0f4e79f0e2ff639c1d010d96afb4b53334-json.logzostanie utworzony tylko wtedy, gdy docker generuje dzienniki, jeśli nie ma żadnych dzienników, to tego pliku nie będzie. jest podobnie, jak czasami, gdy uruchomimy polecenie docker logs containernamei nic nie zwraca. W takim przypadku ten plik nie będzie dostępny.

pl_rock
źródło
tail -f `docker inspect --format='{{.LogPath}}' myapp`- to naprawdę JSON
Adam
nie powiedzie się, jeśli tego pliku nie ma. oznacza, że ​​jeśli docker nie wygeneruje żadnego dziennika, to ten plik nie zostanie utworzony. ale jeśli docker generuje logi, to polecenie jest dobre, aby zobaczyć dzienniki na żywo. dzięki Adam. dodając to do mojej odpowiedzi, aby pomóc innym.
pl_rock
„Docker domyślnie przechowuje dzienniki w jednym pliku dziennika”. - w jakim kontekście? Wszystkie kontenery działające na hoście platformy docker otrzymują dane wyjściowe do jednego pliku? Pojedynczy pojemnik?
Chris Stryczynski
@ChrisStryczynski Docker tworzy plik dziennika dla każdego kontenera
Eddy Hernandez
127

A co z tą opcją:

docker logs containername >& logs/myFile.log

Nie przekieruje dzienników, o które pytano w pytaniu, ale skopiuje je raz do określonego pliku.

Eddy Hernandez
źródło
Jeśli się nie mylę, to polecenie w zasadzie skopiuje wszystkie dzienniki z momentu uruchomienia kontenera, aby przedstawić je w myFile.logs. Dobrze.?
S Andrew,
@SAndrew w zasadzie tak! ale nowe wersje Dockera mogą ulec zmianie. lepiej zobaczyć, docker logs --helpaby mieć pewność
Eddy Hernandez
39

docker logs -f <yourContainer> &> your.log &

Wyjaśnienie:

  • -f(tj. --follow): zapisuje wszystkie istniejące dzienniki i kontynuuje ( następuje ) rejestrowanie wszystkiego, co nastąpi później.
  • &> przekierowuje zarówno standardowe wyjście, jak i błąd standardowy.
  • Prawdopodobnie chcesz uruchomić tę metodę w tle, dlatego plik &.
  • Możesz oddzielić wyjście i stderr przez: > output.log 2> error.log(zamiast używać &>).
juanmirocks
źródło
9

Aby przechwycić zarówno stdout, jak i stderr z kontenera Dockera do pojedynczego pliku dziennika, uruchom następujące polecenie:

docker logs container > container.log 2>&1
Jean Velloen
źródło
8

Zakładając, że masz wiele kontenerów i chcesz zagregować dzienniki w jeden plik, musisz użyć jakiegoś agregatora dzienników, takiego jak fluentd. Fluentd jest obsługiwany jako sterownik rejestrowania dla kontenerów Docker.

Dlatego w docker-compose musisz zdefiniować sterownik rejestrowania

  service1:
    image: webapp:0.0.1
    logging:
      driver: "fluentd"
      options:
        tag: service1 

  service2:
        image: myapp:0.0.1
        logging:
          driver: "fluentd"
          options:
            tag: service2

Drugim krokiem byłaby aktualizacja konfiguracji fluentd w celu obsługi dzienników zarówno dla usługi 1, jak i usługi 2

 <match service1>
   @type copy
   <store>
    @type file
    path /fluentd/log/service/service.*.log
    time_slice_format %Y%m%d
    time_slice_wait 10m
    time_format %Y%m%dT%H%M%S%z
  </store>
 </match> 
 <match service2>
    @type copy
   <store>
    @type file
    path /fluentd/log/service/service.*.log
    time_slice_format %Y%m%d
    time_slice_wait 10m
    time_format %Y%m%dT%H%M%S%
  </store>
 </match> 

W tej konfiguracji prosimy o zapisywanie logów do pojedynczego pliku w tej ścieżce
/fluentd/log/service/service.*.log

a trzecim krokiem byłoby uruchomienie dostosowanego fluentd, który rozpocznie zapisywanie dzienników do pliku.

Oto link do instrukcji krok po kroku

Nieco długi, ale poprawny sposób, ponieważ masz większą kontrolę nad ścieżką plików dziennika itp. I działa również dobrze w Docker Swarm.

Abhishek Galoda
źródło
1

Ponieważ Docker łączy dla nas stdout i stderr, możemy traktować dane wyjściowe dziennika jak każdy inny strumień powłoki. Aby przekierować bieżące dzienniki do pliku, użyj operatora przekierowania

$ docker logs test_container > output.log
docker logs -f test_container > output.log

Zamiast wysyłać dane wyjściowe do stderr i stdout, przekieruj dane wyjściowe aplikacji do pliku i zamapuj plik na stały magazyn poza kontenerem.

$ docker logs test_container> /tmp/output.log

Docker nie akceptuje ścieżek względnych w wierszu poleceń, więc jeśli chcesz użyć innego katalogu, musisz użyć pełnej ścieżki.

Anish Varghese
źródło
1

Jeśli pracujesz w systemie Windows i używasz PowerShell (tak jak ja), możesz użyć następującego wiersza, aby przechwycić stdouti stderr:

 docker logs <containerId> | Out-File 'C:/dev/mylog.txt'

Mam nadzieję, że to komuś pomoże!

mirind4
źródło
1
Aby zapisać wszystkie dzienniki kontenerów do pliku, na podstawie nazwy kontenera ...foreach ($element in $(docker ps -a --format "{{.Names}}")) {docker logs $element | Out-File "C:/dockerlogs/$element.log"}
xisket
1

Najłatwiejszym sposobem, którego używam, jest to polecenie na terminalu:

docker logs elk > /home/Desktop/output.log

struktura to:

docker logs <Container Name> > path/filename.log
itssaifurrehman
źródło
1

Najpierw sprawdź identyfikator kontenera

docker ps -a

Możesz zobaczyć pierwszy wiersz w kolumnach CONTAINER ID. Prawdopodobnie wygląda to tak "3fd0bfce2806", a następnie wpisz go w powłoce

docker inspect --format='{{.LogPath}}' 3fd0bfce2806

Zobaczysz coś takiego

/var/lib/docker/containers/3fd0bfce2806b3f20c2f5aeea2b70e8a7cff791a9be80f43cdf045c83373b1f1/3fd0bfce2806b3f20c2f5aeea2b70e8a7cff791a9be80f43cdf045c83373b1f1-json.log

wtedy możesz zobaczyć to jako

cat /var/lib/docker/containers/3fd0bfce2806b3f20c2f5aeea2b70e8a7cff791a9be80f43cdf045c83373b1f1/3fd0bfce2806b3f20c2f5aeea2b70e8a7cff791a9be80f43cdf045c83373b1f1-json.log

Byłby w formacie JSON, możesz użyć sygnatury czasowej do śledzenia błędów

kiran beethoju
źródło
0

Skrypt Bash do kopiowania wszystkich dzienników kontenerów do określonego katalogu:

#!/usr/bin/env bash

TARGET_DIR=~/logs/docker_logs
mkdir -p "$TARGET_DIR"
for name in `sudo docker ps --format '{{.Names}}'`;
do
    path=$(sudo docker inspect --format='{{.LogPath}}' $name)
    sudo cp -rf "$path" "$TARGET_DIR"/$name.log
done
Mugen
źródło