Eight hours off inside a container
date in the container returns UTC even though -e TZ=Asia/Shanghai was passed. Two usual reasons.
The image has no /usr/share/zoneinfo — Alpine, distroless and scratch all lack it. TZ is just a pointer, and a missing target falls back to UTC. Install tzdata or mount the host file:
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
Or the program ignores TZ and reads /etc/localtime. Java is the classic case and also wants -Duser.timezone=Asia/Shanghai.
Keep system time and display timezone apart: the kernel clock is UTC, and setting a zone changes display, not a clock that has already drifted.