Como definir a hora do sistema dinamicamente em um contêiner do Docker

28

Existe alguma maneira de definir um horário do sistema de contêineres do Docker dinamicamente (em tempo de execução) sem afetar a máquina host?

Usando

hwclock --set --date "Sat Aug 17 08:31:24 PDT 2016"

dá o seguinte erro:

hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --debug option to see the details of our search for an access method.

Usando

date -s "2 OCT 2006 18:00:00"

dá o seguinte erro:

date: cannot set date: Operation not permitted

Caso de uso:

Preciso testar software sensível ao tempo (o comportamento depende da data).

Outros casos de uso comuns:

  • executando software legado com erros do y2k
  • software de teste para conformidade com o ano 2038
  • depuração de problemas relacionados ao tempo, como certificados SSL expirados
  • executando um software que deixa de ser executado fora de um determinado período de tempo
  • processos determinísticos de construção.
Vingtoft
fonte
Qual seria o objetivo de fazer isso? qual é o seu caso de uso?
dawud 6/01/17
Por favor, veja editar.
Vingtoft
11
Na verdade, eu encontrei e testei positivamente uma solução usando o libfaketime github.com/wolfcw/libfaketime . Atualizarei com uma resposta + exemplo de trabalho em breve.
Vingtoft

Respostas:

21

É possível

A solução é falsificá-lo no contêiner. Essa lib intercepta todos os programas de chamada do sistema usados ​​para recuperar a hora e a data atuais.

A implementação é fácil. Adicione funcionalidade ao seu Dockerfile, conforme apropriado:

WORKDIR /
RUN git clone https://github.com/wolfcw/libfaketime.git
WORKDIR /libfaketime/src
RUN make install

Lembre-se de definir as variáveis ​​de ambiente LD_PRELOADantes de executar o aplicativo ao qual você deseja aplicar o tempo falso.

Exemplo:

CMD ["/bin/sh", "-c", "LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 FAKETIME_NO_CACHE=1 python /srv/intercept/manage.py runserver 0.0.0.0:3000]

Agora você pode alterar dinamicamente o horário dos servidores:

Exemplo:

import os
def set_time(request):
    print(datetime.today())
    os.environ["FAKETIME"] = "2020-01-01"  # Note: time of type string must be in the format "YYYY-MM-DD hh:mm:ss" or "+15d"
    print(datetime.today())
Vingtoft
fonte
6
Para outros usuários desta solução, lembre-se de que isso não funcionará para aplicativos golang ou outros exes vinculados estaticamente.
Sentinel
5
Obrigado @Sentinel. Curiosamente, acabei de encontrar esta resposta no google, quero especificamente usá-la com um aplicativo golang e notei que você deixou esse comentário em uma pergunta de 1,5 anos de idade há apenas 2 horas. Parece que foi para mim. Obrigado! :)
dimonomid 16/10
Por que não funciona na sua situação? Golang não usa chamadas do sistema para recuperar o tempo? @ Dimonomid Eu sugiro que você tente, é rápido para implementar a solução.
Vingtoft
11
@Vingtoft Deixe-me saber se de fato funciona, mas procure ao redor. Golang não se vincula dinamicamente nas bibliotecas.
Sentinel
11
Simonomid @ Sim, fiquei muito decepcionado. Mais decepcionado com o Docker, na verdade. Eu preciso implementar testes relacionados ao tempo. Isso torna o Docker praticamente inútil como um "contêiner". Eu pensaria que interceptar as chamadas de hora do sistema para sincronização de fuso horário teria sido o item 1 da agenda do Docker. Aparentemente não.
Sentinel
4

Jenny D está correta, pois, por padrão, o contêiner do Docker não permite o acesso ao relógio do sistema.

No entanto, no Linux, se você estiver bem com seu contêiner tendo acesso a esse recurso, poderá permitir esse recurso usando a opção "--cap-add = SYS_TIME" do comando "docker run" ao criar seu contêiner:

# docker run --cap-add=SYS_TIME -d --name teamcity-server-instance -v /opt/teamcity/data:/data/teamcity_server/datadir -v /opt/teamcity/logs:/opt/teamcity/logs -p 80:8111 jetbrains/teamcity-server

Em seguida, você pode alterar a hora de dentro do contêiner em execução:

# docker exec -it teamcity-server-instance /bin/bash
# date +%T -s "15:03:00"
15:03:00
#

Documentação de referência: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

Oleg Kazakov
fonte
2
Isso altera o tempo na máquina host. Atualmente, o tempo em um sistema Linux não está no namespace, existe apenas um valor para o host e todos os contêineres.
BMitch 27/02
Sim, você está certo. Isso altera a hora do relógio da máquina host. Basta reler a pergunta e perceber que ela realmente é mencionada explicitamente sobre NÃO alterar o relógio da máquina host. Eu estou corrigido :) #
1111 Oleg Kazakov
0

Inicie o contêiner com uma variável de ambiente adicional:

docker run -e "SET_CONTAINER_TIMEZONE=true" \
           -e "CONTAINER_TIMEZONE=US/Arizona" [docker image name]
13dimitar
fonte
Estou procurando uma maneira de definir o tempo dinamicamente, o que significa que ele pode ser definido em tempo de execução. Eu atualizei minha pergunta.
Vingtoft
0

solução docker-compose:

Adicione /etc/localtime:/etc/localtime:roao volumesatributo

Veja este link para um exemplo.

Benyamin Jafari
fonte