Infraestructura como código vs gestión de configuración vs aprovisionamiento de infraestructura

Solucionar problemas de hora y zona horaria en Docker

hora y zona horaria en Docker

Vamos a ver como solucionar la hora y zona horaria en Docker, pero antes de empezar vamos a ver cómo se ajusta en un SO Linux, ya que son los mismos métodos que utilizaremos después para sincronizar los contenedores.

Lo primero, vamos a ver la hora actual:

date

dissabte, 17 de febrer de 2024, 08:31:33 CET

(Os saldrá en el idioma que tengáis configurado el SO)

Aquí hay dos cosas importantes:

  • La zona horaria, aquí es CET por Central European Time, en resumen es la hora de Madrid.
  • La hora en sí, que puede estar bien sincronizada o no. Puedes compararlo por ejemplo en world time server.

Para cambiar la zona horaria en Linux, es bastante sencillo. Sólo tienes que ejecutar este comando y seguir las instrucciones dadas:

Para sincronizar el reloj con la hora correcta, utilizamos un servicio llamado NTP, por Network Time Protocol. Asegurémonos de que está correctamente instalado y habilitado en systemd. Adapta estos comandos a tu sistema operativo, aquí para Debian 10:

apt install ntp
systemctl enable ntp
systemctl start ntp

No es necesario instalar ntp en los contenedores Docker, ya que su reloj se basa en el del host.

Bien, ahora que hemos visto las bases, necesitamos asegurarnos de que nuestros contenedores Docker tienen su reloj correctamente sincronizado, están en la zona horaria correcta, y dejan de tener problemas de interacción debido a su fecha y hora.

Usar la configuración de la máquina anfitriona

Esta es la solución más sencilla para configurar la hora de tus contenedores: utilizar la hora y la zona horaria de la máquina anfitriona, la que aloja el servicio Docker.

Por otro lado, esta solución sólo funciona si tienes el control del host, y no es aplicable si envías tus contenedores a alguna solución cloud.

Para ello, montaremos dos volúmenes en modo sólo lectura en los ficheros de configuración del reloj del host de nuestros contenedores.

En el comando docker run, añadimos dos volúmenes:

docker run -d
   -v /etc/timezone:/etc/timezone:ro \  
   -v /etc/localtime:/etc/localtime:ro \
   [...]

O con un archivo docker-compose.yml:

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

Establecer la zona horaria de los contenedores

Si el método anterior no se puede aplicar, ya sea porque no se tiene control sobre el host, o si es necesario tener diferentes zonas horarias entre diferentes contenedores, entonces es necesario poder establecer la zona horaria directamente en la imagen Docker.

En primer lugar, para Alpine Linux, el paquete tzdata no está instalado por defecto, por lo que es necesario añadirlo manualmente en tu Dockerfile:

RUN apk add --no-cache tzdata

Para cambiar la zona horaria de nuestros contenedores Linux, en lugar de usar dpkg-reconfigure que es interactivo, usaremos un poco de sutileza y haremos la manipulación manualmente en nuestro Dockerfile.

Lo que hace este comando es por un lado actualizar el fichero /etc/timezone con la zona horaria correcta, pero también crear una copia del binario asociado a la zona horaria en /etc/localtime. Hagamos esto

FROM alpine  

ENV TZ=Europa/París 

EJECUTAR apk add --no-cache tzdata
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

Este método funciona en todas partes, y le permite definir directamente la variable de entorno TZ que se detalla en la siguiente sección.

Puede probar su archivo esto muy fácilmente con el comando :

docker build -t tzalpine . && docker run -it --rm tzalpine
$ date
# la fecha debe tener la zona horaria correcta aquí

Ahora el sistema operativo está actualizado dentro de los contenedores, sea cual sea la configuración o el entorno. Todo lo que queda por hacer es asegurarse de que los diferentes programas tienen en cuenta la zona horaria.

Variable de entorno TZ

Buena parte de los lenguajes de programación y/o frameworks modernos dependen de la misma variable de entorno: TZ. Es el caso, por ejemplo, para establecer la hora en Python y NodeJS.

Definiéndola, y junto con la del sistema operativo, deberías cubrir una buena mayoría de casos de uso.

Ten cuidado, sin embargo, esta variable puede ser sobrecargada, si es la elección de los desarrolladores. En estos casos, suele haber una opción disponible en la configuración de la herramienta que estés utilizando, o a veces en su interfaz de usuario.

Sólo tienes que configurarlo cuando lances tu contenedor :

docker run -d
   -e TZ=Europa/París \
   [...]

O en docker-compose.yml:

services:
  service_name:
    environment:
      - TZ=Europa/París

Configuración PHP

Obviamente, PHP utiliza una forma diferente y no tiene en cuenta la variable de entorno TZ.

Para establecer la hora en PHP, es necesario establecer el valor del parámetro date.timezone en el archivo php.ini.

[Date]
; Cuidado de quitar el punto y coma, que significa que es un comentario.
date.timezone = Europa/París

Conclusión

Ya está, deberíamos haber cubierto todo el tema. He actualizado la mayoría de mis contenedores para tener en cuenta estos cambios, y todo parece funcionar sin problemas.

Si alguna vez te encuentras con casos en los que las manipulaciones descritas en este artículo no son suficientes, no dudes en hacérmelo saber – actualizaré esta guía.

Recursos:

Más apuntes

Invítame a un café con bitcoins:
1QESjZDPxWtZ9sj3v5tvgfFn3ks13AxWVZ

Bitcoins para café
También puedes invitarme a algo para mojar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Rellena este campo
Rellena este campo
Por favor, introduce una dirección de correo electrónico válida.
Tienes que aprobar los términos para continuar