Quick fix
# Timezone: works directly on Debian-family/python images; use POSIX form on tzdata-less images
docker run -e TZ=Asia/Shanghai your-image date # when the image ships zoneinfo
docker run -e TZ=UTC-8 your-image date # no tzdata (UTC-8 = UTC+8, inverted sign)
# Garbled text: force UTF-8 output inside the container
docker run -e PYTHONUTF8=1 -e PYTHONIOENCODING=utf-8 your-python-image ...
# Same in compose
services:
app:
image: your-image
environment:
- TZ=Asia/Shanghai
- PYTHONUTF8=1
- PYTHONIOENCODING=utf-8
What you will run into
Inside the container, date shows UTC while the host is 8 hours ahead; you added -e TZ=Asia/Shanghai to compose/docker run exactly like the tutorial says, restarted, and it is still UTC.
Or your program prints Chinese and dies with UnicodeEncodeError: 'ascii' codec can't encode characters, and Chinese in logs comes out as mojibake/question marks.
Containers default to UTC and the C locale, and slim base images often have no timezone data at all — these two are classic container-deployment openers.
Why this happens
Docker images are based on Linux defaults: timezone = UTC, locale = C. date reads /etc/localtime (or TZ env var + zoneinfo), not the host timezone — containers do not inherit the host timezone.
TZ works in two layers: the TZ env var only tells libc "which zone to look up in zoneinfo".
If the image has no /usr/share/zoneinfo/ (reproduced: the alpine base image does not even have that directory), TZ=Asia/Shanghai silently does nothing and stays UTC — this is the #1 reason "TZ is set but useless".
Two workarounds: ① install tzdata (alpine: apk add tzdata; Debian-family images usually ship it, so -e TZ=Asia/Shanghai just works); ② a POSIX TZ string that needs no zoneinfo (-e TZ=UTC-8 = UTC+8, sign is inverted vs intuition;
reproduced: shows 23:09 matching host CST).
Garbled Chinese also splits into two layers: the program inside the container outputting in ASCII/system encoding (Python in a C locale auto-enables UTF-8 — PEP 540 — and prints Chinese fine, reproduced;
but forcing PYTHONIOENCODING=ascii immediately gives UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128), reproduced verbatim);
and the viewing terminal mis-decoding (container emits UTF-8 bytes, a Windows console decodes them as GBK → mojibake, unrelated to the container).
Deterministic takeaway: TZ not working → docker run --rm <image> ls /usr/share/zoneinfo to check for timezone data; UnicodeEncodeError → check env vars for PYTHONIOENCODING/LANG pinning the encoding.
Step by step
1. Confirm where the time is wrong — Must do
docker run --rm alpine date # UTC = not effective
docker run --rm alpine ls /usr/share/zoneinfo # No such file = image has no tzdata
2. Pick the fix by image family — By diagnosis
- Debian family (ubuntu/debian/python:slim etc.): ships zoneinfo;
-e TZ=Asia/Shanghaijust works; - Alpine family:
apk add --no-cache tzdatain the Dockerfile first, then-e TZ=Asia/Shanghai; or skip it with-e TZ=UTC-8(POSIX, inverted sign); - Existing container: changing env vars requires rebuilding the container (
docker compose up -d --force-recreateor a freshdocker run);docker restartkeeps the env from creation time, so changes do not apply.
3. Debug garbled Chinese — By diagnosis
# Confirm the real stdout encoding inside the container
docker run --rm your-python-image python3 -c "import sys; print(sys.stdout.encoding)"
# utf-8 = fine; ascii = pinned by an env var
Fix priority: PYTHONUTF8=1 (global) → PYTHONIOENCODING=utf-8 (stdout/stderr) → LANG=C.UTF-8 (locale).
Note PYTHONUTF8=1 does not override an explicit PYTHONIOENCODING=ascii (reproduced: still errors) — you must change that var to utf-8 directly.
4. Viewer-side mojibake (logs/terminal) — By scenario
If the container output is fine but Windows terminals/old editors show garbage: switch the terminal to UTF-8 (PowerShell: chcp 65001; VS Code: UTF-8 in the bottom-right picker). This is a display-layer problem; fixing the container will not help.
How to confirm it works
docker run --rm -e TZ=Asia/Shanghai <image> date matches the host hour; python3 -c "import sys; print(sys.stdout.encoding)" prints utf-8; Chinese output renders correctly.
Other environments
| Environment | Behavior |
|---|---|
| Debian-family image | Ships zoneinfo; -e TZ=Asia/Shanghai just works |
| Alpine base image | No /usr/share/zoneinfo; TZ=Asia/Shanghai silently ineffective (reproduced) |
| No tzdata, temporary fix | -e TZ=UTC-8 (POSIX, inverted sign = UTC+8; reproduced) |
| Python default C locale | PEP 540 auto UTF-8; Chinese prints fine (reproduced) |
| PYTHONIOENCODING=ascii | UnicodeEncodeError (reproduced verbatim) |
| Windows console reading UTF-8 output | GBK decoding shows mojibake (display layer, not a container issue) |
Symptom
# Timezone
$ docker run --rm -e TZ=Asia/Shanghai alpine date
Mon Aug 31 15:09:18 UTC 2026 # still UTC!
$ docker run --rm alpine ls /usr/share/zoneinfo
ls: /usr/share/zoneinfo: No such file or directory
# Garbled text
$ docker run --rm -e PYTHONIOENCODING=ascii python:3.12-alpine python3 -c "print('中文测试')"
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
Signature: TZ=Asia/Shanghai set but date still UTC; the image lacks zoneinfo; a program printing Chinese raises an ascii encoding error.
Cause
Containers default to UTC and do not inherit the host timezone; alpine-class base images lack /usr/share/zoneinfo, so TZ=Asia/Shanghai is ineffective. Garbled Chinese = the program inside the container is pinned to ASCII/non-UTF-8 output (UnicodeEncodeError), or the viewing terminal's encoding does not match UTF-8 (display mojibake).
Solution
- Timezone:
-e TZ=Asia/Shanghaion Debian-family images; install tzdata on alpine or use-e TZ=UTC-8(POSIX, inverted sign) as a stopgap; rebuild the container after changing env; - Encoding:
PYTHONUTF8=1/PYTHONIOENCODING=utf-8/LANG=C.UTF-8; an explicit ascii pin must be changed to utf-8; - Viewer side: switch the terminal to UTF-8 (
chcp 65001, etc.).
Verification Evidence
- Local reproduction (2026-08-31, custom prebuilt WSL, docker 29.1.3):
- Host
23:09:18 CSTvs container default15:09:18 UTC(8h off); -e TZ=Asia/Shanghaion alpine → still UTC;ls /usr/share/zoneinfo→ No such file;-e TZ=UTC-8on alpine →23:09:19(matches CST; POSIX sign inversion);- python default
stdout encoding: utf-8, Chinese fine;PYTHONIOENCODING=ascii→ UnicodeEncodeError verbatim;PYTHONIOENCODING=utf-8/PYTHONUTF8=1→ fine; - Environment limit: the local alpinelinux mirror is broken (
apk add tzdatareports "no such package"), so the standard tzdata path is documented per official docs and was not fully verified locally.
Evidence details kept locally (2026-08-31)
Related canonicals
Read in order: precondition -> same root / same domain / related:
- Related (similar errors, different cause):
- Garbled output when calling wsl from PowerShell (same encoding/display problem family)
- docker compose stack fails to start: dependency not ready (same-batch Docker domain reproduction)
Applicable tools (1)
This problem is linked from the tool pages below — reachable from either side.
dockerSource & evidence
← Coding Agents & Terminal domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk