原文链接

前言

reference:https://vsupalov.com/docker-build-time-env-values/

很多时候,我们需要在docker镜像中加入环境变量,本人了解的有2种方法可以做到

第一种

使用docker run --env VARIABLE=VALUE image:tag直接添加变量,适用于直接用docker启动的项目

root@ubuntu:/home/vickey/test_build# docker run --rm -it --env TEST=2 ubuntu:latest
root@2bbe75e5d8c7:/# env |grep "TEST"
TEST=2

第二种

使用dockerfile的ARGENV添加变量,适用于不能用docker run命令启动的项目,如k8s

ARG只在构建docker镜像时有效(dockerfile的RUN指令等),在镜像创建了并用该镜像启动容器后则无效(后面有例子验证)。但可以配合ENV指令使用使其在创建后的容器也可以生效。

ARG buildtime_variable=default_value        # if not set default_value buildtime_variable would be set ''
ENV env_var_name=$buildtime_variable

在构建映像时,可以使用--build-arg buildtime_variable=other_value覆盖dockerfile里的变量值default_value

$ docker build --build-arg buildtime_variable=other_value --tag image:tag

多阶段构建

但是有时我们只是临时需要环境变量或文件,最后的镜像是不需要的这些变量的,设置ARG和ENV值就会在Docker镜像中留下痕迹,比如保密信息等。多阶段构建可以用来去掉包含保密信息的镜像。

  • dockerfile
FROM ubuntu as intermediate     # 为第一阶段构建设置别名,在第二阶段引用
ARG TEST=deault_value # 设置环境变量
ENV ENV_TEST=$TEST # 设置环境变量
RUN echo test > /home/test.txt
RUN cat /home/test.txt # 查看文件是否正常
RUN env
RUN env |grep TEST # 查看环境变量是否已设置 FROM ubuntu
COPY --from=intermediate /home/test.txt /home/another_test.txt # 将第一阶段生成的文件拷贝到第二阶段镜像中
RUN cat /home/another_test.txt # 查看拷贝的文件是否正常
RUN env
RUN env |grep TEST # 查看环境变量是否已设置
  • 多阶段构建
root@ubuntu:/home/vickey/test_build# docker build --build-arg TEST=2 -t ubuntu:test-multi-build --no-cache -f ./dockerfile .
Sending build context to Docker daemon 2.56kB
Step 1/12 : FROM ubuntu as intermediate
---> 94e814e2efa8
Step 2/12 : ARG TEST=deault_value
---> Running in 7da9180a6311
Removing intermediate container 7da9180a6311
---> 7e8420f3ecf2
Step 3/12 : ENV ENV_TEST=$TEST
---> Running in 256788d179ce
Removing intermediate container 256788d179ce
---> 11cf4e0581d9
Step 4/12 : RUN echo test > /home/test.txt
---> Running in c84799ba3831
Removing intermediate container c84799ba3831
---> f578ca5fe373
Step 5/12 : RUN cat /home/test.txt
---> Running in dbf8272fd10c
test
Removing intermediate container dbf8272fd10c
---> 9f8720732878
Step 6/12 : RUN env
---> Running in 9050cd9e36c9
HOSTNAME=9050cd9e36c9
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
TEST=2
PWD=/
ENV_TEST=2
Removing intermediate container 9050cd9e36c9
---> f1f4daf42cc0
Step 7/12 : RUN env |grep TEST
---> Running in 1cc7968144f5
TEST=2
ENV_TEST=2
Removing intermediate container 1cc7968144f5
---> c6d390887082
Step 8/12 : FROM ubuntu
---> 94e814e2efa8
Step 9/12 : COPY --from=intermediate /home/test.txt /home/another_test.txt
---> 27480a945fab
Step 10/12 : RUN cat /home/another_test.txt
---> Running in de1f5a999fe1
test
Removing intermediate container de1f5a999fe1
---> 16c630eb6b1b
Step 11/12 : RUN env
---> Running in d13becd5ae77
HOSTNAME=d13becd5ae77
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
Removing intermediate container d13becd5ae77
---> ea52a6e9a7b2
Step 12/12 : RUN env |grep TEST
---> Running in 7ef585772e9a
The command '/bin/sh -c env |grep TEST' returned a non-zero code: 1

从dockerfile的注释和构建时对应步骤的输出可以看出,第一阶段的环境变量和文件,在第二阶段复制了文件后,环境变了没有复制过来(最后一步报错了,就是因为环境变量不存在了),正好达到我们想要的结果---将环境变量保密信息等删除而保留了我们想要的文件。

