使用环境变量、arg参数,config声明式配置docker服务

在k8s中,我们可以使用deployment文件,hashmap文件等声明是的配置微服务。我们也希望利用docker的一些功能来做相同的事情。


一, arg 、env、env_file
arg 可以在docker文件中声明参数,被声明的参数可以被用在声明后的语句中。
arg是编译时变量,仅用于编译阶段;如果一个docker文件中由多个编译阶段,每个阶段应该由自己的arg参数。
声明arg的时候如果没有设置默认值,就需要使用--build-arg <varname>=<value>方式在build的时候提供值。
arg是build阶段的变量,Image创建后将不会存在,也就是说不能用于容器的运行。但是,可以方便的通过“docker history” 方便的查看build时使用的arg.
env 与arg对比,它是运行时变量,env变量在其声明以后就可以使用,并且在build的时候会保存下来;在容器运行的时候可以继续访问。
evn可以在声明时赋值,也可以在运行时赋值,在运行时使用-e参数赋值,例如:
$ docker run -e "env_var_name=another_value"。
Arg与ENV在命令行赋值时有这样显著的区别:

  1. 如果没有显示的声明一个arg, 在build时传递这个arg会出错。但是Env不需要再docker文件中显示的声明,可以在docker run命令中声明任意新的env变量。
  2. 编译时声明arg需要指定值,负责出错。但是env不需要,如果没有给一个env变量赋值,该变量会被认为是来自当前host的变量。

下图就描述了环境变量与arg变量的区别。


image.png

ARG和ENV可以被联合使用,因为env在build的时候可以被保存下来,所以通过联合使用ARG和ENV, 可以在build的时候传递参数,并在运行时仍旧可用。

FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER

ENV参数的来源有三种方式,上面提了两种,还有地中方式,总结如下:

  1. 显示传参, docker run -e env-key=env-vule, 或者被用于docker-compose中:
version: '3'
services:
  plex:
    image: linuxserver/plex
      environment:
        - env_var_name=another_value
  1. 获取宿主机的环境变量,通过不提供赋值:docker run -e env_var_name,或者被用于docker-compose中:
version: '3'
services:
  plex:
    image: linuxserver/plex
      environment:
        - env_var_name
  1. 使用env_file文件批量导入环境变量。
    除了手动书写环境变量,docker也支持把环境变量卸载配置文件中,批量导入。这个工作是由env_file来完成,
//docker run方式
docker run --env-file=env_file_name alpine env
//docker compose 方式
version: '3'
services:
  plex:
    image: linuxserver/plex
    env_file: env_file_name

env_file支持设置多个环境变量文件,例如下面的形式也是可以的:

nv_file:
  - ./a.env
  - ./b.env

上面个的两个环境变量是以相对路径的方式来表明文件,相对路径的起点为docer-compose文件所在的位置。
另外, Env声明的环境变量比在文件中声明的优先级高,所以手写的env环境变量总是试图替换文件中的同名变量。
env_file环境文件的格式时键值对方式,如下, #用于表明注释; 如果只设置key,表示空值,如果只设置=val 将被忽略。

# Set Rails/Rack environment
RACK_ENV=development
VAR="quoted"

注意
ARG主要用于build阶段,当成成image后,可以使用docker history查看Image中的arg信息。
ENV主要用于运行时,当启动容器后,可以使登录容器查看系统环境变量,也可以启动前,使用ocker inspect查看启动时的环境变量及设置。

二,环境变量替换
环境变量(用ENV声明),可以被作为参数用于部分的dockerfile 指令中,通常以variable_name或者{variable_name}表示,带括号的写法也可以用于{foo}_bar类似的变量替换场景。 变量的写法也支持部分bash的变量写法:{variable:-word} 如果变量未被设置,使用word作为期值。
{variable:+word} 如果设置了变量,word是变量结果,否则为空。 转移符号"\"对变量起作用,可以用来将变量变成普通文字。
以下是一个变量替换的例子:

ROM busybox
ENV FOO=/bar
WORKDIR ${FOO}   # WORKDIR /bar
ADD . $FOO       # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux

在dockerfile中环境变量替换支持以下的指令:
. ADD
. COPY
. ENV
. EXPOSE
. FROM
. LABEL
. STOPSIGNAL
. USER
. VOLUME
. WORKDIR
. ONBUILD
从上面arg和env配合使用得例子,可以看到arg也可以作为参数在docker文件中使用。

