---
# System prepended metadata

title: How docker file log works
tags: [IT]

---

# How docker file log works
###### tags: `IT`
Docker generate 2 items when a conatiner is generated.
1. logger
2. copier 

### 1. Logger:
1. Monitoring the size of logs based on config
2. Rotate log file if config stores data into local files.
3. Provide target to copier
4. Provide log() to copier

### 2. Copier:
1. map the stream(stdio and stderr) to target (could be json, jounrald, or any others)
2. Copy data from stream into target(ex: json file)

### 3. Copier, logger and stdio stderr
```graphviz
digraph hierarchy {
    node [color=Red,fontname=Courier,shape=box]
    edge [color=Blue, style=dashed]
    
    {stdio, stderr}->coppier->"log function geterated by logger"->target

}
```
**How does filelog work ?**
1. dockerd opens a log file at [begining](https://github.com/moby/moby/blob/master/daemon/logger/loggerutils/logfile.go#L122), but closes it when the size is full
2. dockerd generate copier gorouting to [catch data from  stdio and stderr](https://github.com/moby/moby/blob/master/daemon/logger/copier.go#L86).
3. Check rotation before [wrting logs](https://github.com/moby/moby/blob/master/daemon/logger/loggerutils/logfile.go#L159)

This means even your file has large size (2GB), it doesn't affect write performance much, why? 
The behavior (stdio,stderr --> target) is no difference between a large and small logfile.



## Docker logger call stack 
https://github.com/moby/moby/blob/master/container/container.go

containerStart
  -> InitializeStdio
    -> [startLogging](https://github.com/moby/moby/blob/master/container/container.go#L661) 
       -> Generate [Copier](https://github.com/moby/moby/blob/master/container/container.go#L631) -> register stdio, stderr and target 
       -> [copier.run()](https://github.com/moby/moby/blob/master/container/container.go#L633)
       -> [run()](https://github.com/moby/moby/blob/master/daemon/logger/copier.go#L45) : Generate gorouting for stdio and stderr


## How the rotation happens on Jsonfile
When copier execute [log](https://github.com/moby/moby/blob/master/daemon/logger/copier.go#L160),which is generated based on log driver configuration, the log checks capacity first and decide to rotate or not.


The flow is : 
[log](https://github.com/moby/moby/blob/master/daemon/logger/copier.go#L160)
-> [WriteLogEntry](https://github.com/moby/moby/blob/master/daemon/logger/jsonfilelog/jsonfilelog.go#L133)
-> [w.capacity in WriteLogEntry](https://github.com/moby/moby/blob/master/daemon/logger/loggerutils/logfile.go#L169)
-> [rotate in WriteLogEntry](https://github.com/moby/moby/blob/master/daemon/logger/loggerutils/logfile.go#L170)
-> [rotate](https://github.com/moby/moby/blob/master/daemon/logger/loggerutils/logfile.go#L198)


How docker daemond [rotates files](https://github.com/moby/moby/blob/master/daemon/logger/loggerutils/logfile.go#L283-L295).
```go
    err := unlink(lastFile) // remove file
    ...
    ...

	for i := maxFiles - 1; i > 1; i-- {
        ...
        ...
		err := os.Rename(fromPath, toPath)
		logrus.WithError(err).WithField("source", fromPath).WithField("target", toPath).Trace("Rotating log file")
        ...
        ...
	}
```


## Where is STDIO and STDERR File of a Container ?
They are under /run/docker/containerd/<container-id>
```shell
# ls /run/docker/containerd/<container-id>
init-stderr  init-stdout
```


Related docs:
* https://signoz.io/blog/docker-logging/
* https://www.logicmonitor.com/blog/docker-logging-how-do-logs-work-with-docker-containers#docker-daemon-logs
* [Docker runtime img](https://github.com/containerd/containerd/blob/main/runtime/v2/README.md)