今天,我们来简要解析一下nacos的nacos/nacos-server:v2.1.2-slim镜像版本做了哪些事。
我们在nacos官网的Quick Start for Nacos Docker页面可以找了解到github名称为nacos-group/nacos-docker的项目是nacos官方用于维护nacos docker镜像的地方,进入项目主页,我们找到2.12对应的版本,下载源码文件,具体链接如下:
这里,我们以Source code(tar.gz)为例来介绍,下载以后,我们得到一个名称为nacos-docker-2.1.2.tar.gz
的文件,解压得到一个名称为nacos-docker-2.1.2
的目录,目录结构如下所示:
lwk@qwfys:~/Downloads/.tmp/.nacos$ tree nacos-docker-2.1.2
nacos-docker-2.1.2
├── build
│ ├── bin
│ │ └── docker-startup.sh
│ ├── conf
│ │ └── application.properties
│ ├── Dockerfile
│ └── Dockerfile.Slim
├── changlog
├── env
│ ├── mysql.env
│ ├── nacos-embedded.env
│ ├── nacos-hostname.env
│ ├── nacos-ip.env
│ └── nacos-standlone-mysql.env
├── example
│ ├── cluster-embedded.yaml
│ ├── cluster-hostname.yaml
│ ├── cluster-ip.yaml
│ ├── image
│ │ └── mysql
│ │ ├── 5.7
│ │ │ └── Dockerfile
│ │ └── 8
│ │ └── Dockerfile
│ ├── prometheus
│ │ ├── prometheus-cluster.yaml
│ │ └── prometheus-standalone.yaml
│ ├── standalone-derby.yaml
│ ├── standalone-mysql-5.7.yaml
│ └── standalone-mysql-8.yaml
├── README.md
└── README_ZH.md
10 directories, 22 files
lwk@qwfys:~/Downloads/.tmp/.nacos$
我们找到文件build/Dockerfile.Slim
,该文件维护了nacos的slim版本的docker镜像所完成的主要工作,内容如下:
FROM amd64/buildpack-deps:buster-curl as installer
ARG NACOS_VERSION=2.1.1
ARG HOT_FIX_FLAG=""
RUN set -x \
&& curl -SL --output /var/tmp/nacos-server.tar.gz https://github.com/alibaba/nacos/releases/download/${NACOS_VERSION}${HOT_FIX_FLAG}/nacos-server-${NACOS_VERSION}.tar.gz \
&& tar -xzvf /var/tmp/nacos-server.tar.gz -C /home \
&& rm -rf /var/tmp/nacos-server.tar.gz /home/nacos/bin/* /home/nacos/conf/*.properties /home/nacos/conf/*.example /home/nacos/conf/nacos-mysql.sql
FROM openjdk:8-jre-slim
# set environment
ENV MODE="cluster" \
PREFER_HOST_MODE="ip"\
BASE_DIR="/home/nacos" \
CLASSPATH=".:/home/nacos/conf:$CLASSPATH" \
CLUSTER_CONF="/home/nacos/conf/cluster.conf" \
FUNCTION_MODE="all" \
NACOS_USER="nacos" \
JAVA="/usr/local/openjdk-8/bin/java" \
JVM_XMS="1g" \
JVM_XMX="1g" \
JVM_XMN="512m" \
JVM_MS="128m" \
JVM_MMS="320m" \
NACOS_DEBUG="n" \
TOMCAT_ACCESSLOG_ENABLED="false" \
TZ="Asia/Shanghai"
WORKDIR $BASE_DIR
# copy nacos bin
COPY --from=installer ["/home/nacos", "/home/nacos"]
ADD bin/docker-startup.sh bin/docker-startup.sh
ADD conf/application.properties conf/application.properties
# set startup log dir
RUN mkdir -p logs \
&& cd logs \
&& touch start.out \
&& ln -sf /dev/stdout start.out \
&& ln -sf /dev/stderr start.out
RUN chmod +x bin/docker-startup.sh
EXPOSE 8848
ENTRYPOINT ["bin/docker-startup.sh"]
我们可以看到,docker镜像构建的时候,会从nacos github官网找对应的版本,这里会下载到一个名称为nacos-server-2.1.2.tar.gz
的文件,解压到/home目录,解压完成以后,清理掉以下几组文件:
构建的时候,以openjdk:8-jre-slim
为母板构建。
最后设置容器中的文件/home/nacos/bin/docker-startup.sh
为容器启动后要执行的初始化命令。
文件docker-startup.sh
主要用于设置nacos启动过程中java如何启动naocs进程,具体内容如下:
#!/bin/bash
# Copyright 1999-2018 Alibaba Group Holding Ltd.
# Licensed 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.
set -x
export CUSTOM_SEARCH_NAMES="application"
export CUSTOM_SEARCH_LOCATIONS=file:${BASE_DIR}/conf/
export MEMBER_LIST=""
PLUGINS_DIR="/home/nacos/plugins/peer-finder"
function print_servers() {
if [[ ! -f "${CLUSTER_CONF}" ]]; then
echo "" >"$CLUSTER_CONF"
for server in ${NACOS_SERVERS}; do
echo "$server" >>"$CLUSTER_CONF"
done
else
bash $PLUGINS_DIR/plugin.sh
sleep 30
fi
}
#===========================================================================================
# JVM Configuration
#===========================================================================================
if [[ "${MODE}" == "standalone" ]]; then
JAVA_OPT="${JAVA_OPT} -Xms${JVM_XMS} -Xmx${JVM_XMX} -Xmn${JVM_XMN}"
JAVA_OPT="${JAVA_OPT} -Dnacos.standalone=true"
else
if [[ "${EMBEDDED_STORAGE}" == "embedded" ]]; then
JAVA_OPT="${JAVA_OPT} -DembeddedStorage=true"
fi
JAVA_OPT="${JAVA_OPT} -server -Xms${JVM_XMS} -Xmx${JVM_XMX} -Xmn${JVM_XMN} -XX:MetaspaceSize=${JVM_MS} -XX:MaxMetaspaceSize=${JVM_MMS}"
if [[ "${NACOS_DEBUG}" == "y" ]]; then
JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n"
fi
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE_DIR}/logs/java_heapdump.hprof"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"
print_servers
fi
#===========================================================================================
# Setting system properties
#===========================================================================================
# set mode that Nacos Server function of split
if [[ "${FUNCTION_MODE}" == "config" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.functionMode=config"
elif [[ "${FUNCTION_MODE}" == "naming" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.functionMode=naming"
fi
# set nacos server ip
if [[ ! -z "${NACOS_SERVER_IP}" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.server.ip=${NACOS_SERVER_IP}"
fi
if [[ ! -z "${USE_ONLY_SITE_INTERFACES}" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.inetutils.use-only-site-local-interfaces=${USE_ONLY_SITE_INTERFACES}"
fi
if [[ ! -z "${PREFERRED_NETWORKS}" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.inetutils.preferred-networks=${PREFERRED_NETWORKS}"
fi
if [[ ! -z "${IGNORED_INTERFACES}" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.inetutils.ignored-interfaces=${IGNORED_INTERFACES}"
fi
### If turn on auth system:
if [[ ! -z "${NACOS_AUTH_ENABLE}" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.core.auth.enabled=${NACOS_AUTH_ENABLE}"
fi
if [[ "${PREFER_HOST_MODE}" == "hostname" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.preferHostnameOverIp=true"
fi
JAVA_OPT="${JAVA_OPT} -Dnacos.member.list=${MEMBER_LIST}"
JAVA_MAJOR_VERSION=$($JAVA -version 2>&1 | sed -E -n 's/.* version "([0-9]*).*$/\1/p')
if [[ "$JAVA_MAJOR_VERSION" -ge "9" ]]; then
JAVA_OPT="${JAVA_OPT} -cp .:${BASE_DIR}/plugins/cmdb/*.jar:${BASE_DIR}/plugins/mysql/*.jar"
JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${BASE_DIR}/logs/nacos_gc.log:time,tags:filecount=10,filesize=102400"
else
JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext:${BASE_DIR}/plugins/health:${BASE_DIR}/plugins/cmdb:${BASE_DIR}/plugins/mysql"
JAVA_OPT="${JAVA_OPT} -Xloggc:${BASE_DIR}/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
fi
JAVA_OPT="${JAVA_OPT} -Dnacos.home=${BASE_DIR}"
JAVA_OPT="${JAVA_OPT} -jar ${BASE_DIR}/target/nacos-server.jar"
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
JAVA_OPT="${JAVA_OPT} --spring.config.additional-location=${CUSTOM_SEARCH_LOCATIONS}"
JAVA_OPT="${JAVA_OPT} --spring.config.name=${CUSTOM_SEARCH_NAMES}"
JAVA_OPT="${JAVA_OPT} --logging.config=${BASE_DIR}/conf/nacos-logback.xml"
JAVA_OPT="${JAVA_OPT} --server.max-http-header-size=524288"
echo "Nacos is starting, you can docker logs your container"
exec $JAVA ${JAVA_OPT}
我们看到,像java堆内存大小这些,这里都已经做了参数化配置。
如果我们要以debug方式启动,这里也做了参数化配置,不过启动后,debug端口号为9555。
环境变量CUSTOM_SEARCH_NAMES
、CUSTOM_SEARCH_LOCATIONS
可以指定新的nacos 配置文件的名称及路径。
文件nacos-docker-2.1.2/build/conf/application.properties
重写了nacos github项目中给到的默认配置文件,主要用于将部分配置项以环境变量的方式暴露了出来,方便我们从外部控制nacos启动过程中的相关细节,具体内容如下:
# spring
server.servlet.contextPath=${SERVER_SERVLET_CONTEXTPATH:/nacos}
server.contextPath=/nacos
server.port=${NACOS_APPLICATION_PORT:8848}
server.tomcat.accesslog.max-days=30
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
spring.datasource.platform=${SPRING_DATASOURCE_PLATFORM:""}
nacos.cmdb.dumpTaskInterval=3600
nacos.cmdb.eventTaskInterval=10
nacos.cmdb.labelTaskInterval=300
nacos.cmdb.loadDataAtStart=false
db.num=${MYSQL_DATABASE_NUM:1}
db.url.0=jdbc:mysql://${MYSQL_SERVICE_HOST}:${MYSQL_SERVICE_PORT:3306}/${MYSQL_SERVICE_DB_NAME}?${MYSQL_SERVICE_DB_PARAM:characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false}
db.url.1=jdbc:mysql://${MYSQL_SERVICE_HOST}:${MYSQL_SERVICE_PORT:3306}/${MYSQL_SERVICE_DB_NAME}?${MYSQL_SERVICE_DB_PARAM:characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false}
db.user=${MYSQL_SERVICE_USER}
db.password=${MYSQL_SERVICE_PASSWORD}
### The auth system to use, currently only 'nacos' and 'ldap' is supported:
nacos.core.auth.system.type=${NACOS_AUTH_SYSTEM_TYPE:nacos}
### worked when nacos.core.auth.system.type=nacos
### The token expiration in seconds:
nacos.core.auth.plugin.nacos.token.expire.seconds=${NACOS_AUTH_TOKEN_EXPIRE_SECONDS:18000}
### The default token:
nacos.core.auth.plugin.nacos.token.secret.key=${NACOS_AUTH_TOKEN:SecretKey012345678901234567890123456789012345678901234567890123456789}
### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay.
nacos.core.auth.caching.enabled=${NACOS_AUTH_CACHE_ENABLE:false}
nacos.core.auth.enable.userAgentAuthWhite=${NACOS_AUTH_USER_AGENT_AUTH_WHITE_ENABLE:false}
nacos.core.auth.server.identity.key=${NACOS_AUTH_IDENTITY_KEY:serverIdentity}
nacos.core.auth.server.identity.value=${NACOS_AUTH_IDENTITY_VALUE:security}
server.tomcat.accesslog.enabled=${TOMCAT_ACCESSLOG_ENABLED:false}
# default current work dir
server.tomcat.basedir=file:.
## spring security config
### turn off security
nacos.security.ignore.urls=${NACOS_SECURITY_IGNORE_URLS:/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**}
# metrics for elastic search
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
nacos.naming.distro.taskDispatchThreadCount=10
nacos.naming.distro.taskDispatchPeriod=200
nacos.naming.distro.batchSyncKeyCount=1000
nacos.naming.distro.initDataRatio=0.9
nacos.naming.distro.syncRetryDelay=5000
nacos.naming.data.warmup=true
我们看到,这里关于数据源类型部分,没有给到默认值,如果大家要用到mysql,需要通过环境变量SPRING_DATASOURCE_PLATFORM
指定为mysql
。
源码分析,要点是抓住主干把整个业务逻辑理顺,然后在必要时候去仔细研讨细节,这样就可以做到功半事倍、四两拨千斤的效果,否则一头扎进细节中会把自己搞得晕头转向,理不出头绪。