不同Docker操作系統的時區同步

我們經常會發現docker和宿主機的時間是不同步的,這幾乎是個坑,特別是數據庫系統,時間錯誤簡直要命。這時間一般是相差8小時,因我們的時間是東八區時間,而docker用的是標準時間:

CST是指(China Shanghai Time,東八區時間) 
UTC是指(Coordinated Universal Time,標準時間)

這2個時間相差8個小時,一般沒有設置過的容器,跟宿主機時間相差8h,通過date命令就能看出來。雖然這個問題很簡單,但沒人提醒的話,一頓找別的原因,也足以讓很多人抓狂(我在部署docker版的skywalking時就犯了這個錯,怎麼修改配置都看不到監控數據,因爲當前收集的數據全變成8小時前的歷史數據了)。

遇到docker時區不一致,我們只需要對其進行同步處理就可以了,但由於docker運行的基礎操作系統不同,或者系統裏沒裝時區工具或是沒有zoneinfo信息,那麼我們的處理方式就略有不同:

1. Docker常用的運行環境

docker常用的操作系統包括busybox、alpine、debian、ubuntu、centos,它們的大小都不一樣,適用的範圍也會有區別,一般由docker中部署的項目特性來決定,鏡像大小肯定也是優先考慮的因素:

基本上除了busybox,大部分的linux系統都可以通過命令 cat /etc/issue 來獲知其系統版本:

# 進入容器命令行
docker exec -it [container_name | container_id] /bin/sh

##########################################
/ # cat /etc/issue
Welcome to Alpine Linux 3.12
Kernel \r on an \m (\l)

##########################################

root@9f1fc6293ff9:/# cat /etc/issue
Debian GNU/Linux 10 \n \l

#########################################

[root@qa ~]# cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m

對於CentOS / Redhat 可以通過 cat /etc/redhat-release 來看具體版本:

[root@localhost ~]# cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)

  busybox和alpine系統在bin目錄下,可以找到busybox文件:

/ # find /bin |grep busybox
/bin/busybox

對於docker環境,除了進入容器用以上的命令查看方式來判斷操作系統版本,有時候可以通過鏡像文件dockerfile的images標識或是RUN命令來判斷(其實不好判斷,一般apk命令是針對alpine,apt-get是針對debian或ubuntu,yum命令是針對centos):

2. busybox下同步時區

busybox是極度輕量版的操作系統,很多時候沒法安裝時區數據文件,我們可以採用簡單粗暴方式,直接從宿主機拷。

# 查看是否有Shanghai時區文件
ls /usr/share/zoneinfo/Asia/Shanghai

# 如果沒有就需要獲取時區文件,先進入busybox,如container_id=be318f78137f
docker exec -ti be318f78137f /bin/sh
mkdir -p /usr/share
exit
# 拷貝宿主機的時區文件到docker中
docker cp /usr/share/zoneinfo be318f78137f:/usr/share/zoneinfo

# 進入busybox,同步時區
docker exec -ti be318f78137f /bin/sh
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

同步完時間後,通過date命令就可以看到時間已和宿主機同步。

另外也可以在dockerfile中完成這個工作:

# 需將/usr/share/zoneinfo先拷到dockerfile的目錄下
COPY zoneinfo /usr/share/zoneinfo/
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

3. alpine下同步時區

alpine默認也是沒有時區文件,也需要安裝:

# 進入容器命令行
docker exec -it [container_name | container_id] /bin/sh

# 安裝 timezone 數據包,爲了防止添加失敗,加上-U參數,更新倉儲緩存。
apk add -U tzdata

# 列出安裝的時區文件,驗證是否下載成功。
ls /usr/share/zoneinfo

# 拷貝需要的時區文件到localtime,國內需要的是Asia/Shanghai:
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

# 驗證時區,CST 即爲中國標準時間。
date
# Tue Jun 30 11:53:46 CST 2020

# 移除時區文件:
apk del tzdata

另外也可以在dockerfile中添加以下內容,完成時區的構建:

# Install root filesystem
ADD ./rootfs /
# Install base packages
RUN apk update && apk add curl bash tree tzdata \
    && cp -r -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo -ne "timezone Asia/Shanghai. (`uname -rsv`)\n" >> /root/.built

4. debian / ubuntu下同步時區

# 進入容器命令行
docker exec -it [container_name | container_id] /bin/bash

# 列出安裝的時區文件,驗證是否存在tzdata。
ls /usr/share/zoneinfo
# 一般是已經安裝了 timezone 數據包,如未安裝則執行
apt-get install tzdata

# 軟鏈接時區文件到localtime
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

另外也可以在dockerfile中添加以下內容,完成時區的構建:

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

5. centos下同步時區

# 進入容器命令行
docker exec -it [container_name | container_id] /bin/bash

# 一般都已經安裝了 timezone 數據包,如遇到未安裝則執行
yum install -y tzdata

# 軟鏈接時區文件到localtime
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

在dockerfile中可以添加:

RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo 'Asia/Shanghai' >/etc/timezone

如果你獲取的docker鏡像沒有root權限,你又着急馬上進入容器修改時區,那就簡單暴力一點,直接從宿主機拷入時區文件到docker中,來實現時區的修改:

docker cp /usr/share/zoneinfo/Asia/Shanghai 容器ID:/etc/localtime
echo 'Asia/Shanghai' >/etc/timezone && docker cp /etc/timezone 容器ID:/etc/timezone
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章