验证第二种方法实例(可忽略)

  • 同一目录下创建个dockerfile和至少一个文件
root@ubuntu:/home/vickey/test_build# tree -L 2
.
├── dockerfile
└── whatever
0 directories, 2 files
root@ubuntu:/home/vickey/test_build# cat dockerfile
FROM ubuntu

dockfile

FROM ubuntu
  • docker构建镜像
root@ubuntu:/home/vickey/test_build# docker build --build-arg TEST=1 -t ubuntu:test-build -f ./dockerfile .
Sending build context to Docker daemon 2.56kB
Step 1/1 : FROM ubuntu
---> 94e814e2efa8
[Warning] One or more build-args [TEST] were not consumed
Successfully built 94e814e2efa8
Successfully tagged ubuntu:test-build
root@ubuntu:/home/vickey/test_build# docker images |grep test-build
ubuntu test-build 94e814e2efa8 3 months ago 88.9MB
  • 用镜像启动个容器
root@ubuntu:/home/vickey/test_build# docker run --rm -it ubuntu:test-build
root@383c30a1d6f5:/# env
HOSTNAME=383c30a1d6f5
PWD=/
HOME=/root
TERM=xterm
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
_=/usr/bin/env
root@383c30a1d6f5:/# env|grep "TEST"
root@383c30a1d6f5:/#

发现并没有构建镜像时--build-arg TEST=1传入的变量,因为构建时有个[Warning] One or more build-args [TEST] were not consumed, 需要在dockfile里面引用TEST才行。

  • 在dockerfile加入变量
FROM ubuntu
ARG TEST
  • 重新构建并创建容器
root@ubuntu:/home/vickey/test_build# docker build --build-arg TEST=1 -t ubuntu:test-build -f ./dockerfile .
Sending build context to Docker daemon 2.56kB
Step 1/2 : FROM ubuntu
---> 94e814e2efa8
Step 2/2 : ARG TEST
---> Running in f9ccda7b3a4b
Removing intermediate container f9ccda7b3a4b
---> dc95b444ffc5
Successfully built dc95b444ffc5
Successfully tagged ubuntu:test-build
root@ubuntu:/home/vickey/test_build# docker run --rm -it ubuntu:test-build
root@370dd8b3d2ca:/# env
... ignore...
root@370dd8b3d2ca:/# env|grep "TEST"
root@370dd8b3d2ca:/#

发现没有warning了,但还是没有变量TEST,因为ARG只在构建docker镜像时有效,在镜像创建了并用该镜像启动容器后则无效。但可以配合ENV指令使用使其在创建后的容器也可以生效。下面加入ENV看看

  • 在dockerfile加入ENV
FROM ubuntu
ARG TEST
ENV ENV_TEST=$TEST
  • 再次构建并启动容器
root@ubuntu:/home/vickey/test_build# docker build --build-arg TEST=1 -t ubuntu:test-build -f ./dockerfile .
Sending build context to Docker daemon 2.56kB
Step 1/3 : FROM ubuntu
---> 94e814e2efa8
Step 2/3 : ARG TEST
---> Using cache
---> dc95b444ffc5
Step 3/3 : ENV ENV_TEST=$TEST
---> Running in d8cd0014b36b
Removing intermediate container d8cd0014b36b
---> ebd198fcb586
Successfully built ebd198fcb586
Successfully tagged ubuntu:test-build
root@ubuntu:/home/vickey/test_build# docker run --rm -it ubuntu:test-build
root@f9dd6cf0bb47:/# env|grep "TEST"
ENV_TEST=1

很好,这时dockerfile的ARG变量TEST已经传给ENV变量ENV_TEST了。我们已经可以使用docker构建时传入的变量了。

