Docker容器中与主机同步的时间

时间:2020-03-31 20:23:24

标签: docker

我正在尝试通过我的CosmosDB应用连接到SpringBoot。如果我使用Spring或通过Intellij运行应用程序,则所有这些工作都可以进行。但是,当我在Docker中运行该应用程序时,出现以下错误消息:

com.azure.data.cosmos.CosmosClientException: The authorization token is not valid at the current time.
Please create another token and retry
(token start time: Thu, 26 Mar 2020 04:32:10 GMT, 
token expiry time: Thu, 26 Mar 2020 04:47:10 GMT, current server time: Tue, 31 Mar 2020 20:12:42 GMT).

请注意,在以上错误消息中,current server time是正确的,但其他时间落后了5天。

我发现有趣的是,我只在docker容器中收到过此消息。

FROM {copy of zulu-jdk11}

ARG JAR_FILE

#.crt file in the same folder as your Dockerfile
ARG CERT="cosmos.cer"
ARG ALIAS="cosmos2"

#import cert into java
COPY $CERT /
RUN chmod +x /$CERT
WORKDIR $JAVA_HOME/lib/security
RUN keytool -importcert -file /$CERT -alias $ALIAS -cacerts -storepass changeit -noprompt

WORKDIR /
COPY /target/${JAR_FILE} app.jar
COPY run-java.sh /
RUN chmod +x /run-java.sh

ENV JAVA_OPTIONS "-Duser.timezone=UTC"
ENV JAVA_APP_JAR "/app.jar"

# run as non-root to mitigate some security risks
RUN addgroup -S pcc && adduser -S nonroot -G nonroot
USER nonroot:nonroot

ENTRYPOINT ["/run-java.sh"]

要注意的一件事是ENV JAVA_OPTIONS "-Duser.timezone=UTC",但是删除它根本对我没有帮助

我基本上从IntelliJ运行相同的步骤,但没有问题,但是在docker中,到期日期似乎要晚5天。

version: "3.7"
services:
  orchestration-agent:
    image: {image-name}
    ports:
      - "8080:8080"
    network_mode: host
    environment:
      - COSMOSDB_URI=https://host.docker.internal:8081/
      - COSMOSDB_KEY={key}
      - COSMOSDB_DATABASE={database}
      - COSMOSDB_POPULATEQUERYMETRICS=true
      - COSMOSDB_ITEMLEVELTTL=60

我想也应该提到我将network_mode更改为host。而且我还将CosmosDB URI从https://localhost:8081更改为https://host.docker.internal:8081/

我还要提及的是,我在{@ 1}的帮助下构建了自己的dockerfile

Importing self-signed cert into Docker's JRE cacert is not recognized by the service

How to add a SSL self-signed cert to Jenkins for LDAPS within Dockerfile?

3 个答案:

答案 0 :(得分:3)

Docker容器不维护独立的时钟,它与Linux主机相同,因为时间不是命名空间值。这也是Docker删除更改容器内部时间的权限的原因,因为这会影响主机和其他容器,从而破坏隔离模型。

但是,在Docker桌面上,docker在VM内部运行(允许您在非Linux桌面上运行Linux容器),并且在笔记本电脑挂起时,VM的时间可能会不同步。当前正在github上的一个问题中对此进行跟踪,您可以按照以下问题查看进度:https://github.com/docker/for-win/issues/4526

可能的解决方案包括重新启动计算机,重新启动docker的VM,将NTP作为特权容器运行或使用以下PowerShell在Windows VM中重置时间同步:

Get-VMIntegrationService -VMName DockerDesktopVM -Name "Time Synchronization" | Disable-VMIntegrationService
Get-VMIntegrationService -VMName DockerDesktopVM -Name "Time Synchronization" | Enable-VMIntegrationService

使用WSL 2,重新启动VM涉及:

wsl --shutdown
wsl

答案 1 :(得分:1)

WSL 2 time shift after sleep 最近有一个已知问题,fixed in 5.10.16.3 WSL 2 Linux kernel 仍未包含在 Windows 10 版本 21H1 更新中,但 can be installed manually

如何查看 WSL 内核版本:

> wsl uname -r

旧内核的临时解决方法,有助于直到下次睡眠:

> wsl hwclock -s

答案 2 :(得分:0)

这是在 Windows 上使用 Docker 桌面的 WSL2 上对我有用的替代方法:

由于无法在 Docker 容器中设置日期,我只是在 WSL2 中打开 Ubuntu 并运行以下命令来同步时钟:

sudo date -s "$(wget -qSO- --max-redirect=0 google.com 2>&1 | grep Date: | cut -d' ' -f5-8)Z"

效果很好,所以我在 root 用户的 crontab 中添加了以下行:

# Edit root user's crontab
sudo crontab -e

# Add the following line to run it every minute of every day:
* * * * * sudo date -s "$(wget -qSO- --max-redirect=0 google.com 2>&1 | grep Date: | cut -d' ' -f5-8)Z"

在那之后,我刚刚重新启动了我的 Docker 容器,日期是正确的,因为它们似乎使用了 WSL2 Ubuntu 日期。

之前的日期(不正确):

date
Thu Feb  4 21:50:35 UTC 2021

之后的日期(正确):

date
Fri Feb  5 19:01:05 UTC 2021