Docker containers are a great way to run multiple applications in parallel. However, if you want to use timezones in your containers, you’ll need to do some extra work. First, you’ll need to create a timezone file in your container’s root directory. This file will contain the timezones of your local area. Next, you’ll need to set up a docker-compose file that will include the timezones file. The following code example shows how to do this: version: “1” services: docker-compose up # Set up the timezones docker-compose down # Remove the timezones from the container
Timezones are a common source of confusion when containerizing an application. Will your cron tasks run at the right time? Docker containers don’t inherit the host’s timezone, so you can run into unexpected scheduling issues that wreak havoc with your application.
Here’s the date command running natively on an Ubuntu 20.04 host in the British Summer Time timezone:
And here’s the same command in a container based on an unmodified ubuntu:20.04 image:
The container is using the UTC timezone, creating a one hour difference between the two times.
How Do Linux Timezones Work?
Most Linux distributions use the tzdata package to provide timezone information. When tzdata is installed, you can inspect the current timezone by reading the /etc/timezone file:
You’ll also have an /etc/localtime file. This is a symlink to the correct timezone database for the selected location:
If you change the timezone, using dpkg-reconfigure tzdata, the /etc/localtime symlink gets updated to point to the new database. The output of commands like date will be adjusted to include the active timezone’s offset.
The Problem With Containers
The challenge with containers derives from setting the timezone in the first place. If you think back to when you setup your host, you’d have needed to set the timezone as part of the operating system installation. When you run a new container, it starts immediately though, without any “installation” stage. There’s no opportunity to select an appropriate timezone.
Theoretically, container runtimes could offer automatic inheritance of the host’s timezone. This doesn’t happen as it might lead to unexpected results when deploying to remote environments. It would be easy to overlook that your cron schedule works on your local machine but executes unexpectedly in a managed Kubernetes cluster using UTC time.
Container images ship with a baked-in timezone instead. For most popular images, this will be UTC. Many base images, particularly minimal ones, won’t even include the tzdata package. You’ll have no /etc/timezone or /etc/localtime files.
Adding Timezones to Your Containers
The first part of setting the proper timezone is to make sure tzdata is installed. If your image doesn’t include it, you’ll need to manually add the package as part of your Dockerfile.
When tzdata installs, you usually get an interactive prompt that lets you select the correct timezone from a menu. This is unhelpful when you’re programmatically building Docker containers. Setting the DEBIAN_FRONTEND environment variable suppresses the prompt and defaults the timezone to UTC.
Once you’ve got tzdata into your image, you’re ready to configure the correct timezone for your application. The simplest approach is to set the TZ environment variable to the timezone you want to use:
If you prefer, you can set the TZ variable when you start containers. Pass it as an environment variable to docker run. This lets you override an image’s default timezone, provided it includes the tzdata package.
An alternative to environment variables is the /etc/timezone file. You can write the required timezone as part of your Dockerfile. If you use this method, you must reconfigure tzdata using your package manager. Remember to use non-interactive mode or you’ll receive the graphical timezone prompt again.
Other Techniques
If you want to guarantee timezone synchronization with the host, you can mount your local tzdata files into your containers. You’ll still need tzdata inside the container for this to work correctly.
Although Docker doesn’t provide any built-in support for timezones, that’s not true of all container engines. Podman has a dedicated –tz flag which lets you set the timezone when creating a new container:
Behind the scenes, Podman will mount an appropriate /etc/localtime file for you. The specified timezone will persist for the lifetime of the container.
Podman also lets you set a default timezone for containers created without the –tz flag. Create or edit .config/containers/containers.conf in your home directory. Add a tz setting on a new line in the file:
Podman’s native timezone integration makes it easier to work with than Docker. As Podman’s CLI is compatible with Docker’s, making the switch can be worth considering if you’re frequently working with containers in different timezones.
Summary
Timezones are often overlooked when setting up Docker containers. Most base images default to UTC time which can lead to confusion when the host’s timezone is different.
By installing the tzdata package, your container gains compatibility with all timezones via the TZ environment variable, /etc/timezone, and /etc/localtime. Alternatively, you can sync your host’s timezone by mounting the relevant files into your containers.
Finally, remember that these considerations also apply to hosted Docker services and Kubernetes clusters. Your containers will use UTC time unless instructed otherwise. As long as you can set environment variables, you’ll be able to use TZ to adjust the timezone for your workloads.