Cómo configurar la hora del sistema dinámicamente en un contenedor Docker

28

¿Hay alguna forma de configurar el tiempo de un sistema de contenedores Docker dinámicamente (en tiempo de ejecución) sin afectar la máquina host?

Utilizando

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

da el siguiente error:

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.

Utilizando

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

da el siguiente error:

date: cannot set date: Operation not permitted

Caso de uso:

Necesito probar un software sensible al tiempo (el comportamiento depende de la fecha).

Otros casos de uso común:

  • ejecutando software heredado con errores y2k
  • prueba de software para el cumplimiento del año 2038
  • depuración de problemas relacionados con el tiempo, como certificados SSL caducados
  • Ejecutar software que deja de ejecutarse fuera de un cierto período de tiempo
  • Procesos de construcción deterministas.
Vingtoft
fuente
¿Cuál sería el propósito de hacerlo? ¿Cuál es tu caso de uso?
Dawud
Por favor vea editar.
Vingtoft
1
En realidad, acabo de encontrar y probar positivamente una solución usando libfaketime github.com/wolfcw/libfaketime que actualizaré con una respuesta + ejemplo de trabajo en breve.
Vingtoft

Respuestas:

21

Es posible

La solución es fingirlo en el contenedor. Esta biblioteca intercepta todos los programas de llamadas al sistema que utilizan para recuperar la fecha y hora actuales.

La implementación es fácil. Agregue funcionalidad a su Dockerfile según corresponda:

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

Recuerde configurar las variables de entorno LD_PRELOADantes de ejecutar la aplicación a la que desea aplicar el tiempo falso.

Ejemplo:

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]

Ahora puede cambiar dinámicamente la hora del servidor:

Ejemplo:

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
fuente
66
Para otros que vienen a esta solución, tenga en cuenta que esto no funcionará para aplicaciones de Golang u otros exes vinculados estáticamente.
Sentinel
55
Gracias @Sentinel. Curiosamente, acabo de encontrar esta respuesta a través de google, específicamente quiero usarla con una aplicación de golang, y noté que dejaste este comentario en una pregunta de hace 1,5 años hace solo 2 horas. Se siente como si fuera para mí. ¡Gracias! :)
dimonomid
¿Por qué no funciona en tu situación? ¿Golang no utiliza las llamadas del sistema para recuperar el tiempo? @dimonomid Le sugiero que lo pruebe, es rápido implementar la solución.
Vingtoft
1
@Vingtoft Avíseme si realmente funciona, pero busque. Golang no se vincula dinámicamente en las bibliotecas.
Sentinel
1
@dimonomid Sí, estaba bastante decepcionado. Más decepcionado con Docker en realidad. Necesito implementar pruebas relacionadas con el tiempo. Esto hace que Docker sea prácticamente inútil como un "contenedor". Pensé que interceptar las llamadas de hora del sistema para la sincronización de la zona horaria habría sido el elemento 1 en la agenda de Docker. Aparentemente no.
Sentinel
4

Jenny D tiene razón en que, por defecto, el contenedor Docker no permite el acceso al reloj del sistema.

Sin embargo, en Linux, si está de acuerdo con que su contenedor tenga acceso a esta capacidad, puede permitir esta capacidad utilizando la opción "--cap-add = SYS_TIME" del comando "docker run" al crear su contenedor:

# 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

Luego, puede cambiar el tiempo desde el interior del contenedor en ejecución:

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

Documentación de referencia: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

Oleg Kazakov
fuente
2
Esto cambia el tiempo en la máquina host. El tiempo en un sistema Linux no tiene espacio de nombres actualmente, solo hay un valor para el host y todos los contenedores.
BMitch
Sí tienes razón. Esto cambia la hora del reloj de la máquina host. Simplemente releí la pregunta y me di cuenta de la pregunta, de hecho, mencionada explícitamente sobre NO cambiar el reloj de la máquina host. Estoy corregido :)
Oleg Kazakov
0

Inicie el contenedor con una variable de entorno adicional:

docker run -e "SET_CONTAINER_TIMEZONE=true" \
           -e "CONTAINER_TIMEZONE=US/Arizona" [docker image name]
13dimitar
fuente
Estoy buscando una manera de configurar el tiempo dinámicamente, lo que significa que se puede configurar en tiempo de ejecución. He actualizado mi pregunta.
Vingtoft
0

solución de docker-compose:

Añadir /etc/localtime:/etc/localtime:roal volumesatributo.

Mira este enlace para ver un ejemplo.

Benyamin Jafari
fuente