Hora y zona horaria del contenedor Docker (no reflejará los cambios)

136

¿De dónde obtienen los contenedores Docker su información de tiempo? He creado algunos contenedores a partir del ubuntu básico: imagen de confianza, y cuando lo ejecuto y solicito 'fecha', obtengo la hora UTC.

Por un tiempo, resolví esto haciendo lo siguiente en mi Dockerfile:

RUN sudo echo "America/Los_Angeles" > /etc/timezone

Sin embargo, por alguna razón eso dejó de funcionar. Al buscar en línea, vi lo siguiente sugerido:

docker run -v /etc/timezone:/etc/timezone [image-name]

¡Sin embargo, ambos métodos establecen correctamente la zona horaria!

$ cat /etc/timezone
America/Los_Angeles
$ date
Tue Apr 14 23:46:51 UTC 2015

Alguien sabe lo que da?

Chockomonkey
fuente
3
Si usa Alpine, tzdataprimero necesita instalar , vea aquí github.com/gliderlabs/docker-alpine/issues/136
Belter
1
FYI. . . Deseo establecer la zona horaria del contenedor en el tiempo de ejecución de docker, no en el tiempo de compilación de docker / dockerfile. Usando -v /etc/localtime:/etc/localtime:ro(CentOS) tipo de trabajos. La fecha de la línea de comandos del contenedor interno devuelve la fecha en el formato de zona horaria esperado. PERO jenkins corriendo en un contenedor piensa que la zona horaria es UTC. ¿Por qué? / etc / localtime es un enlace simbólico a ../usr/share/zoneinfo/UTC en el contenedor integrado. El contenido del archivo UTC en el contenedor ahora es la nueva zona horaria. Pero jenkins (y quizás otro software basado en Java) usa el nombre del enlace simbólico que todavía es "UTC". Buscando una solución. . .
Gaoithe
1
Necesita 2 cosas, 1. cuando se crea el contenedor, use un script de inicio para establecer / etc / localtime symlink y / etc / timezone y 2. para jenkins timezone se toma de dos opciones de Java, estas opciones deben pasarse al script de inicio que comienza el proceso de jenkins. por ejemplo, "-Dorg.apache.commons.jelly.tags.fmt.timeZone = America / New_York -Duser.timezone = America / New_York". Disculpas, esto es específico de jenkins, pero espero que sea útil para otros usuarios de jenkins.
Gaoithe

Respuestas:

210

El secreto aquí es que dpkg-reconfigure tzdatasimplemente crea /etc/localtimecomo una copia, un enlace duro o un enlace simbólico (se prefiere un enlace simbólico) a un archivo /usr/share/zoneinfo. Por lo tanto, es posible hacer esto completamente desde su Dockerfile. Considerar:

ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

Y como beneficio adicional, TZ también se configurará correctamente en el contenedor.

Esto también es independiente de la distribución, por lo que funciona con casi cualquier Linux.

Nota: si está utilizando una imagen alpina, debe instalar la tzdataprimera. (ver este tema aquí )

Se ve como esto:

RUN apk add --no-cache tzdata
ENV TZ America/Los_Angeles
Michael Hampton
fuente
20
Lista de nombres TZ: en.wikipedia.org/wiki/List_of_tz_database_time_zones
BillyTom
55
Con Ubuntu: 16.04 (y tal vez otras versiones) necesita tener tzdatainstalado el paquete para que esto funcione.
Opsse
66
¿Soy el único que piensa que no es muy inteligente codificar una zona horaria en el Dockerfile?
Wolfgang el
1
@Wolfgang Este es un ejemplo. Puede proporcionarlo de cualquier otra manera que normalmente proporcionaría variables de entorno, como la línea de comando, docker-compose.yml, etc.
Michael Hampton
Me di cuenta de que, al menos para las imágenes basadas en Alpine, basta con configurar la TZvariable. No tuve que configurar los enlaces simbólicos ni nada más.
code_dredd
59

Por lo general, es suficiente establecer una variable de entorno en el contenedor acoplable, de esta manera:

docker run -e TZ=Europe/Amsterdam debian:jessie date

Por supuesto, esto funcionaría también con docker-compose.

Victor Klos
fuente
2
Esta parece ser la forma más elegante. Tenga cuidado de que alguna imagen base, como ubuntu:16.04, no tenga el tzdatapaquete que debe agregarse en Dockerfile.
Julien Fastré
1
+1 - Estoy de acuerdo con Julien; Este parece ser el enfoque más elegante para establecer zonas horarias en tiempo de ejecución. Esto funciona bien con CentOS. La imagen alpina requiere la instalación del paquete 'tzdata', que se prefiere a las configuraciones de codificación en el momento de la compilación, a menos que no se pueda tolerar la carga útil adicional de la imagen de 3MB :)
Frelling
Esto parece bueno pero parece no funcionar para mí (con CentOS 7.5.1804 y tzdata-2018e-3.el7.noarch)? cara triste
gaoithe
22

El montaje /etc/localtimeen la imagen, por lo que está sincronizado, host -ves el más popular.

Pero vea el problema 12084 :

no es correcto porque no funciona cuando el software requiere /etc/timezoneque se configure el archivo .
De esa manera que está usando lo deja como el valor predeterminado etc/UTC.

