DazDylz
DazDylz

Reputation: 1096

Running python script inside Docker container wrong timezone

I'm running a script inside a Docker container (python:3.6) and it shows me the wrong time in the logs. When using the following python code in the python console(inside the container) it gives me the correct timezone.

import datetime
datetime.datetime.now()
datetime.datetime(2019, 8, 3, 17, 26, 25, 662809)

Also, when running the date command inside the container, it gives the correct timezone.

However, I have this print statement in my script:

print("Updating....", datetime.datetime.now())

This however, gives me the wrong timezone (2 hours off).

enter image description here

This is my docker-compose.yml:

version: '3'
services:
  app:
    container_name: app
    build: .
    restart: unless-stopped
    environment:
      TZ: Europe/Amsterdam
    depends_on:
      - db
  db:
    container_name: db
    image: mariadb
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: x
      MYSQL_DATABASE: x
      MYSQL_USER: x
      MYSQL_PASSWORD: x
      TZ: Europe/Amsterdam
    volumes:
      - /volumes/x/db:/var/lib/mysql

This is my crontab file (runs inside the app container)

CRON_TZ=Europe/Amsterdam

*/5 * * * * cd /usr/src/app && /usr/local/bin/python3.6 -u -m x > /proc/1/fd/1 2>/proc/1/fd/2
0,30 * * * * cd /usr/src/app && /usr/local/bin/python3.6 -u -m x > /proc/1/fd/1 2>/proc/1/fd/2
5 0 * * * cd /usr/src/app && /usr/local/bin/python3.6 -u -m x > /proc/1/fd/1 2>/proc/1/fd/2

I tried setting the timezone in docker-compose.yml, that worked for date command and the python console. I tried setting the timezone inside the crontab file, but it still doesn't show the correct timezone in the script.

How do I set the timezone for Python inside a crontab, so that the logs do have the correct timezone? Also, I need to run a script at 00:05 not 22:05, does that work now?

Upvotes: 14

Views: 15619

Answers (8)

chethan
chethan

Reputation: 305

This may not be the expected answer, but it could help if someone is making a common rookie mistake.

In my case, I was setting an environment variable in the docker-compose file like this:

environment:
   - TZ="America/New_York" 

However, Docker processes this differently and outputs something like:

TZ: '"America/New_York"'

This extra set of quotes caused issues.

To fix it, simply remove the double quotes and use:

environment:
   - TZ=America/New_York

This ensures Docker assigns the correct value without unnecessary quotes. Hope this helps! 🚀

Upvotes: 1

Asclepius
Asclepius

Reputation: 63504

For most users, setting the environment variable as below for your Python container in your docker-compose.yml should be sufficient and effective:

   environment:
      TZ: America/New_York

And iff your container is defined via devcontainer.json instead, similarly add this to that file:

    "containerEnv": {
        "TZ": "America/New_York"
    },

This was tested with CPython 3.8. Remember to recreate and not merely restart your container after setting it.


Credit: comment by Harsh Nagarkar.

Upvotes: 7

KingOtto
KingOtto

Reputation: 1503

Tell your docker container which time zone it should use, while building the image.

For example, with a dockerfile, install tzdata and set the ENV var TZ. More explanation, and instructions for docker Engine and Compose see here.

FROM ubuntu:16.04
 
# tzdata for timzone
RUN apt-get update -y
RUN apt-get install -y tzdata
 
# timezone env with default
ENV TZ=America/Bogota

Upvotes: 0

dragsu
dragsu

Reputation: 129

I solved this by passing TZ environment variable to the container and providing a converter function to the logging.Formatter.converter as specified in https://docs.python.org/3/library/logging.html.

According to https://www.redhat.com/sysadmin/tick-tock-container-time, "Usually, the time zone is set to the location where the image or base image was built, or to UTC±00:00". Therefore, I passed timezone to podman container using --tz=<time-zone> parameter. If it is a podman play kube you can pass TZ value as an environment variable as below. This will set the timezone of the container.

....
spec:
  containers:
  - name: python
    env:
    -name: TZ
     value: "Asia/Colombo"
....

Then I modified my python code to assign a converter function. Since I wanted the container's local time (i.e "Asia/Colombo") I assigned below to the converter.

logging.Formatter.converter = time.localtime

Upvotes: 0

Tim Chaubet
Tim Chaubet

Reputation: 726

What is extremely strange, is that I have a python script writing the time to a log (among other things).

import time 
print(time.strftime("%c"))

will return 'Tue Mar 15 14:25:31 2022' for example. If I connect to the container and start python3 and do the commands manually, it returns 'Tue Mar 15 15:25:31 2022'

the container has the timezone set as TZ parameter and if I run 'date' from the shell in the container, the time is indeed the intended localtime. If I omit the TZ, it's reverts to UTC time.

I was forced to pass the TZ as a parameter to the python script and process it.

import time
import os
os.environ['TZ'] = a
time.tzset()
print(time.strftime("%c"))

where 'a' is that passed parameter

It's quite clear in my github project: https://github.com/TrueOsiris/docker-godaddypy as this only has a Dockerfile, one bash script and one python script.

Upvotes: 0

Nick Rundle
Nick Rundle

Reputation: 639

If you are trying to sync the timezone in the container with the host machine, you can map the timezone setting from the host. I've done this successfully with the following volume:

-v /etc/localtime:/etc/localtime

Or in your docker-compose.yml file:

volumes:
    - /etc/localtime:/etc/localtime

Upvotes: 10

kederrac
kederrac

Reputation: 17322

you can try to use time.tzset() in the beginning of your code or you can use :

import detetime
import pytz

datetime.now(tz=pytz.timezone('Europe/Amsterdam'))

# or datetime.now(tz=pytz.timezone(os.environ.get('TZ'))

also, check this

Upvotes: 0

Neil
Neil

Reputation: 3301

I got burned by this same problem a while back. Unfortunately, I don't remember the exact fix that ended up working. But here are some pointers:

1) The problem is with Docker, not Python or datetime or anything else. Docker containers struggle to know what the time is. What you want to search for is ways to sync up time inside a container with host.

2) There are many suggested ways of handling time in containers, but I remember them all being work-arounds of sorts. Last I checked there was no clear solution.

3) I would HIGHLY recommend that you do not put cron jobs inside containers. If you need things to run at a certain time, put the crons ON THE HOST, and have them spin up the containers when needed. This is much more reliable.

Upvotes: 3

Related Questions