三, .Env 文件
.env 文件仅试用于docker-compose 或docker-stack, 首先它不是env_file文件,除非你把它在env_file文件下声明。其次,它是作为默认的环境变量替换与ocker-compose 必须存在于相同的补录。
也就是说,它只跟docker-compose.yaml文件有关系,它运行docker-compose.yaml时,胡主动从.env找寻需要替换的环境变量。它的格式也是key=value格式。如下,它们被用于替换comose文件以开头的变量,例如VARIABLE_NAME.

//.env文件
VARIABLE_NAME=some value
OTHER_VARIABLE_NAME=some other value, like 5

//compose文件中的引用替换
version: '3'
services:
  plex:
    image: linuxserver/plex
      environment:
        - env_var_name=${VARIABLE_NAME} # here it is

注意
对于.env文件,我们可以在不启动docker-compose的情况下,使用 docker-compose config来查看最终替换后的效果,这个非常的方便。

四, config 文件
环境变量文件外(.env, env-file),docker swarm 支持在image镜像以外定义配置属性,这些配置属性被保存到config文件中,它可以由docker config 命令来创建。
config文件类似于k8s得configMap, 它得内容不加密(不同于secret),通常被用来直接mount到容器磁盘文件系统里,它可以任意时候通过docker config添加,也可以任意时候移除。而且,config文件可以被服务之间共享。
config文件可以是string类型或者二级制类型。config文件默认在容器中mount到/<config-name>。挂在config文件得时候,可一个给文件设置权限,如果没有设置,默认权限为容器启动时得运行用户,并且所有用户可读。
config文件在运行时mount给容器,在容器关闭的时候在从容器的文件系统unmount。除了容器服务可以访问外, 作为swarm manager的node也可以访问,其它节点是不能访问config文件的。
另外一个config如果正在被服务使用,是不能用命令删除的,所以最好使用版本号、替换更新的技巧来替换和删除旧config文件。
docker config的子命令包括以下:

docker config create
docker config create [OPTIONS] CONFIG file|-
通过一个文件或者STDIN创建 config。这个命令只能在swarm得manager节点执行,需要特别注意。
options支持两个变量:
--label , -l : 给config创建一个lable
--template-driver: 将config内的模板内容最终转化为config内容的驱动。
示例1,通过STDIN输入创建config

$ printf <config> | docker config create my_config -

onakdyv307se2tl7nl20anokv

$ docker config ls

ID                          NAME                CREATED             UPDATED
onakdyv307se2tl7nl20anokv   my_config           6 seconds ago       6 seconds ago

示例2, 通过文件来创建config

$ docker config create my_config ./config.json

dg426haahpi5ezmkkj5kyl3sn

$ docker config ls

ID                          NAME                CREATED             UPDATED
dg426haahpi5ezmkkj5kyl3sn   my_config           7 seconds ago       7 seconds ago

可以看到,我们可以使用任何格式的文件来生成config,这个比k8s的configmap方便。

示例3,使用golang作为模板引擎,生成config
index.html.tmpl:
<html lang="en">
<head><title>Hello Docker</title></head>
<body>
<p>Hello {{ env "HELLO" }}! I'm service {{ .Service.Name }}.</p>
</body>
</html>
创建config

$ docker config create --template-driver golang homepage index.html.tmpl

运行docker 并设置变量

$ docker service create \
     --name hello-template \
     --env HELLO="Docker" \
     --config source=homepage,target=/usr/share/nginx/html/index.html \
     --publish published=3000,target=80 \
     nginx:alpine

最终访问容器,查看到的config文件

$ curl http://0.0.0.0:3000

<html lang="en">
  <head><title>Hello Docker</title></head>
  <body>
    <p>Hello Docker! I'm service hello-template.</p>
  </body>
</html>

总结: 可以看到使用.env , env-file 可以让环境变量的设置独立维护,并在compose文件中共享环境变量。
使用config可以向在k8s中创建configMap一样,闯将相应的配置文件,并指定mount的地址。
所以在sarming集群中我们可以利用这些元素来创建声明式的配置文件。


参考:

  1. The Compose Specification
  2. ocker ARG, ENV and .env - a Complete Guide
  3. Dockerfile reference
  4. Store configuration data using Docker Configs
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容