Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker: How to clear the logs properly for a Docker container?

I use docker logs [container-name] to see the logs of a specific container.

Is there an elegant way to clear these logs?

like image 718
Youssouf Maiga Avatar asked Feb 28 '17 13:02

Youssouf Maiga


People also ask

How do I reduce docker logs?

If you want to disable logs only for specific containers, you can start them with --log-driver=none in the docker run command. Another option could be to mount an external storage to /var/lib/docker . Like an NFS share or something which has more storage capacity than the host in question.


15 Answers

First the bad answer. From this question there's a one-liner that you can run:

echo "" > $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

instead of echo, there's the simpler:

: > $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

or there's the truncate command:

truncate -s 0 $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

I'm not a big fan of either of those since they modify Docker's files directly. The external log deletion could happen while docker is writing json formatted data to the file, resulting in a partial line, and breaking the ability to read any logs from the docker logs cli. For an example of that happening, see this comment on duketwo's answer:

after emptying the logfile, I get this error: error from daemon in stream: Error grabbing logs: invalid character '\x00' looking for beginning of value

Instead, you can have Docker automatically rotate the logs for you. This is done with additional flags to dockerd if you are using the default JSON logging driver:

dockerd ... --log-opt max-size=10m --log-opt max-file=3

You can also set this as part of your daemon.json file instead of modifying your startup scripts:

