Make writing a habit together! This is the 10th day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.
Container deployment is now very mature, and many of our services use container deployment, which is very easy to update and restore. However, one of the more troublesome issues is time zone handling, which is usually handled by injecting TZ environment variables. However, this kind of handling does not work in Django.
Timezone related configurations in Django
In Django’s settings.py configuration file, there are two parameters that depend on time and time zone: TIME_ZONE and USE_TZ. We expected Django to get the local time correctly when configured in settings.py, but it doesn’t. Let’s take a look at what these two Settings do.
USE_TZ=True
If USE_TZ is set to True, Django uses the system’s default timezone setting. The TIME_ZONE setting is essentially invalid, meaning it doesn’t work with or without a TIME_ZONE setting.
USE_TZ=False
If USE_TZ is set to False
- TIME_ZONE set to None Django still uses the default time zone
- If TIME_ZONE is set to another time zone
-
- On Windows, the TIME_ZONE setting is useless, and Django uses the native time
- For example, if USE_TZ = False, TIME_ZONE = ‘Asia/Shanghai’ is set, Shanghai UTC is used.
At this point, you might think the time is up, but it’s not, and we need to worry about the system time zone Settings.
The Settings of the middle area in the Linux container
USE_TZ = False, TIME_ZONE = ‘Asia/Shanghai’
The TZ=Asia/Shanghai environment variable is not injected
Enter the container to view the container time and time zone
The system time displays the UTC time zone, which is 08:15, 8 hours off
Go to your Django environment and check the time and time zone
Python manage.py shell from datetime import datetime.now() # datetime.datetime(2021, 10, 8, 8, 24, 8, 289230) from django.utils import timezone timezone.get_current_timezone_name() # output 'Asia/Shanghai'Copy the code
Inject the environment variable TZ=Asia/Shanghai
Enter the container to view the time and time zone
The system time is displayed as the Asia time zone, but the time is still UTC time. The actual local time is not displayed
Go to your Django environment and check the time and time zone
Python manage.py shell from datetime import datetime.now() # datetime.datetime(2021, 10, 8, 8, 24, 8, 289230) from django.utils import timezone timezone.get_current_timezone_name() # output 'Asia/Shanghai'Copy the code
As you can see, although the time zone has changed, the time is still UTC time, both in the container itself and in Django
To change the time zone in Linux, you need to modify the /etc/localtime file
Change the Time zone of a Linux container
The common practice is to copy the host’s /etc/localtime file to the container’s /etc/localtime file, but we found that the /etc/localtime file is actually a soft connection. The actual file is: /usr/share/zoneinfo/Asia/Shanghai
docker cp /usr/share/zoneinfo/Asia/Shanghai test:/etc/localtime
Copy the code
Without injecting the container with the TZ=Asia/Shanghai environment variable, we log in to the container and find that the system time of the container has been correctly retrieved to the local time and time zone
If the TZ=Asia/Shanghai environment variable is injected, even if the /etc/localtime file is replaced, only the time zone is changed and the time is still UTC
Go to your Django environment and check the time
Python manage.py shell from datetime import datetime.now() # datetime.datetime(2021, 10, 8, 8, 43, 43, 754698).Copy the code
The time in your Django environment is still UTC time, but the time in your Linux environment is still UTC time. Many people get a little crazy when they think the USE_TZ and TIME_ZONE Settings in settings.py are wrong. The reason is that the datetime library looks for the Asia/Shanghai file in /usr/share/zoneinfo/, which is not included in our image, so Django uses UTC. The solution is very simple: create /usr/share/zoneinfo/asia and copy files to this directory
# in containers (e.g., not the directory does not exist) mkdir -p/usr/share/zoneinfo/Asia # outside the container docker cp/usr/share/zoneinfo/Asia/Shanghai test:/usr/share/zoneinfo/Asia/ShanghaiCopy the code
Then log into the container and check the time in the Django environment
Python manage.py shell from datetime import datetime.now() # datetime.datetime(2021, 10, 8, 16, 49, 32, 57)Copy the code
Now the time is exactly right.
conclusion
For the container time zone problem, you are advised to install and set /etc/localtime during container creation. For example, add the following statement to the dockerfile
ADD /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
RUN ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
Copy the code
This way our container does not need to worry about time zones when it is started. If the container is already made, mount the time zone file at startup
docker run -d -v /etc/localtime:/etc/localtime -v /usr/share/zoneinfo/Asia/Shanghai:/usr/share/zoneinfo/Asia/Shanghai imageName
Copy the code
This way is more troublesome. There is also a case that we now encounter, the service has been online, find the time problem, manually copy the two files into the container, and then restart the container
docker cp /usr/share/zoneinfo/Asia/Shanghai test:/etc/localtime
docker cp /usr/share/zoneinfo/Asia/Shanghai test:/usr/share/zoneinfo/Asia/Shanghai
docker restart test
Copy the code