Contents

Docker 修改時區方法

Docker 容器預設使用 UTC 時間,但在台灣的服務通常需要 UTC+8(Asia/Taipei)。本文整理幾種常見的時區設定方法,並說明各自的適用場景。

方法一:環境變數 TZ(推薦)

最簡單也最通用的方式,透過 TZ 環境變數告訴容器使用哪個時區:

1
2
3
4
5
# Dockerfile
FROM alpine
RUN apk add --no-cache tzdata
ENV TZ=Asia/Taipei
CMD ["date"]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# docker-compose.yml

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      - TZ=Asia/Taipei
    command: ["date"]

或在 docker run 時指定:

1
docker run -e TZ=Asia/Taipei my-app

常用時區值:

地區 TZ 值
台灣 Asia/Taipei
日本 Asia/Tokyo
美東 America/New_York
UTC UTC

方法二:掛載主機的 /etc/localtime

將主機的時區設定檔掛載到容器內,容器就會使用與主機相同的時區:

1
2
3
4
5
6
7
8
# docker-compose.yml
services:
  app:
    image: alpine
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    command: ["date"]

注意:部分精簡版映像(如 Alpine-based)沒有 /etc/localtime,此方法可能無效。建議搭配方法一一起使用。

方法三:在 Dockerfile 中安裝 tzdata

適合需要固定時區且希望映像自帶設定的情況:

Debian/Ubuntu 基礎映像

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
FROM ubuntu:22.04

# 避免安裝時互動提示
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && \
    apt-get install -y tzdata && \
    ln -sf /usr/share/zoneinfo/Asia/Taipei /etc/localtime && \
    echo "Asia/Taipei" > /etc/timezone && \
    apt-get clean

ENV TZ=Asia/Taipei

Alpine 基礎映像

1
2
3
4
5
6
7
8
FROM alpine:3.18

RUN apk add --no-cache tzdata && \
    cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime && \
    echo "Asia/Taipei" > /etc/timezone && \
    apk del tzdata

ENV TZ=Asia/Taipei

Alpine 安裝完後可以移除 tzdata 套件以縮小映像大小。

驗證時區設定是否生效

1
2
3
4
5
6
7
8
9
# 進入容器確認時區
docker exec -it <container_name> date
# 應該顯示 CST(台灣標準時間)

# 查看容器內時區資訊
docker exec -it <container_name> sh -c "date && cat /etc/timezone"

# 查看環境變數
docker exec -it <container_name> env | grep TZ

docker-compose 完整範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: '3.8'

services:
  web:
    image: nginx:alpine
    environment:
      - TZ=Asia/Taipei
    ports:
      - "80:80"

  db:
    image: mysql:8.0
    environment:
      - TZ=Asia/Taipei
      - MYSQL_ROOT_PASSWORD=secret
    volumes:
      - db_data:/var/lib/mysql

  app:
    build: .
    environment:
      - TZ=Asia/Taipei
    depends_on:
      - db

volumes:
  db_data:

Java 容器的特殊情況

Java 應用程式有自己的時區設定機制,單靠 TZ 環境變數有時不夠,需要額外設定 JVM 參數:

1
2
ENV JAVA_OPTS="-Duser.timezone=Asia/Taipei"
ENV TZ=Asia/Taipei

或在啟動指令中加入:

1
java -Duser.timezone=Asia/Taipei -jar app.jar

參考資料