How to set the timezone when using the Python Alpine Docker image
When using a Python Alpine Docker image we must add the tzdata package before we can set the timezone.
While writing an application on my Docker platform I hit an unexpected problem, yes, another one ... This was the first time that I had to show the time on a page of a website running on Docker and it appeared that the time was UTC instead of local time. In the code I was just using the normal Python calls to get the time:
import datetime
...
now = datetime.datetime.now()
hour = now.hour
minute = now.minute
I live in The Netherlands and when it was 9:30 the time shown on the web page was 8:30. Why? Searching the internet showed that Docker images based on Ubuntu did not have this problem. It appeared the problem was with the Alpine Docker image, I am using the Python 3.6-alpine image. The size of this image is small but that is because they left out a lot! The solution consists of:
- Adding the tzdata package to the Docker image
- Setting the timezone in the Docker image
Adding the tzdata package is easy. I use Docker multi-stage builds so in the first stage we add tzdata. In the second stage we copy the zoneinfo directory from the first stage to the second stage. In the Dockerfile we also set the timezone:
FROM python:3.6-alpine as base
...
RUN apk add --update \
....
tzdata \
...
FROM python:3.6-alpine
...
COPY --from=base /usr/share/zoneinfo /usr/share/zoneinfo
ENV TZ=Europe/Amsterdam
After these changes the correct time was shown in the page. The only drawback is that this adds another few MBs.
Links / credits
Setting the timezone
https://wiki.alpinelinux.org/wiki/Setting_the_timezone
Using local time in a Golang Docker container built from Scratch
https://medium.com/@mhcbinder/using-local-time-in-a-golang-docker-container-built-from-scratch-2900af02fbaf
Recent
- Hiding database UUID primary keys of your web application
- Don't Repeat Yourself (DRY) with Jinja2
- SQLAlchemy, PostgreSQL, maximum number of rows per user
- Show the values in SQLAlchemy dynamic filters
- Secure data transfer with Public Key encryption and pyNaCl
- rqlite: a high-availability and distributed SQLite alternative
Most viewed
- Using Python's pyOpenSSL to verify SSL certificates downloaded from a host
- Using UUIDs instead of Integer Autoincrement Primary Keys with SQLAlchemy and MariaDb
- Connect to a service on a Docker host from a Docker container
- Using PyInstaller and Cython to create a Python executable
- SQLAlchemy: Using Cascade Deletes to delete related objects
- Flask RESTful API request parameter validation with Marshmallow schemas