支持初始化數據的Zookeeper Docker鏡像


最近在做一個演示項目 https://github.com/cnscud/cavedemo, 自然為了方便, 也做了docker打包, 發現zookeeper的鏡像沒有導入初始化數據的功能, 於是自己做了一個鏡像, 還是蠻簡單的.

鏡像已經發布在 https://hub.docker.com/r/cnscud/zookeeper 官方倉庫.

使用方法1: 命令行直接運行

沒參數的話和官方鏡像一樣, 也可以指定參數, 建議用docker-compose.

docker run --name zk1 -d -p 2181:2181 cnscud/zookeeper:zk3.6-0.1

使用docker-compose, 方便設定參數

下面是一個例子: samples/docker-compose1/docker-compose.yml:

version: '3'
services:
  cnscud-zookeeper:
    image: cnscud/zookeeper:zk3.6-0.1
    volumes:
      - ./init.data:/init.data/
      - ./rundata/data:/data
      - ./rundata/logs:/datalog
    container_name: cnscud-sample-zk1
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - "2181:2181"
    restart: on-failure
    ## use the hostname in project
    hostname: cnscud-sample-zk1.cnscud.com

你可以在 samples/docker-compose1 目錄下發現所需的所有文件: https://github.com/cnscud/cnscud-docker/tree/main/docker-zookeeper/samples/docker-compose1

初始化數據使用說明

我們可以看到, 在volume里綁定了一個 /init.data/ 目錄, 那么還有什么特定規則哪?

需要准備一個 腳本文件 "import.data.zk.sh", 放在這個目錄里, 用來初始化數據, 至於文件內容, 就根據你的需要來編寫了.

下面是一個例子, 是從文件里讀取節點內容, 並設置到zookeeper的節點上去.

#!/bin/bash

## for init zookeeper data, you need update this file.
##
## author: Felix Zhang<https://github.com/cnscud/>  2021.8.22
##
## please make sure the file 755
##


CMD=`which zkCli.sh`
find="1"
if [ -z $CMD ]
then
	find="0"
fi

if [ $find = "0" ]
then
	CMD="$ZK_HOME/bin/zkCli.sh"
fi

echo $CMD

if [ -z $CMD ]
then
  echo "not found zkCli.sh, please check!!!"
  exit 1
fi


$CMD  create /xpower "1"
$CMD  create /xpower/cache "1"
$CMD  create /xpower/config "1"
$CMD  create /xpower/dbn "1"

## read from file!!!
## read from file!!!
## read from file!!!
$CMD  create /xpower/cache/redis.test "`cat /init.data/redis.test.conf`"
$CMD  create /xpower/config/kafka "`cat /init.data/kafka.conf`"
$CMD  create /xpower/dbn/cavedemo "`cat /init.data/mysql.cavedemo.conf`"

我們可以看到這個腳本做了幾件事:

  • 查找zkCli.sh, 並設置正確的路徑
  • 創建各級節點
  • 創建最終的節點, 節點的內容是從文件讀取的, 可以支持換行和雙引號等, 要特別注意這個語法.

在這個腳本里, 使用zookeeper自帶的zkCli.sh 腳本創建你的節點, 可以通過下面的命令從文件讀入節點內容:

"cat /init.data/kafka.conf"

要注意這個腳本里用到的文件要實現放到統一目錄下, 或者其他綁定的目錄下.

更多配置選項

因為繼承的是官方的zookeeper docker鏡像, 所以更多信息可以參考 https://hub.docker.com/_/zookeeper.

原理分析

我們用 docker inspect 或者直接查看git倉庫可以看到官方docker的設置:

ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["zkServer.sh", "start-foreground"]

如果我們需要導入數據, 則需要先后台啟動zookeeper, 執行導入操作, 然后重啟zookeeper, 不過要放在foreground方式啟動.
看看這個重寫的dockerfile:

FROM zookeeper:3.6

##
## docker image for zookeeper with init data feature.
##
## author: Felix Zhang<cnscud@gmail.com>  2021.8.23
## website: https://github.com/cnscud/cnscud-docker

LABEL OG=cnscud.com
LABEL maintainer="Felix Zhang<cnscud@gmail.com>"
LABEL reference="https://github.com/cnscud/cnscud-docker"

## my entrypoint script
ADD cnscud-docker-entrypoint.sh /

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

## declare the volumen for init data
VOLUME /init.data

## declare the port
EXPOSE 2181

## ===================================

## from official zookeeper as reference
# ENTRYPOINT ["/docker-entrypoint.sh"]
# CMD ["zkServer.sh" "start-foreground"]

ENTRYPOINT ["/cnscud-docker-entrypoint.sh"]
CMD ["zkServer.sh","start-foreground"]

里面重新聲明了ENTRYPOINT, 換成了自定義版本的 cnscud-docker-entrypoint.sh. 里面還聲明了VOLUME /init.data .

當然我們盡量復用原有的腳本, 而不是改的面目全非(畢竟那么亂...), 我們來看看:

#!/bin/bash
## script for support import data with zookeeper
## author: Felix Zhang 2021.8.22
## please make sure the file 755

# set -e

initedfile="/data/zk.cnscud.inited"
initcmdfile='/init.data/import.data.zk.sh'

needcallinit="Y"

#
if [ ! -f "$initedfile" ]
then
  needcallinit="Y${needcallinit}"
else
  echo "[cnscud] data had inited, will not init again."
fi

if [ -f "$initcmdfile" ]
then
  needcallinit="Y${needcallinit}"
else
  echo "[cnscud] not found script for init data, skip."
fi

echo "check needcallinit is: $needcallinit"

## start my import data ====================
if [ $needcallinit = "YYY" ]
then

  ## start in backgroup by original entry point
  /docker-entrypoint.sh zkServer.sh start

  ## waiting for zookeeper
  sleep 10

  echo "[cnscud] call init data now..."
  date > "$initedfile"

  ##import data
  sh $initcmdfile >> $initedfile

  /docker-entrypoint.sh zkServer.sh stop

  ## mark
  echo "[cnscud] mark: init was finished!"
  date >> "$initedfile"
  echo "done" >> "$initedfile"
fi

## end my import data ====================


echo "[cnscud] Starting Zookeeper in foreground mode..."
/docker-entrypoint.sh $@

我們可以看到這個代碼其實很簡單, 雖然很多行:

  • 首選判斷是否已經執行過, 用 /data/zk.cnscud.inited 文件方式來標記
  • 如果沒有初始化過, 則后台方式啟動zkServer
  • 執行初始化腳本
  • 停止 zkServer
  • 重新按默認參數或傳入的參數啟動zkServer.

感想

其實很簡單, 只不過第一次發布鏡像到docker hub, 沒想到社區非常開放, 任何人都能發布鏡像上去, 就導致很混亂, 很多鏡像沒有說明, 沒有人維護, 但下載量很大. 希望不要像npm那么出現問題.

docker很好, 准備好內存和硬盤~!

感謝

感謝google, stackoverflow, withpy 以及我的家人.

Star

如果覺得好, 就給個Star 吧: https://github.com/cnscud/cnscud-docker


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM