为什么docker容器中的shell会显示来自主机的dmesg内容?

我有一个在Ubuntu yakkety上运行Debian jessie的docker容器。

在Docker中(例如通过ssh连接),我与主机隔离(这是预期的)。 然而,我意识到, dmesg向我显示了主机的信息,而不是容器的信息。 如何获取主机的信息?

docker容器的configuration不是特别的(除了它使用一个特定的桥,不同于docker0 ),特别是它不能以任何特权模式运行(下面的"Privileged": false ):

 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" } } } } ] 

在大多数发行版的dmesg不是一个特权命令。 任何用户都可以使用klogctl接口读取内核环缓冲区。

 $ id uid=1001(matt) gid=1001(matt) groups=1001(matt) $ dmesg | head -1 [ 0.000000] Initializing cgroup subsys cpuset 

但是除了阅读之外什么都不能做

 $ dmesg -C dmesg: klogctl failed: Operation not permitted 

这延伸到了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 

限制访问

您可以通过/proc/sys/kernel/dmesg_restrict将读取权限限制在root用户和具有CAP_SYSLOG或CAP_SYS_ADMIN function的 /proc/sys/kernel/dmesg_restrict

 $ echo 1 > /proc/sys/kernel/dmesg_restrict 

那么你应该得到一个权限被拒绝的消息:

 $ docker run ubuntu:yakkety dmesg dmesg: read kernel buffer failed: Operation not permitted 

以特权模式运行容器将重新获得对主机内核环形缓冲区的访问权限

 $ docker run --privileged ubuntu:yakkety dmesg [146902.131915] br-fa26f1dc96a1: port 3(veth80d3d5d) entered disabled state ... 

如果您需要永久使用sysctl来configurationkernel.dmesg_restrict=1

命名空间

至于为什么内核日志没有其他内核区域的名称空间,我想答案是“很难”。 有更多的细节比你在2012年更加了解更接近实际的容器:“syslog”命名空间LWN发布。 我看不到任何参考,它得到比build议的补丁更进一步: https : //lwn.net/Articles/562389/ https://lwn.net/Articles/561271/ 。 正如你可以在这个最近的netfilter补丁中看到的,他们有一个解决方法来允许容器名称空间中的规则使用全局日志。

Interesting Posts