{
  "log-driver": "json-file",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

These options need to be configured with root access. Make sure to run a systemctl reload docker after changing this file to have the settings applied. This setting will then be the default for any newly created containers. Note, existing containers need to be deleted and recreated to receive the new log limits.


Similar log options can be passed to individual containers to override these defaults, allowing you to save more or fewer logs on individual containers. From docker run this looks like:

docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 ...

or in a compose file:

version: '3.7'
services:
  app:
    image: ...
    logging:
      options:
        max-size: "10m"
        max-file: "3"

For additional space savings, you can switch from the json log driver to the "local" log driver. It takes the same max-size and max-file options, but instead of storing in json it uses a binary syntax that is faster and smaller. This allows you to store more logs in the same sized file. The daemon.json entry for that looks like:

{
  "log-driver": "local",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

The downside of the local driver is external log parsers/forwarders that depended on direct access to the json logs will no longer work. So if you use a tool like filebeat to send to Elastic, or Splunk's universal forwarder, I'd avoid the "local" driver.

I've got a bit more on this in my Tips and Tricks presentation.

like image 104
BMitch Avatar answered Oct 06 '22 04:10

BMitch


Use:

truncate -s 0 /var/lib/docker/containers/*/*-json.log

You may need sudo

sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"

ref. Jeff S. How to clear the logs properly for a Docker container?

Reference: Truncating a file while it's being used (Linux)

like image 41
duketwo Avatar answered Oct 06 '22 03:10

duketwo


On Docker for Windows and Mac, and probably others too, it is possible to use the tail option. For example:

docker logs -f --tail 100

This way, only the last 100 lines are shown, and you don't have first to scroll through 1M lines...

(And thus, deleting the log is probably unnecessary)

like image 20
Egbert Nierop Avatar answered Oct 06 '22 03:10

Egbert Nierop


sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"
like image 22
richard Avatar answered Oct 06 '22 04:10

richard


You can set up logrotate to clear the logs periodically.

Example file in /etc/logrotate.d/docker-logs

/var/lib/docker/containers/*/*.log {
 rotate 7
 daily
 compress
 size=50M
 missingok
 delaycompress
 copytruncate
}
like image 44
AlexPnt Avatar answered Oct 06 '22 03:10

AlexPnt


You can also supply the log-opts parameters on the docker run command line, like this:

docker run --log-opt max-size=10m --log-opt max-file=5 my-app:latest

or in a docker-compose.yml like this

my-app:
image: my-app:latest
logging:
    driver: "json-file"
    options:
        max-size: "10m"
        max-file: "5"

Credits: https://medium.com/@Quigley_Ja/rotating-docker-logs-keeping-your-overlay-folder-small-40cfa2155412 (James Quigley)

like image 29
Dag Baardsen Avatar answered Oct 06 '22 04:10

Dag Baardsen


Docker4Mac, a 2018 solution:

LOGPATH=$(docker inspect --format='{{.LogPath}}' <container_name_or_id>)
docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- truncate -s0 $LOGPATH

The first line gets the log file path, similar to the accepted answer.

The second line uses nsenter that allows you to run commands in the xhyve VM that servers as the host for all the docker containers under Docker4Mac. The command we run is the familiar truncate -s0 $LOGPATH from non-Mac answers.

If you're using docker-compose, the first line becomes:

local LOGPATH=$(docker inspect --format='{{.LogPath}}' $(docker-compose ps -q <service>))

and <service> is the service name from your docker-compose.yml file.

Thanks to https://github.com/justincormack/nsenter1 for the nsenter trick.

like image 41
elifiner Avatar answered Oct 06 '22 05:10

elifiner


You can't do this directly through a Docker command.

You can either limit the log's size, or use a script to delete logs related to a container. You can find scripts examples here (read from the bottom): Feature: Ability to clear log history #1083

Check out the logging section of the docker-compose file reference, where you can specify options (such as log rotation and log size limit) for some logging drivers.

like image 34
Tristan Avatar answered Oct 06 '22 05:10

Tristan


As a root user, try to run the following:

>  /var/lib/docker/containers/*/*-json.log

or

cat /dev/null > /var/lib/docker/containers/*/*-json.log

or

echo "" > /var/lib/docker/containers/*/*-json.log
like image 34
matson kepson Avatar answered Oct 06 '22 05:10

matson kepson


Here is a cross platform solution to clearing docker container logs:

docker run --rm -v /var/lib/docker:/var/lib/docker alpine sh -c "echo '' > $(docker inspect --format='{{.LogPath}}' CONTAINER_NAME)"

Paste this into your terminal and change CONTAINER_NAME to desired container name or id.

like image 26
Max Barrass Avatar answered Oct 06 '22 03:10

Max Barrass


On my Ubuntu servers even as sudo I would get Cannot open ‘/var/lib/docker/containers/*/*-json.log’ for writing: No such file or directory

But combing the docker inspect and truncate answers worked :

sudo truncate -s 0 `docker inspect --format='{{.LogPath}}' <container>`
like image 23
aqwan Avatar answered Oct 06 '22 03:10

aqwan


I do prefer this one (from solutions above):

truncate -s 0 /var/lib/docker/containers/*/*-json.log

However I'm running several systems (Ubuntu 18.x Bionic for example), where this path does not work as expected. Docker is installed through Snap, so the path to containers is more like:

truncate -s 0 /var/snap/docker/common/var-lib-docker/containers/*/*-json.log
like image 23
igraczech Avatar answered Oct 06 '22 04:10

igraczech


This will delete all logfiles for all containers:

sudo find /var/lib/docker/containers/ -type f -name "*.log" -delete
like image 7
Jakobovski Avatar answered Oct 06 '22 05:10

Jakobovski


Not sure if this is helpful for you, but removing the container always helps.

So, if you use docker-compose for your setup, you can simply use docker-compose down && docker-compose up -d instead of docker-compose restart. With a proper setup (make sure to use volume mounts for persistent data), you don't lose any data this way.

Sure, this is more than the OP requested. But there are various situations where the other answers cannot help (if using a remote docker server or working on a Windows machine, accessing the underlying filesystem is proprietary and difficult)

like image 5
Daniel Alder Avatar answered Oct 06 '22 04:10

Daniel Alder


Thanks to answer by @BMitch, I've just wrote a shell script to clean logs of all the containers:

#!/bin/bash
ids=$(docker ps -a --format='{{.ID}}')
for id in $ids
do
        echo $(docker ps -a --format='{{.ID}} ### {{.Names}} ### {{.Image}}' | fgrep $id)
        truncate -s 0 $(docker inspect --format='{{.LogPath}}' $id)
        ls -llh $(docker inspect --format='{{.LogPath}}' $id)
done
like image 4
Mohsen Abasi Avatar answered Oct 06 '22 05:10

Mohsen Abasi