The simplest way is to add -e option or ENV directive to set TZ environment variable, because debian, ubuntu, etc. already included tzdata.
Someone recommends to mount the timezone from the host:
$ docker run -it --rm \
-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone \
debian:bullseye date
Mon Jul 3 19:41:30 CST 2023
This may work, but it is dangerous. Because /etc/localtime is actually a symbol link (in some newer distributions), and Docker by default follow the symbol link. As a result, the timezone data (instead of the symbol link it self) is overridden silently.
$ docker run -it --rm debian:bullseye \
sh -c 'ls -l /etc/localtime && tail -n1 /etc/localtime'
lrwxrwxrwx 1 root root 27 Mar 20 00:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
UTC0
$ docker run -it --rm -v /etc/localtime:/etc/localtime debian:bullseye \
sh -c 'ls -l /etc/localtime && tail -n1 /etc/localtime'
lrwxrwxrwx 1 root root 27 Mar 20 08:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
CST-8
That is why this does not work:
$ docker run -it --rm \
-v /usr/share/zoneinfo:/usr/share/zoneinfo \
-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone \
debian:bullseye date
Mon Jul 3 11:41:59 UTC 2023