Post

docker 안의 DB를 사용할 때 timezone 문제

Oracle로 설명했지만 대부분의 DB in docker image에서 통하는 내용이다.

문제 상황

Oracle docker image를 사용해서 DB 올리고 작업하고 있는데, insert된 row들 날짜 필드 시간이 안맞는다. (UTC -> Asia/Seoul)로 timezone 설정이 필요한 상황이다.

1
2
3
4
5
6
7
8
9
10
SELECT SYSDATE, CURRENT\_DATE, DBTIMEZONE, SESSIONTIMEZONE FROM DUAL;


-- 현재 시각은 한국 기준 05-19 00:38:51
+-------------------+--------------------------+----------+---------------+
    |SYSDATE            |CURRENT\_DATE              |DBTIMEZONE|SESSIONTIMEZONE|
   +-------------------+--------------------------+----------+---------------+
    |2021-05-18 15:38:51|2021-05-18 15:38:51       |+00:00    |UTC            |
   +-------------------+--------------------------+----------+---------------+

timezone 설정은 크게 2가지가 있다 [ OS timezone, DB timezone ]

OS ( docker image인 linux ) timezone에 영향을 받는 Oracle 내장 함수

SYSDATE returns the current date and time set for the operating system on which the database resides

DB timezone에 영향을 받는 Oracle 내장 함수
  • CURRENT\_DATE, CURRENT\_TIMESTAMP, LOCALTIMESTAMP

DB timezone 바꾸는 방법

  • 여기서는 SESSIONTIMEZONE만 변경. SYSDATE는 변함없고 CURRENT_DATE만 바뀐 것을 볼 수 있다.
1
2
3
4
5
6
7
8
ALTER SESSION SET TIME\_ZONE='Asia/Seoul';
-- [DB 재시작 필요하다] ALTER DATABASE SET TIME\_ZONE = 'Asia/Seoul';
+-------------------+-------------------+----------+---------------+
    |SYSDATE            |CURRENT\_DATE       |DBTIMEZONE|SESSIONTIMEZONE|
   +-------------------+-------------------+----------+---------------+
    |2021-05-18 15:58:08|2021-05-19 00:58:08|+00:00    |Asia/Seoul     |
   +-------------------+-------------------+----------+---------------+

docker OS timezone 바꾸는 방법

GNU libc (and thus any non-embedded Linux),
reads /etc/localtime to determine the system’s time zone (the default timezone if not overridden by the TZ environment variable or by an application-specific setting).
https://unix.stackexchange.com/questions/452559/what-is-etc-timezone-used-for

따라서 다음 2 단계 진행하면 된다.

  1. TZ 설정 or /etc/localtime 설정
  2. /etc/timezone 설정

그러나!!! 애초에 도커 이미지의 /usr/share/zoneinfo 에 timezone 파일이 없다면 위 설정이 동작하지 않는다.

Alpine 등 가벼운 base image를 사용한 도커 이미지라면 내부에 timezone 파일이 없을 수 있다.

그래서 먼저 docker 내부에 timezone 파일이 있는지 확인하고, 없다면 넣어주어야 한다.

docker 내부에 zoneinfo 파일 생성하기

외부의 timezone 파일을 복사해서 넣어주는 방법
1
2
3
4
5
COPY {outter OS에 위치한 Asia/Seoul path} /usr/share/zoneinfo/Asia/Seoul
ENV TZ=Asia/Seoul
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime
RUN echo $TZ > /etc/timezone

timezone 파일 직접 설치하는 방법
1
2
3
4
5
6
7
8
9
apt-get update
apt-get install -y tzdata


- 이후 아래 3가지 방법 중 아무거나 써서 설정해도 된다.
1. 직접 ln으로 설정
2. $ tzselect 커맨드 -> env $TZ 통해 설정해준다.
3. $ dpkg-reconfigure tzdata  커맨드 -> /etc/localdate, /etc/timezone 통해 설정해준다.

결과

  • DB 껐다 킬 필요는 없고 세션만 새로 열면 적용된다. SYSDATE만 변경된 것 확인 가능하다.
1
2
3
4
5
6
+-------------------+--------------------------+----------+---------------+
    |SYSDATE            |CURRENT\_DATE              |DBTIMEZONE|SESSIONTIMEZONE|
   +-------------------+--------------------------+----------+---------------+
    |2021-05-19 00:24:54|2021-05-18 15:24:54       |+00:00    |UTC            |
   +-------------------+--------------------------+----------+---------------+

기존 이미지에 timezone 설정을 추가한 docker 이미지 빌드하기

1
2
3
4
5
6
7
FROM oracleinanutshell/oracle-xe-11g
ENV TZ=Asia/Seoul
RUN apt-get update && apt-get install -y tzdata && \
echo $TZ > /etc/timezone && \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
LABEL org.opencontainers.image.authors="sungbum.um@navercorp.com"

This post is licensed under CC BY 4.0 by the author.