Docker与Windows时间不同步的问题及解决办法

最近突然发现Windows上的Docker Container时间滞后于Windows系统时间,这有时候会对Container造成不可预测的影响。因此在做了一番调研,解决方法记录如下。

出现原因

目前我的Docker容器内的时间为Sun Jun 6 21:54:29 UTC 2021,但是Windows系统时间为2021年6月7日 15:05:10,Docker Container滞后了大约9个小时。这个问题出现的原因,简而言之就是使用了Windows系统的睡眠功能。当Windows从睡眠中醒来时,时间没有得到同步,于是Docker Container就滞后了睡眠所消耗的时间。

因此,要解决这个问题,我们就要让两边的时间同步。

解决方案

以下假设你的Windows系统装载了PowerShell。强烈建议直接装Windows Terminal一步到位,在官方应用商店可以下载到。如果需要查看你的Docker引擎,可以进入Docker Desktop的设置页,看一下Use the WSL 2 based engine是否被勾选。

运行在WSL2之上的Docker[1]

运行WSL2上的Docker很容易可以解决这个问题。关于该bug的讨论可以参考GitHub[2]。解决该问题的方法非常简单,只需在PowerShell里运行:

1
wsl --shutdown

此时Docker Desktop会提示你WSL2后端已经被关闭,并问你是否需要重启。点击restart并等待一段时间即可修复问题。

运行在Hyper-V之上的Docker[3]

这个版本的解决方案没有经过我的亲自实验(因为我的Docker基于WSL2),仅供参考。

首先我们准备如下的.ps1脚本:

1
2
3
4
5
$vm = Get-VM -Name DockerDesktopVM
$feature = "Time Synchronization"

Disable-VMIntegrationService -vm $vm -Name $feature
Enable-VMIntegrationService -vm $vm -Name $feature

保存该文件为docker-time-sync.ps1(或者你喜欢的其他名字)。通过管理员身份启动PowerShell,定位到该文件的位置并运行它。

如果显示以下错误信息:

1
无法将“Get-VM”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。……

则需要你修改一下权限。首先运行Get-ExecutionPolicy -List查看一下当前的作用域,并通过Set-ExecutionPolicy RemoteSigned -Scope CurrentUser进行修改。修改完毕后再次尝试运行以上脚本。

根据GitHub[4]上的讨论,你也可以打开Hyper-V管理器程序,关闭并重新开启以下功能(未经翻译)即可解决:

1
MobyLinuxVM > Settings > Integration Services > Time synchronization

  1. https://www.thegrussalo.com/2021/01/docker-container-time-drift-using-wsl2.html ↩︎

  2. https://github.com/microsoft/WSL/issues/4149 ↩︎

  3. https://www.thorsten-hans.com/docker-on-windows-fix-time-synchronization-issue ↩︎

  4. https://hub.fastgit.org/docker/for-win/issues/72 ↩︎