I have a docker container running Debian jessie on Ubuntu yakkety.
When within the docker (connected via ssh
for instance) I am isolated from the host (which is expected). I however realized that dmesg
shows me the messages for the host and not for the container. How can it have access to information of its host?
The configuration of the docker container is not special (except that it uses a specific bridge, different from docker0
), in particular it does not run in any privileged mode ("Privileged": false
below):
root@srv ~# docker inspect minecraft-1-8
[
{
"Id": "748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e",
"Created": "2016-12-01T15:35:05.287672787Z",
"Path": "/usr/bin/supervisord",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 28650,
"ExitCode": 0,
"Error": "",
"StartedAt": "2016-12-15T18:37:08.409564695Z",
"FinishedAt": "2016-12-15T18:37:07.457274028Z"
},
"Image": "sha256:78a2f88d47e29523503c2196ed2faaa3d1039d948d73987edc03b2abd338595d",
"ResolvConfPath": "/var/lib/docker/containers/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e/hostname",
"HostsPath": "/var/lib/docker/containers/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e/hosts",
"LogPath": "/var/lib/docker/containers/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e-json.log",
"Name": "/minecraft-1-8",
"RestartCount": 0,
"Driver": "overlay",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "docker",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DiskQuota": 0,
"KernelMemory": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": -1,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0
},
"GraphDriver": {
"Name": "overlay",
"Data": {
"LowerDir": "/var/lib/docker/overlay/e78ce9dbcedd6974429a4aada8f38913b7d35da41f586f203dd99a568f38b6c3/root",
"MergedDir": "/var/lib/docker/overlay/e8422e4707d95db8ea747af2367626cc8bf16e95f8eb05dfad9a63461c9ade86/merged",
"UpperDir": "/var/lib/docker/overlay/e8422e4707d95db8ea747af2367626cc8bf16e95f8eb05dfad9a63461c9ade86/upper",
"WorkDir": "/var/lib/docker/overlay/e8422e4707d95db8ea747af2367626cc8bf16e95f8eb05dfad9a63461c9ade86/work"
}
},
"Mounts": [],
"Config": {
"Hostname": "minecraft-1-8",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/usr/bin/supervisord"
],
"Image": "minecraft",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "cf411634babad31138ab4572b9cd7306f74a54dd1baf4cd8d7706d7e7020c594",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/cf411634baba",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": {
"docker": {
"IPAMConfig": {
"IPv4Address": "10.200.0.100"
},
"Links": null,
"Aliases": [
"748cfdfbf3fb"
],
"NetworkID": "7b20560b36032d36ffe6c0ebece6b4408355d207f4e203a2957b0434ee0afdc1",
"EndpointID": "9fa4fc914dfe76022ce0db02e48a7e7c85c57bc2a15b0b3e5d81b1f24d95f376",
"Gateway": "10.200.0.1",
"IPAddress": "10.200.0.100",
"IPPrefixLen": 24,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:0a:c8:00:64"
}
}
}
}
]
In most distro's dmesg
is not a privileged command. Any user can use the klogctl interface to read the kernel ring buffer.
$ id
uid=1001(matt) gid=1001(matt) groups=1001(matt)
$ dmesg | head -1
[ 0.000000] Initializing cgroup subsys cpuset
But can't do anything beyond read
$ dmesg -C
dmesg: klogctl failed: Operation not permitted
Which extends to Docker
$ sudo docker run debian dmesg | head -1
[ 0.000000] Initializing cgroup subsys cpuset
$ sudo docker run debian dmesg -C
dmesg: klogctl failed: Operation not permitted
You can restrict read access down to root users and those with the CAP_SYSLOG or CAP_SYS_ADMIN capabilities via /proc/sys/kernel/dmesg_restrict
.
$ echo 1 > /proc/sys/kernel/dmesg_restrict
Then you should be getting a permission denied message:
$ docker run ubuntu:yakkety dmesg
dmesg: read kernel buffer failed: Operation not permitted
Running a container in privileged mode will then regain access to the hosts kernel ring buffer
$ docker run --privileged ubuntu:yakkety dmesg
[146902.131915] br-fa26f1dc96a1: port 3(veth80d3d5d) entered disabled state
...
Use sysctl to configure kernel.dmesg_restrict=1
if you need it permanently.
As to why the kernel log doesn't have name spacing like other kernel areas, I think the answer is "it's difficult". There's more detail than you'd care to know in this 2012 Stepping closer to practical containers: "syslog" namespaces LWN post. I can't see any reference's to it getting any further than proposed patches: https://lwn.net/Articles/562389/ https://lwn.net/Articles/561271/. As you can see in this recent netfilter patch, they have a work around to allow rules in a container name space to use the global log.