Время в контейнере 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 дней.
Что мне интересно, так это то, что я получаю это только в контейнере докера.
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, и у меня нет проблем с ним, но в докере срок годности кажется на 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
. И я также изменил URI CosmosDB сhttps://localhost:8081
к https://host.docker.internal:8081/
Хочу также отметить, что построил свой dockerfile
с помощью:
Импорт самозаверяющего сертификата в Docker JRE cacert не распознается службой
Как добавить самозаверяющий сертификат SSL в Jenkins для LDAPS в Dockerfile?
3 ответа
Контейнеры Docker не поддерживают отдельные часы, они идентичны хосту Linux, поскольку время не является значением пространства имен. По этой же причине Docker удаляет разрешение на изменение времени внутри контейнера, поскольку это повлияет на хост и другие контейнеры, нарушив модель изоляции.
Однако на Docker Desktop docker работает внутри виртуальной машины (что позволяет запускать контейнеры Linux на рабочих столах, отличных от Linux), и время этой виртуальной машины может не синхронизироваться, когда ноутбук приостановлен. В настоящее время это отслеживается в проблеме на github, за которой вы можете следить, чтобы увидеть прогресс: https://github.com/docker/for-win/issues/4526
Возможные решения включают перезагрузку компьютера, перезапуск виртуальной машины докера, запуск NTP в качестве привилегированного контейнера или сброс синхронизации времени на виртуальной машине Windows с помощью следующей оболочки PowerShell:
Get-VMIntegrationService -VMName DockerDesktopVM -Name "Time Synchronization" | Disable-VMIntegrationService
Get-VMIntegrationService -VMName DockerDesktopVM -Name "Time Synchronization" | Enable-VMIntegrationService
В WSL 2 перезапуск виртуальной машины включает:
wsl --shutdown
wsl
Недавно появилась известная проблема с временным сдвигом WSL 2 после сна, которая была исправлена в ядре Linux 5.10.16.3 WSL 2, которое включено в обновление Windows 10 версии 21H1 и также может быть установлено вручную .
Вот альтернатива, которая сработала для меня на WSL2 с Docker Desktop в Windows:
Поскольку установить дату внутри контейнера Docker невозможно, я просто открыл Ubuntu в WSL2 и выполнил следующую команду для синхронизации часов:
sudo date -s "$(wget -qSO- --max-redirect=0 google.com 2>&1 | grep Date: | cut -d' ' -f5-8)Z"
Это сработало хорошо, поэтому я добавил следующую строку в 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