He determinado que en realidad no hay una manera elegante e infalible de configurar la zona horaria dentro de un contenedor acoplable.
Así que finalmente nos hemos decidido por esta solución:

Archivo acoplable de la aplicación:

# Relocate the timezone file
RUN mkdir -p /config/etc && mv /etc/timezone /config/etc/ && ln -s /config/etc/timezone /etc/

Script de punto de entrada de la aplicación:

# Set timezone as specified in /config/etc/timezone
dpkg-reconfigure -f noninteractive tzdata

/configArchivo docker de volumen de datos , localizado en un país o región específicos:

# Set the time zone
RUN echo "Europe/London" > /config/etc/timezone

... no es elegante porque involucra 3 archivos separados y se vuelve a crear /etc/localtimeen cada inicio de contenedor de tiempo de ejecución. Lo cual es bastante derrochador.

Sin embargo, funciona correctamente y logra con éxito la separación entre la imagen de la aplicación base y cada configuración localizada por país.
En 3 líneas de código.

VonC
fuente
1
Para mí, fue: RUN echo "Europe/London" > /etc/timezone
jpmottin
@jpmottin ¿Entonces un poco como en serverfault.com/a/856593/783 ?
VonC
18

Puede agregar sus archivos locales (/ etc / timezone y / etc / localtime) como volumen en su contenedor acoplable.

Actualiza tu docker-compose.ymlcon las siguientes líneas.

volumes:
    - "/etc/timezone:/etc/timezone:ro"
    - "/etc/localtime:/etc/localtime:ro"

Ahora el tiempo del contenedor es el mismo que en su host

gracias
fuente
Si su host de distribución en CentOS ingrese el comando echo "Europe/Paris" > /etc/timezoneantes de reiniciar el contenedor.
CrazyMax
¿Funciona esto en el host de MacOS?
Redsandro
No funciona en MAC
Marcello de Sales
Esto solía funcionar en MacOS, pero lo intenté nuevamente después de mucho tiempo y obtengo lo siguiente. No estoy seguro si High Sierra o un cambio de Docker causó esto: "docker: Respuesta de error del demonio: Monturas denegadas: La ruta / etc / localtime no se comparte desde OS X y Docker no la conoce. Puede configurar rutas compartidas desde Docker - > Preferencias ... -> Compartir archivos. Consulte docs.docker.com/docker-for-mac/osxfs/#namespaces para obtener más información ".
gae123
1
Esto dañará su db de zoneinfo ya que / etc / localtime es un enlace simbólico (por lo tanto, / usr / share / zoneinfo / Some / Thing es probable que se monte como / usr / share / zoneinfo / UTC dentro del contenedor). Sin mencionar que mezclarías el archivo db del host con el del contenedor.
ionelmc
12

En ubuntu 16.04 imagen hay error. La solución fue

    ENV TZ 'Europe/Tallinn'
    RUN echo $TZ > /etc/timezone && \
    apt-get update && apt-get install -y tzdata && \
    rm /etc/localtime && \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
    dpkg-reconfigure -f noninteractive tzdata && \
    apt-get clean
QWERTY
fuente
1
En serio ... ¡esta es la única solución que funcionó!
Gerrat
1
También tuve que hacer esto: parece que tzdata ya no está en algunas distribuciones por defecto.
Peter
4

Si está utilizando la imagen acoplable basada en ubuntu:

# Change the docker default timezone from UTC to SGT
echo "Asia/Singapore" > /etc/timezone
dpkg-reconfigure tzdata
date
Xianlin
fuente
3

Gracias a VonC por la información y el enlace al problema. Esto parece un desastre tan complicado, así que hice algunas pruebas sobre mi propia idea de cómo resolver esto y parece funcionar muy bien.

>docker run -it ubuntu:trusty /bin/bash
#dpkg-reconfigure tzdata

(siga las indicaciones para seleccionar mi zona horaria)

>docker commit [container-id] chocko/ubuntu:local

Luego actualicé mis Dockerfiles para reflejar esto:

FROM chocko/ubuntu:local

Debe haber algo mal con esto porque parece demasiado fácil pasarlo por alto ... ¿O es esto aceptable?

Chockomonkey
fuente
Esto también es lo que probé, pero la zona horaria todavía se restablece después exitdel contenedor. Esto está en Debian.
Mike Chamberlain
@ MikeChamberlain, ¿probaste la respuesta aceptada de Michael Hampton anterior? No lo he implementado yo mismo, pero creo que es el camino a seguir teniendo en cuenta los votos positivos que ha recibido.
Chockomonkey
2

Agregué mis dos centavos aquí, porque he probado varios de estos pero ninguno funcionó en imágenes alpinas.

Sin embargo, esto hizo el truco:

ENV TZ=America/Toronto
RUN apk update
RUN apk upgrade
RUN apk add ca-certificates && update-ca-certificates
RUN apk add --update tzdata
RUN rm -rf /var/cache/apk/*

[ Fuente ]

Alfa
fuente
1

Una forma más genérica de establecer la zona horaria en docker runargumentos:

-e TZ=`ls -la /etc/localtime | cut -d/ -f8-9`

O para reutilizar:

function GET_TZ () {
    ls -la /etc/localtime | cut -d/ -f8-9
}

...
-e TZ=`GET_TZ`
Mugen
fuente
no ayuda si su imagen base es alpina (5 MB) que no tiene instalada la "tzdata"
max4ever