这个问题似乎已被问过很多次,但答案似乎已经过时,或者只是不起作用。
我使用的是没有 RTC(树莓派)的 Linux 系统。我的主机运行一个 ntp 守护进程 (
ntpd
),假设主机有互联网,它会在主机启动后立即检查在线时间,并设置系统时钟。
我的容器内的代码需要知道主机的系统时钟是否准确(自上次启动以来已更新)。
在主机本身上,这很容易做到 - 使用类似
ntpdate -q 127.0.0.1
的东西。 ntpdate
通过 udp 连接到 127.0.0.1:123
,并使用 ntpd
守护进程检查时钟是否准确(如果自上次启动后已更新)。这似乎在容器内更难做到。
如果我启动一个容器,并使用
docker container inspect NAME
查看容器的 IP,它会向我显示以下内容:
"Gateway": "172.19.0.1",
"IPAddress": "172.19.0.6",
如果我在容器内运行
ntpdate -q 172.19.0.1
,这是有效的。不幸的是,172.19.0.1
不是主机的永久 IP。如果容器启动时子网已被占用,则子网将会更改,因此硬编码此 IP 是一个坏主意。我需要的是一个始终反映主机正确 IP 的环境变量。
Windows 和 MacOS 版本的 docker 似乎可以在容器内设置
host.docker.internal
主机名,但 Linux 则不然。有些人建议在主机的 /etc/hosts
文件中设置此项,但随后您只需对 IP 进行硬编码,而 IP 又可以更改。
我使用
docker-compose.yml
文件运行我的 docker 容器,显然,在新版本的 docker 上,您可以执行以下操作:
extra_hosts:
- "host.docker.internal:host-gateway"
我试过了,这有效。有点像。在我的容器内,
host.docker.internal
解析为 172.17.0.1
,这是主机上 docker0
接口的 IP。虽然我可以从容器内 ping host.docker.internal
,但使用 ntpdate -q host.docker.internal
或 ntpdate -q 172.17.0.1
不起作用。
有没有办法让
host.docker.internal
从容器内解析到主机的正确网关IP?在我的例子中,172.19.0.1
。
注意:是的,我可以使用容器内的代码来检查容器的网关是什么,或者类似的,但是我需要使我的代码复杂化,使其找出 NTP 服务器(docker 主机)的 IP 。我也许还可以将 docker 套接字传递到容器中,并尝试通过它获取 docker 主机的 IP,但这似乎超级 hackey,并且是不必要的安全问题。
netstat
包中的
ip
命令,查找默认路由并使用它的网关地址。iproute2
如果您希望将其放在环境变量中,可以使用在入口点脚本中设置它
ip route | awk '/default/ {print $3}'
export HOST_IP_ADDRESS=$(ip route | awk '/default/ {print $3}')
,但使用
或host.docker.internal
不起作用。 最可能的原因是主机上的 NTP 服务器未绑定到 docker 接口。事实上,当你的 NTP 服务器启动时,docker 接口甚至可能不存在。ntpdate -q host.docker.internal
您可以通过在主机上运行一个简单的网络服务器来确认这一点:
ntpdate -q 172.17.0.1
然后尝试从容器访问它:
python -m http.server
如果有效,则确认您可以从容器内访问主机。
对于 NTP 服务器,在 docker 网络设置完毕后尝试重新启动它,看看是否有助于它绑定到 docker 接口。