文档

使用传入参数改变构建行为

更新时间:
一键部署

尽管一个应用仅对应一个<应用名称>.release文件,但根据构建时上下文中传入的参数的不同,可以改变构建的行为,输出不同的构建结果。典型的,为不同的运行环境(比如测试环境和线上环境),打出不同内容,甚至不同类型的包。下面详细讲解基于同一份构建配置文件,根据上下文参数改变构建行为的方法。

原理:包标签及其他环境变量

在流水线上配置构建任务时,点击打开高级配置,会看到“包标签”这个配置:

包标签

包标签的默认值是default,但可以调整这个配置。构建打包得到的包,用于不同用途时,可以在上面打上相应的标签。比如部署到日常测试环境的包和部署到预发环境的包、生产环境的包,分别用testingstagingproduction来区分。流水线上的部署组件,就可以根据需要,配置取得特定标签对应的包。比如,取得testing对应的包,用来部署日常测试环境。

那么,构建组件是如何根据包标签名的不同,打出不同的包呢?在构建时,系统会把包标签的值通过环境变量的方式,传到构建的上下文中。具体来说,该环境变量的key是PACKAGE_LABEL,值就是包标签的名字。于是,构建过程就可以据此进行调整,以产生适合这个构建目的的包。调整方法详见下文描述。

除了包标签PACKAGE_LABEL这个环境变量,构建时系统还将把其他一些环境变量传入构建上下文。其中的一些,是系统自带的,详见构建传入环境变量完整列表。此外,用户还可以自定义若干key-value对:流水线上配置构建组件时的高级配置部分,在包标签设置的下方,有“+添加参数”按钮,点击可添加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_LABELtesting时候,云效会寻找所有不带前缀的键值,并与带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.testingapplication.properties.stagingapplication.properties.production,在自定义流水线中也定义了的三个的PACKAGE_LABEL的值是testingstagingproduction。然后在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_NAMEENV_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的值被分别设置为testingstagingproduction。(也就是旧版本云效中的ENV_TYPE的值)

此外,当不是自定义流水线时,用户也无法传入更多的自定义环境变量。