现状
目前市面上和官方均只有rocketmq x86架构下的docker镜像,而随着国产化和信创适配的需求越来越多,显然现有的x86架构下的docker镜像不能满足多样化的需求,因此我们需要根据官方发布的版本制作满足需求的多架构镜像,以在不同cpu架构下部署使用。
rocketmq官方网站:RocketMQ · 官方网站 | RocketMQ
关于rocketmq的介绍请阅读官方文档,这里就不做过多赘述。
前提条件
1. 构建镜像的机器需要能访问互联网,拥有良好的网络环境
2. 构建之前请搭建好私有仓库,比如harbor、registry这种,以便将多架构镜像推送到镜像仓库中
3. 需要安装docker,版本要求19.03以上,并支持buildx插件
准备工作
1. 编写Dockerfile文件
# 多阶段构建方式 cat Dockerfile-centos################################################################################ # Build stage 1 `builder`: # Download and extract RocketMQ ################################################################################ FROM eclipse-temurin:8-jdk-centos7 AS builderARG versionRUN set -eux \&& yum -y update \&& yum -y install curl gnupg unzip \&& yum clean all -yRUN curl -L https://archive.apache.org/dist/rocketmq/${version}/rocketmq-all-${version}-bin-release.zip -o rocketmq.zip \&& curl -L https://archive.apache.org/dist/rocketmq/${version}/rocketmq-all-${version}-bin-release.zip.asc -o rocketmq.zip.asc \&& curl -L https://www.apache.org/dist/rocketmq/KEYS -o KEYS \&& gpg --import KEYS \&& gpg --batch --verify rocketmq.zip.asc rocketmq.zipRUN unzip rocketmq.zip \&& mkdir -p /tmp/rocketmq-${version} \&& mv rocketmq*/* /tmp/rocketmq-${version}################################################################################ # Build stage 2: # Make the actual RocketMQ docker image ################################################################################ FROM eclipse-temurin:8-jdk-centos7ARG user=rocketmq ARG group=rocketmq ARG uid=3000 ARG gid=3000ARG version# Rocketmq version ENV ROCKETMQ_VERSION ${version}# Rocketmq home ENV ROCKETMQ_HOME /home/rocketmq/rocketmq-${ROCKETMQ_VERSION}# expose namesrv port EXPOSE 9876# expose broker ports EXPOSE 10909 10911 10912# RocketMQ is run with user `rocketmq`, uid = 3000 # If you bind mount a volume from the host or a data container, # ensure you use the same uid RUN groupadd -g ${gid} ${group} \&& useradd -l -u ${uid} -g ${gid} -m -s /bin/bash ${user} \&& yum -y update \&& yum -y install less openssl which bash wget curl tzdata \&& yum clean all -y && rm -rf /var/cache/yum # Copy customized scripts COPY scripts/ ${ROCKETMQ_HOME}/bin/# Copy RocketMQ artifact from builder COPY --from=builder --chown=${uid}:${gid} /tmp/rocketmq-${version}/ ${ROCKETMQ_HOME}# Override customized scripts for namesrv # Override customized scripts for broker # Export Java options # Add ${JAVA_HOME}/lib/ext as java.ext.dirs RUN mv ${ROCKETMQ_HOME}/bin/runserver-customize.sh ${ROCKETMQ_HOME}/bin/runserver.sh \&& mv ${ROCKETMQ_HOME}/bin/runbroker-customize.sh ${ROCKETMQ_HOME}/bin/runbroker.sh \&& chmod -R a+x ${ROCKETMQ_HOME}/bin/ \&& export JAVA_OPT=" -Duser.home=/opt" \&& sed -i 's/${JAVA_HOME}\/jre\/lib\/ext/${JAVA_HOME}\/jre\/lib\/ext:${JAVA_HOME}\/lib\/ext/' ${ROCKETMQ_HOME}/bin/tools.sh \&& chown -R ${uid}:${gid} ${ROCKETMQ_HOME} \&& localedef -i en_US -f UTF-8 en_US.UTF-8 \&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \&& export LANG=C.UTF-8USER ${user}WORKDIR ${ROCKETMQ_HOME}/binENTRYPOINT ["./docker-entrypoint.sh"] # Dummy overridable parameter parsed by entrypoint CMD ["dummy"]
2. 编写需要的脚本文件
# 脚本文件docker-entrypoint.sh cat docker-entrypoint.sh#!/bin/bash set -e# Allow user specify custom CMD, maybe run /bin/bash to check the image if [[ "$1" == "nameserver" || "${NODE_ROLE}" == "nameserver" ]]; thenshiftexec ./mqnamesrv "${@}" elif [[ "$1" == "broker" || "${NODE_ROLE}" == "broker" ]]; thenshiftexec ./mqbroker "${@}" elif [[ "$1" == "controller" || "${NODE_ROLE}" == "controller" ]]; thenshiftexec ./mqcontroller "${@}" else# Run whatever command the user wantsexec "$@" fi
# 脚本文件 runbroker-customize.sh#!/bin/bash# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.#=========================================================================================== # Java Environment Setting #=========================================================================================== error_exit () {echo "ERROR: $1 !!"exit 1 }find_java_home() {case "`uname`" inDarwin)JAVA_HOME=$(/usr/libexec/java_home);;*)JAVA_HOME=$(dirname $(dirname $(readlink -f $(which javac))));;esac }find_java_home[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java [ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!"export JAVA_HOME export JAVA="$JAVA_HOME/bin/java" export BASE_DIR=$(dirname $0)/.. export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH}#=========================================================================================== # JVM Configuration #=========================================================================================== calculate_heap_sizes() {case "`uname`" inLinux)system_memory_in_mb=`free -m| sed -n '2p' | awk '{print $2}'`system_cpu_cores=`egrep -c 'processor([[:space:]]+):.*' /proc/cpuinfo`;;FreeBSD)system_memory_in_bytes=`sysctl hw.physmem | awk '{print $2}'`system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024`system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'`;;SunOS)system_memory_in_mb=`prtconf | awk '/Memory size:/ {print $3}'`system_cpu_cores=`psrinfo | wc -l`;;Darwin)system_memory_in_bytes=`sysctl hw.memsize | awk '{print $2}'`system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024`system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'`;;*)# assume reasonable defaults for e.g. a modern desktop or# cheap serversystem_memory_in_mb="2048"system_cpu_cores="2";;esac# some systems like the raspberry pi don't report cores, use at least 1if [ "$system_cpu_cores" -lt "1" ]thensystem_cpu_cores="1"fi# set max heap size based on the following# max(min(1/2 ram, 1024MB), min(1/4 ram, 8GB))# calculate 1/2 ram and cap to 1024MB# calculate 1/4 ram and cap to 8192MB# pick the maxhalf_system_memory_in_mb=`expr $system_memory_in_mb / 2`quarter_system_memory_in_mb=`expr $half_system_memory_in_mb / 2`if [ "$half_system_memory_in_mb" -gt "1024" ]thenhalf_system_memory_in_mb="1024"fiif [ "$quarter_system_memory_in_mb" -gt "8192" ]thenquarter_system_memory_in_mb="8192"fiif [ "$half_system_memory_in_mb" -gt "$quarter_system_memory_in_mb" ]thenmax_heap_size_in_mb="$half_system_memory_in_mb"elsemax_heap_size_in_mb="$quarter_system_memory_in_mb"fiMAX_HEAP_SIZE="${max_heap_size_in_mb}M"# Young gen: min(max_sensible_per_modern_cpu_core * num_cores, 1/4 * heap size)max_sensible_yg_per_core_in_mb="100"max_sensible_yg_in_mb=`expr $max_sensible_yg_per_core_in_mb "*" $system_cpu_cores`desired_yg_in_mb=`expr $max_heap_size_in_mb / 4`if [ "$desired_yg_in_mb" -gt "$max_sensible_yg_in_mb" ]thenHEAP_NEWSIZE="${max_sensible_yg_in_mb}M"elseHEAP_NEWSIZE="${desired_yg_in_mb}M"fi }calculate_heap_sizes# Dynamically calculate parameters, for reference. Xms=$MAX_HEAP_SIZE Xmx=$MAX_HEAP_SIZE Xmn=$HEAP_NEWSIZE MaxDirectMemorySize=$MAX_HEAP_SIZE # Set for `JAVA_OPT`. JAVA_OPT="${JAVA_OPT} -server -Xms${Xms} -Xmx${Xmx} -Xmn${Xmn}" JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:SurvivorRatio=8" JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/dev/shm/mq_gc_%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy" JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m" JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch" JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=${MaxDirectMemorySize}" JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking" JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib" #JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"numactl --interleave=all pwd > /dev/null 2>&1 if [ $? -eq 0 ] thenif [ -z "$RMQ_NUMA_NODE" ] ; thennumactl --interleave=all $JAVA ${JAVA_OPT} $@elsenumactl --cpunodebind=$RMQ_NUMA_NODE --membind=$RMQ_NUMA_NODE $JAVA ${JAVA_OPT} $@fi else$JAVA ${JAVA_OPT} $@ fi
# 脚本文件 runserver-customize.sh#!/bin/bash# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.#=========================================================================================== # Java Environment Setting #=========================================================================================== error_exit () {echo "ERROR: $1 !!"exit 1 }find_java_home() {case "`uname`" inDarwin)JAVA_HOME=$(/usr/libexec/java_home);;*)JAVA_HOME=$(dirname $(dirname $(readlink -f $(which javac))));;esac }find_java_home[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java [ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!"export JAVA_HOME export JAVA="$JAVA_HOME/bin/java" export BASE_DIR=$(dirname $0)/.. export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH}#=========================================================================================== # JVM Configuration #=========================================================================================== calculate_heap_sizes() {case "`uname`" inLinux)system_memory_in_mb=`free -m| sed -n '2p' | awk '{print $2}'`system_cpu_cores=`egrep -c 'processor([[:space:]]+):.*' /proc/cpuinfo`;;FreeBSD)system_memory_in_bytes=`sysctl hw.physmem | awk '{print $2}'`system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024`system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'`;;SunOS)system_memory_in_mb=`prtconf | awk '/Memory size:/ {print $3}'`system_cpu_cores=`psrinfo | wc -l`;;Darwin)system_memory_in_bytes=`sysctl hw.memsize | awk '{print $2}'`system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024`system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'`;;*)# assume reasonable defaults for e.g. a modern desktop or# cheap serversystem_memory_in_mb="2048"system_cpu_cores="2";;esac# some systems like the raspberry pi don't report cores, use at least 1if [ "$system_cpu_cores" -lt "1" ]thensystem_cpu_cores="1"fi# set max heap size based on the following# max(min(1/2 ram, 1024MB), min(1/4 ram, 8GB))# calculate 1/2 ram and cap to 1024MB# calculate 1/4 ram and cap to 8192MB# pick the maxhalf_system_memory_in_mb=`expr $system_memory_in_mb / 2`quarter_system_memory_in_mb=`expr $half_system_memory_in_mb / 2`if [ "$half_system_memory_in_mb" -gt "1024" ]thenhalf_system_memory_in_mb="1024"fiif [ "$quarter_system_memory_in_mb" -gt "8192" ]thenquarter_system_memory_in_mb="8192"fiif [ "$half_system_memory_in_mb" -gt "$quarter_system_memory_in_mb" ]thenmax_heap_size_in_mb="$half_system_memory_in_mb"elsemax_heap_size_in_mb="$quarter_system_memory_in_mb"fiMAX_HEAP_SIZE="${max_heap_size_in_mb}M"# Young gen: min(max_sensible_per_modern_cpu_core * num_cores, 1/4 * heap size)max_sensible_yg_per_core_in_mb="100"max_sensible_yg_in_mb=`expr $max_sensible_yg_per_core_in_mb "*" $system_cpu_cores`desired_yg_in_mb=`expr $max_heap_size_in_mb / 4`if [ "$desired_yg_in_mb" -gt "$max_sensible_yg_in_mb" ]thenHEAP_NEWSIZE="${max_sensible_yg_in_mb}M"elseHEAP_NEWSIZE="${desired_yg_in_mb}M"fi }calculate_heap_sizes# Dynamically calculate parameters, for reference. Xms=$MAX_HEAP_SIZE Xmx=$MAX_HEAP_SIZE Xmn=$HEAP_NEWSIZE # Set for `JAVA_OPT`. JAVA_OPT="${JAVA_OPT} -server -Xms${Xms} -Xmx${Xmx} -Xmn${Xmn}" JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC" JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/dev/shm/rmq_srv_gc.log -XX:+PrintGCDetails" JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages" JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib" #JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"$JAVA ${JAVA_OPT} $@
编写构建脚本build-image.sh
# 构建镜像的脚本#!/usr/bin/env bashcheckVersion() {echo "Version = $1"echo $1 |grep -E "^[0-9]+\.[0-9]+\.[0-9]+" > /dev/nullif [ $? = 0 ]; thenreturn 1fiecho "Version $1 illegal, it should be X.X.X format(e.g. 4.5.0), please check released versions in 'https://archive.apache.org/dist/rocketmq/'"exit -1
}if [ $# -lt 2 ]; thenecho -e "Usage: sh $0 Version BaseImage"exit -1
fiROCKETMQ_VERSION=$1BASE_IMAGE=centoscheckVersion $ROCKETMQ_VERSION# Build rocketmq
case "${BASE_IMAGE}" incentos)docker run --privileged --rm harbor.codemiracle.com.cn/baseapp/binfmt:latest --install alldocker buildx create --use --name=mybuilder-rocketmq --driver docker-container --driver-opt image=harbor.codemiracle.com.cn/baseapp/buildkit:masterdocker buildx build --no-cache -f Dockerfile-centos --platform=linux/amd64,linux/arm64 -t harbor.codemiracle.com.cn/baseapp/rocketmq:${ROCKETMQ_VERSION} --build-arg version=${ROCKETMQ_VERSION} . --pushdocker buildx rm mybuilder-rocketmq;;*)echo "${BASE_IMAGE} is not supported, supported base images: centos"exit -1;;
esac
如何构建
# 如何使用脚本构建呢?1. 创建相关目录,将文件放到对应目录下mkdir scriptsmv docker-entrypoint.sh scripts/mv runbroker-customize.sh scripts/mv runserver-customize.sh scripts/2. 登陆harbordocker login harbor.codemiracle.com.cn3. 执行构建脚本sh build-image.sh [rocketmq版本号]eg: sh build-image.sh 4.5.2
参考资料:
GitHub - apache/rocketmq-docker: Apache RocketMQ Docker