在docker镜像中加入环境变量的更多相关文章

  1. 解析docker中的环境变量使用和常见问题解决

    docker容器中的环境变量 docker可以为容器配置环境变量.配置的途径有两种: 在制作镜像时,通过ENV命令为镜像增加环境变量.在容器启动时使用该环境变量. 在容器启动时候,通过参数配置环境变量 ...

  2. 更优雅的配置:docker/运维/业务中的环境变量

    目录 docker-compose 环境变量 .env 文件 env_file docker stack 不支持基于文件的环境变量 envsubst envsubst.py 1. 使用行内键值对 2. ...

  3. Xcode 8:在 Active Compilation Conditions 中自定义环境变量

    来源:没故事的卓同学 链接:http://www.jianshu.com/p/96b36360bb2d 在Xcode 7我们在 OTHER_SWIFT_FLAGS中配置环境变量.但是有一个不爽的地方就 ...

  4. bootargs中的环境变量说明和一些常用的uboot命令

    bootargs中的环境变量说明和一些常用的uboot命令 一些常见的uboot命令:Help [command]在屏幕上打印命令的说明Boom [addr]启动在内存储器的内核Tftpboot通过t ...

  5. python 程序中设置环境变量

    python 中调用系统命令有三种方法: 1.os.system('command') ,这个方法是直接调用标准C的system() 函数,仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息 ...

  6. 关于Lumen / Laravel .env 文件中的环境变量是如何生效的

    .env 文件包含默认环境变量,我们还可自定义其他任何有效的变量,并可通过  调用 env() 或 $_SERVER 或 $_ENV  来获取该变量.那么env()是如何加载到这些变量的呢?在Lume ...

  7. 怎样在Ubuntu中设置环境变量

    首先启动终端. 单击屏幕左上角的Ubuntu图标,在弹出的窗口中点击搜索栏,输入"terminal", 稍等片刻,终端就会赫然在目!二话不说,直接点击!     然后打开环境设置文 ...

  8. 在PHP中管理环境变量

    在PHP中管理环境变量 现在我们都能用很多个编程语言开发,当我开始熟悉PHP时,我会忽略其它语言的特点.我用过其他语言(比如Node.js),但在PHP中没有看到一种轻松控制设置环境变量的方法,特别是 ...

  9. 深入理解Java中配置环境变量

    深入理解Java中配置环境变量 配置的目的: 本来只在安装JDK的bin目下能运行java.exe,javac.exe,jar.exe,javadoc.exe等Java开发工具包命令,我们现在想让在所 ...

随机推荐

  1. MCP|DYM|Quantitative mass spectrometry to interrogate proteomic heterogeneity in metastatic lung adenocarcinoma and validate a novel somatic mutation CDK12-G879V (利用定量质谱探究转移性肺腺瘤的蛋白质组异质性及验证新体细胞突变)

    文献名:Quantitative mass spectrometry to interrogate proteomic heterogeneity in metastatic lung adenoca ...

  2. IOS Swift UITableViewcontroller实现点击空白处隐藏键盘

    在ios开发中,为了方便,我们经常使用UITableViewcontroller,比如搜索界面为了方便可能更多的使用UITableViewcontroller,那么问题就来了,当我点击搜索框的时候会弹 ...

  3. Maven中常用插件的配置

    在Maven项目的pom.xml文件中配置插件信息,使用<build></build>标签 1.配置JDK版本插件和Tomcat版本插件 <build> <! ...

  4. Java 引用类型

    若内存中一个对象没有任何引用的话,则可以认为该对象已经不再使用了,可以成为GC的候选.不过由于垃圾回收器的运行时间不确定,可被垃圾回收的对象的实际被回收时间是不确定的.对于一个对象来说,只要有引用的存 ...

  5. shell脚本——循环和函数

    1.打印一个等腰三角形 ` ;do -$i]` ;do echo -n ' ' done -]` ;do echo -n '*' done echo done 2.打印99乘法表 #!/bin/bas ...

  6. 《SQL 进阶教程》 自连接排序

    子查询所做的,是计算出价格比自己高的记录的条数并将其作为自己的位次 -- 自连接实现排序功能SELECT P1.name,P1.price,(SELECT COUNT(P2.price)FROM Pr ...

  7. vue中v-bind绑定样式

    近来发现v-bind绑定样式的两个好玩的栗子 可以直接绑定到一个样式对象,让模板更清晰: <div id="app"> <div v-bind:style=&qu ...

  8. angularJs1.x 版本中 uib-tabset 如何默认激活不同的标签页

     <uib-tabset> 默认有个active属性,根据官方文档,active的默认值是0,也就是说,默认显示索引为0的标签页,可以通过修改这个值来默认显示不同的索引的标签页. 示例: ...

  9. 牛客假日团队赛1B.便便传送门(一)

    链接:https://ac.nowcoder.com/acm/contest/918/B 题意: Farmer John最讨厌的农活是运输牛粪.为了精简这个过程,他制造了一个伟大的发明:便便传送门!与 ...

  10. 加注解时插入权限切面@EnableDataSecurity

    import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.an ...