Horário e fuso horário do contêiner do Docker (não refletirá alterações)

135

Onde os contêineres do Docker obtêm suas informações de horário? Criei alguns contêineres a partir da imagem básica do ubuntu: trusty, e quando executo e solicito 'date', recebo a hora UTC.

Por um tempo, eu resolvi isso fazendo o seguinte no meu Dockerfile:

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

No entanto, por algum motivo, isso parou de funcionar. Pesquisando online, vi o abaixo sugerido:

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

Ambos os métodos definem corretamente o fuso horário!

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

Alguém sabe o que dá?

Chockomonkey
fonte
3
Se você usar Alpine, precisará instalar tzdataprimeiro, consulte aqui github.com/gliderlabs/docker-alpine/issues/136
Belter
1
PARA SUA INFORMAÇÃO . . . Desejo definir o fuso horário do contêiner no tempo de execução do docker e não no tempo do builder / arquivo do docker. Usando -v /etc/localtime:/etc/localtime:ro(CentOS) meio que funciona. A data da linha de comando do contêiner interno retorna a data no formato de fuso horário esperado. Mas o jenkins executado no contêiner acha que o fuso horário é UTC. Por quê? / etc / localtime é um link simbólico para ../usr/share/zoneinfo/UTC no contêiner criado. O conteúdo do arquivo UTC no contêiner agora é o novo fuso horário. Mas os jenkins (e talvez outro software baseado em java) usam o nome do link simbólico que ainda é "UTC". Procurando por solução. . .
gaoithe 21/01
1
Precisa de 2 coisas, 1. quando o contêiner for criado, use um script init para definir / etc / localtime symlink e / etc / timezone e 2. para jenkins, o fuso horário é retirado de duas opções java, essas opções precisam ser passadas para o script init que inicia o processo de jenkins. por exemplo "-Dorg.apache.commons.jelly.tags.fmt.timeZone = America / New_York -Duser.timezone = America / New_York". Desculpas, isso é específico da jenkins, mas espero que seja útil para alguns outros usuários da jenkins.
gaoithe 22/01

Respostas:

208

O segredo aqui é que dpkg-reconfigure tzdatasimplesmente cria /etc/localtimecomo uma cópia, hardlink ou link simbólico (um link simbólico é preferido) para um arquivo /usr/share/zoneinfo. Portanto, é possível fazer isso totalmente no seu Dockerfile. Considerar:

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

E como bônus, o TZ também será definido corretamente no contêiner.

Isso também é independente de distribuição, por isso funciona com praticamente qualquer Linux.

Nota: se você estiver usando uma imagem alpina, precisará instalar a tzdataprimeira. (veja esta edição aqui )

Se parece com isso:

RUN apk add --no-cache tzdata
ENV TZ America/Los_Angeles
Michael Hampton
fonte
20
Lista de nomes de TZ: en.wikipedia.org/wiki/List_of_tz_database_time_zones
BillyTom
5
Com o Ubuntu: 16.04 (e talvez outra versão), você precisa ter o tzdatapacote instalado para fazer isso funcionar.
Opsse 23/10
5
Eu sou o único que acha que não é muito inteligente codificar um fuso horário no Dockerfile?
Wolfgang
1
@ Wolfgang Este é um exemplo. Você pode fornecê-la de qualquer outra forma você normalmente fornecer variáveis de ambiente, como a linha de comando, docker-compose.yml, etc.
Michael Hampton
Percebi que, pelo menos para imagens baseadas nos Alpes, basta definir a TZvariável. Não precisei configurar os links simbólicos ou qualquer outra coisa.
code_dredd 21/06
58

Geralmente, é suficiente definir uma variável de ambiente no contêiner do docker, da seguinte maneira:

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

Claro que isso funcionaria também com docker-compose.

Victor Klos
fonte
2
Esta parece ser a maneira mais elegante. Certifique-se de que alguma imagem base, como ubuntu:16.04, não tenha o tzdatapacote que deve ser adicionado ao Dockerfile.
Julien Fastré 19/05
1
+1 - eu concordo com Julien; essa parece ser a abordagem mais elegante para definir fusos horários em tempo de execução. Isso funciona bem com o CentOS. Imagem Alpine requer instalação de pacote 'tzdata', que é preferido sobre configurações harcoding em tempo de compilação, a menos que a carga imagem 3MB adicional não pode ser tolerada :)
Frelling
Isso parece bom, mas parece não funcionar para mim (com o CentOS 7.5.1804 e o tzdata-2018e-3.el7.noarch)? cara triste
gaoithe 21/01
22

