💡 개요
컨테이너 환경에서 애플리케이션을 운영할 때, 정확한 타임존(Timezone) 설정은 매우 중요하다. 로그 기록, 데이터베이스 시간 동기화, 스케줄링된 작업 등 다양한 영역에서 시간 정보가 일관되지 않으면 예상치 못한 문제나 오류가 발생할 수 있다. 이 문서에서는 Docker 컨테이너의 타임존을 설정하는 다양한 방법과 각 방법의 특징을 살펴보았다.
💬 이슈
쿠버네티스(Kubernetes) 상에 동작 중인 파드(Pod)마다 서로 다른 timezone을 가지고 있었고, 이를 GMT+9 (Asia/Seoul)로 일괄 변환하는 방법이 필요했다.
🧗 해결
컨테이너의 타임존을 설정하는 주요 방법은 다음과 같다.
1. Dockerfile을 통한 설정 (Build-time)
컨테이너 이미지를 빌드하는 시점에 Dockerfile 내에서 타임존을 설정하는 방법이다. 이 방법은 컨테이너가 시작될 때마다 별도의 설정 없이 일관된 타임존을 보장하여 가장 권장되는 방식 중 하나이다.
- 원리: 대부분의 Linux 시스템은
/etc/timezone
파일에 타임존 정보를 저장하거나,/etc/localtime
파일이 실제 타임존 데이터 파일(예:/usr/share/zoneinfo/Asia/Seoul
)을 가리키는 심볼릭 링크로 구성된다.tzdata
패키지는 이러한 타임존 데이터 파일을 제공한다.ENV TZ
명령어는 컨테이너 내부의 환경 변수를 설정하여 시스템이 해당 타임존을 사용하도록 지시한다.
# 예시: Ubuntu/Debian 기반 이미지
FROM ubuntu:latest
# tzdata 패키지 설치 (타임존 데이터 제공)
# noninteractive 모드로 설치하여 사용자 입력 없이 진행
RUN apt-get update && apt-get install -y tzdata && rm -rf /var/lib/apt/lists/*
# 환경 변수 TZ를 Asia/Seoul로 설정
ENV TZ=Asia/Seoul
# 애플리케이션 실행 명령어 (예시)
CMD ["/bin/bash"]
- 장점:
- 이미지 자체에 타임존 정보가 포함되어 있어 이식성이 높다.
- 컨테이너 실행 시 별도의 설정이 필요 없어 관리가 용이하다.
- 빌드 시점에 타임존이 고정되므로 예측 가능하다.
- 단점:
- 타임존 변경 시 이미지를 다시 빌드해야 한다.
tzdata
패키지 설치로 인해 이미지 크기가 약간 증가할 수 있다.
2. Volume Mount를 통한 설정 (Run-time)
호스트 시스템의 타임존 정보를 컨테이너 내부로 마운트하여 사용하는 방법이다. 이 방법은 컨테이너 이미지를 수정하지 않고 런타임에 타임존을 유연하게 설정할 수 있다.
- 원리: 호스트 시스템의
/etc/localtime
파일 또는/usr/share/zoneinfo
디렉토리를 컨테이너 내부의/etc/localtime
경로로 마운트한다. 컨테이너는 마운트된 호스트의 타임존 정보를 사용하게 된다.
Docker CLI
$ docker run -d \
-v /etc/localtime:/etc/localtime:ro \
-v /usr/share/zoneinfo/Asia/Seoul:/etc/localtime:ro # 특정 타임존 파일 마운트 (더 명시적)
your-image-name
/etc/localtime:/etc/localtime:ro
: 호스트의 현재 타임존 설정을 컨테이너로 읽기 전용(read-only)으로 마운트한다./usr/share/zoneinfo/Asia/Seoul:/etc/localtime:ro
: 호스트의 특정 타임존 데이터 파일(Asia/Seoul
)을 컨테이너의/etc/localtime
로 마운트한다. 이 방법은 호스트의 현재 타임존 설정과 무관하게 컨테이너에 특정 타임존을 강제할 때 유용하다.
Kubernetes 환경
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-container
image: your-image-name
volumeMounts:
- name: tz-config
mountPath: /etc/localtime # /etc/localtime 파일을 마운트
readOnly: true
volumes:
- name: tz-config
hostPath:
path: /usr/share/zoneinfo/Asia/Seoul # 호스트의 Asia/Seoul 타임존 파일을 사용
type: File # 파일임을 명시
- 장점:
- 이미지 재빌드 없이 런타임에 타임존을 변경할 수 있다.
- 호스트의 타임존과 동기화하거나, 호스트에 존재하는 특정 타임존 파일을 선택하여 사용할 수 있다.
- 단점:
- 컨테이너가 호스트 시스템에 의존하게 된다. 호스트의 타임존 설정이 변경되면 컨테이너에도 영향을 미친다.
hostPath
사용 시 노드 간 이식성이 저하될 수 있다 (모든 노드에 동일한 타임존 파일이 존재해야 한다).- 보안상의 이유로
hostPath
사용을 제한하는 환경도 있다.
3. 환경 변수 TZ
만 설정 (Run-time)
컨테이너 이미지에 이미 tzdata
패키지가 설치되어 있는 경우, TZ
환경 변수만 설정하여 타임존을 변경할 수 있다.
- 원리:
TZ
환경 변수는 C 라이브러리(glibc)에서 시간을 처리할 때 참조하는 타임존을 지정한다.tzdata
패키지가 설치되어 있다면,/usr/share/zoneinfo
경로에 다양한 타임존 데이터 파일이 존재하며,TZ
변수는 이 중 어떤 파일을 사용할지 알려주는 역할을 한다.
Docker CLI
$ docker run -d \
-e TZ=Asia/Seoul \
your-image-name
Kubernetes 환경
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-container
image: your-image-name
env:
- name: TZ
value: Asia/Seoul
- 장점:
- 가장 간단하고 유연한 방법이다.
- 이미지 재빌드 없이 런타임에 타임존을 변경할 수 있다.
- 단점:
- 컨테이너 이미지 내부에
tzdata
패키지가 미리 설치되어 있어야 한다. 그렇지 않으면TZ
환경 변수가 제대로 작동하지 않거나 기본 UTC로 동작할 수 있다.
- 컨테이너 이미지 내부에
4. timedatectl
명령어 사용 (컨테이너 내부)
일부 컨테이너 이미지에는 systemd
가 포함되어 있지 않아 timedatectl
명령어를 직접 사용할 수 없는 경우가 많다. 하지만 디버깅 목적이나 특정 베이스 이미지에서는 유용할 수 있다.
# 컨테이너 내부에서 실행 (예시)
$ docker exec -it <container_id> /bin/bash
# 컨테이너 쉘 내부에서
$ timedatectl set-timezone Asia/Seoul
- 장점: 컨테이너 내부에서 직접 시스템 타임존을 설정하는 것과 유사한 효과를 낼 수 있다.
- 단점: 대부분의 경량 컨테이너 이미지에는
systemd
나timedatectl
이 포함되어 있지 않아 사용하기 어렵다. 컨테이너 재시작 시 설정이 유지되지 않을 수 있다.
✅ 확인
컨테이너 내부에서 타임존이 올바르게 설정되었는지 확인하는 방법이다.
# date 명령어 사용
$ date
Tue Nov 22 07:44:20 KST 2022 # 예시 출력: KST (한국 표준시)로 표시되었다.
# timedatectl 명령어 사용 (timedatectl이 설치된 경우)
$ timedatectl
Local time: 화 2022-11-22 07:44:20 KST
Universal time: 월 2022-11-21 22:44:20 UTC
RTC time: 월 2022-11-21 22:44:20
Time zone: Asia/Seoul (KST, +0900)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
🚀 요약
방법 | 장점 | 단점 | 권장 시나리오 |
---|---|---|---|
Dockerfile | 이미지에 타임존 내장, 이식성 높음, 일관된 설정 보장 | 이미지 재빌드 필요, 이미지 크기 약간 증가 | 대부분의 프로덕션 환경, 일관된 타임존이 필요한 경우 |
Volume Mount | 이미지 재빌드 불필요, 런타임 유연성, 호스트와 동기화 가능 | 호스트 의존성, 노드 간 이식성 저하, hostPath 보안 문제 | 런타임에 타임존 변경이 잦거나 호스트와 동기화가 필요한 경우 |
환경 변수 TZ | 가장 간단, 이미지 재빌드 불필요, 런타임 유연성 | tzdata 설치 필수, 설치되지 않은 경우 기본 UTC | tzdata 가 포함된 경량 이미지 사용 시, 간단한 설정 |
timedatectl | 컨테이너 내부에서 직접 설정 가능 | 대부분의 경량 이미지에서 사용 불가, 컨테이너 재시작 시 설정 유지 안됨, 디버깅 목적 외 비권장 | 디버깅 목적, 특정 베이스 이미지 사용 시 |
🔗 참고
- https://dev.to/0xbf/set-timezone-in-your-docker-image-d22
- Docker 공식 문서: Configure timezone (ENV 명령어 관련)
- Kubernetes 공식 문서: Volumes - hostPath (hostPath 관련)
- Linux man page: tzset(3) (TZ 환경 변수 관련)