使用传入参数改变构建行为
尽管一个应用仅对应一个<应用名称>.release
文件,但根据构建时上下文中传入的参数的不同,可以改变构建的行为,输出不同的构建结果。典型的,为不同的运行环境(比如测试环境和线上环境),打出不同内容,甚至不同类型的包。下面详细讲解基于同一份构建配置文件,根据上下文参数改变构建行为的方法。
原理:包标签及其他环境变量
在流水线上配置构建任务时,点击打开高级配置,会看到“包标签”这个配置:
包标签的默认值是default
,但可以调整这个配置。构建打包得到的包,用于不同用途时,可以在上面打上相应的标签。比如部署到日常测试环境的包和部署到预发环境的包、生产环境的包,分别用testing
、staging
、production
来区分。流水线上的部署组件,就可以根据需要,配置取得特定标签对应的包。比如,取得testing
对应的包,用来部署日常测试环境。
那么,构建组件是如何根据包标签名的不同,打出不同的包呢?在构建时,系统会把包标签的值通过环境变量的方式,传到构建的上下文中。具体来说,该环境变量的key是PACKAGE_LABEL,值就是包标签的名字。于是,构建过程就可以据此进行调整,以产生适合这个构建目的的包。调整方法详见下文描述。
除了包标签PACKAGE_LABEL这个环境变量,构建时系统还将把其他一些环境变量传入构建上下文。其中的一些,是系统自带的,详见构建传入环境变量完整列表。此外,用户还可以自定义若干key-value对:流水线上配置构建组件时的高级配置部分,在包标签设置的下方,有“+添加参数”按钮,点击可添加key-value对儿。
构建过程可以根据以上这些环境变量进行调整。详见下文。
方法1:以PACKAGE_LABEL的值作为配置键的前缀
<应用名称>.release
中的键(比如docker.file
),可以用PACKAGE_LABEL
的值作为前缀(比如testing.docker.file
)。构建时,如果找到以当时PACKAGE_LABEL
的值(比如testing
)作为前缀的键(比如testing.docker.file
),就将以它的值(比如Dockerfile
),作为键(比如docker.file
)的值。
当PACKAGE_LABEL
为testing
时候,云效会寻找所有不带前缀的键值,并与带testing
前缀的键值,进行合并。带前缀的键值拥有更高的优先级。也就是说下面的例子中,docker.file
最终的值是Dockerfile_test
docker.file=Dockerfile
testing.docker.file=Dockerfile_test
这个方法,不仅可以让特定键在为不同环境构建时,获得不同的值,甚至可以仅在特定环境获得值。比如,如果仅日常环境使用阿里云容器服务,需要进行镜像构建,但在生产环境希望使用ECS部署,不需要进行镜像构建。那么对于这个场景,可以使用下面的写法。
code.language=java
baseline.jdk=jdk-1.7.0_51
build.tools.maven=maven2.2.1
# 使用`PACKAGE_LABEL`的前缀(testing, staging, production)的键值,只会在相应环境的构建中生效
testing.docker.file=Dockerfile
testing.docker.repo=registry.cn-hangzhou.aliyuncs.com/mynamespace/container-app
testing.docker.tag=${TIMESTAMP}
方法2:键值因为环境变量的值而改变
可以在键值中使用环境变量,例如:
docker.tag=${PACKAGE_LABEL}
还可以是组合,例如:
docker.tag=${PACKAGE_LABEL}_${TIMESTAMP}
再举个例子,使用PACKAGE_LABEL
作为maven
构建的profile
。在release
文件中配置build.command=mvn clean install -P$PACKAGE_LABEL
。并且在您的pom
文件中设置对应的profile
,在其中定义不同环境的不同行为。
方法3:构建过程中引用环境变量
比如,设置build.command=sh build.sh
,然后在build.sh
中使用环境变量的值来进行判断,并执行不同的操作。
一个具体的例子:我想在不同包的构建中,使用不同的数据库配置。假设程序运行时从application.properties
中读取数据库配置,则可以在代码库中放置三个配置文件:application.properties.testing
,application.properties.staging
,application.properties.production
,在自定义流水线中也定义了的三个的PACKAGE_LABEL的值是testing
,staging
,production
。然后在build.sh
中包含这么一行,将属于相应环境的配置文件覆盖到程序读取的文件,也就是application.properteis
。
cp application.properties.$PACKAGE_LABEL application.properties
注意:上面只是一个例子,具体的配置文件的路径以你的项目的实际情况为准。
方法4:dockerfile中如何使用变量?
云效的应用中都有个<应用名称>.release
文件,需要到release 文件中声明要传入的变量名称和值。
build.tools.docker.args=--build-arg APP_NAME=${APP_NAME} --build-arg ENV_TYPE=${ENV_TYPE} --build-arg ENV_MY_KEY=${ENV_MY_KEY}
这里面的变量有两种,一种是系统内置的变量,如APP_NAME
和ENV_TYPE
,另一种就是用户在构建组件界面中配置的自定义变量,如MY_KEY
,注意使用的时候需要加上ENV_
前缀。Dockerfile 加入如下信息:
ARG APP_NAME
ARG ENV_TYPE
ARG ENV_MY_KEY
#将传入的应用名设置成环境变量
ENV APP_NAME ${APP_NAME}
ENV ENV_MY_KEY ${ENV_MY_KEY}
#类似用法可以发挥想象,注意shell 命令必须转换成行形式。可以续行
RUN if [[ "${ENV_TYPE}" = "testing" ]]; then echo ${APP_NAME}; fi
非自定义流水线时的情况
前面讲的在流水线上配置构建组件时配置PACKAGE_LABEL的值,指的是用户可自定义的流水线。目前有些情况下,系统仍然在使用不能这样自定义的流水线。典型的,当使用分支模式时,每个环境(典型的:日常测试环境、预发环境、正式环境),都对应一条不能用户灵活配置的流水线。此时,PACKAGE_LABEL的值被分别设置为testing
,staging
,production
。(也就是旧版本云效中的ENV_TYPE的值)
此外,当不是自定义流水线时,用户也无法传入更多的自定义环境变量。