A montagem /etc/localtimena imagem, para que ela esteja sincronizada, host -vé a mais popular.

Mas veja a edição 12084 :

não está correto porque não funciona quando o software exige que o arquivo /etc/timezoneseja definido.
Dessa forma, você está usando o deixa como o valor padrão etc/UTC.

Concluí que, na verdade, não há uma maneira elegante e infalível de definir o fuso horário dentro de um contêiner de estivador.
Então finalmente decidimos esta solução:

Arquivo docker do aplicativo:

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

Script do ponto de entrada do aplicativo:

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

/configArquivo de encaixe de volume de dados , localizado em um país ou região específico:

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

... não é elegante porque envolve 3 arquivos separados e é recriado /etc/localtimea cada início do contêiner de tempo de execução. O que é um grande desperdício.

No entanto, ele funciona corretamente e consegue com êxito a separação entre a imagem do aplicativo base e cada configuração localizada por país.
Em 3 linhas de código.

VonC
fonte
1
Para mim, foi: RUN echo "Europe/London" > /etc/timezone
jpmottin 19/10/10
@jpmottin Então, um pouco como em serverfault.com/a/856593/783 então?
VonC 19/10/19
18

Você pode adicionar seus arquivos locais (/ etc / fuso horário e / etc / localtime) como volume no seu docker-container.

Atualize seu docker-compose.ymlcom as seguintes linhas.

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

Agora, o tempo do contêiner é o mesmo do seu host

do que
fonte
Se seu host de distribuição no CentOS, digite o comando echo "Europe/Paris" > /etc/timezoneantes de reiniciar o contêiner.
CrazyMax
Isso funciona no host do MacOS?
Redsandro 26/10
Não funciona no MAC
Marcello de Sales
Isso costumava funcionar no MacOS, mas eu tentei novamente depois de muito tempo e recebo o seguinte. Não tenho certeza se o High Sierra ou uma alteração no docker causou o seguinte: "docker: resposta de erro do daemon: montagens negadas: o caminho / etc / localtime não é compartilhado no OS X e não é conhecido pelo Docker. Você pode configurar caminhos compartilhados no Docker - > Preferências ... -> Compartilhamento de arquivos. Consulte docs.docker.com/docker-for-mac/osxfs/#namespaces para obter mais informações. "
precisa saber é
1
Isso corromperá o seu zoneinfo db, pois / etc / localtime é um link simbólico (portanto, / usr / share / zoneinfo / Some / Thing provavelmente será montado como / usr / share / zoneinfo / UTC dentro do contêiner). Sem mencionar que você misturaria o arquivo db do host com o do contêiner.
Ionelmc
12

Na imagem do ubuntu 16.04 há um bug. A solução foi

    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
fonte
1
Sério ... essa é a única solução que funcionou!
Gerrat 30/06
1
Também tive que fazer isso - parece que o tzdata não está mais em algumas distros por padrão.
Peter
4

se você estiver usando a imagem do Docker com base em ubuntu:

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

Obrigado a VonC pelas informações e link para o problema. Isso parece uma bagunça tão complicada, então eu testei minha própria idéia de como resolver isso e parece funcionar muito bem.

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

(siga as instruções para selecionar meu fuso horário)

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

Em seguida, atualizei meus Dockerfiles para refletir isso:

FROM chocko/ubuntu:local

Deve haver algo errado com isso, porque parece fácil demais ser esquecido ... Ou isso é aceitável?

Chockomonkey
fonte
Também foi o que tentei, mas o fuso horário ainda se redefine após exito contêiner. Isso está no Debian.
Mike Chamberlain
@ MikeChamberlain, por acaso você tentou a resposta aceita por Michael Hampton acima? Eu não o implementei, mas acho que é o caminho a percorrer, considerando as votações recebidas.
Chockomonkey
2

Adicionando meus dois centavos aqui, porque tentei vários deles, mas nenhum funcionou em imagens baseadas em alpinos.

No entanto, isso fez o truque:

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/*

[ Fonte ]

Alfa
fonte
1

Uma maneira mais genérica de definir o fuso horário nos docker runargumentos:

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

Ou para reutilização:

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

...
-e TZ=`GET_TZ`
Mugen
fonte
não ajuda se sua imagem base é alpina (5 MB) que não possui o "tzdata" instalado
max4ever