# 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)