原文链接

前言

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. C#线程入门(一)

    入门 概述与概念 创建和开始使用多线程 线程同步基础 同步要领 锁和线程安全 Interrupt 和 Abort 线程状态 等待句柄 同步环境 使用多线程 单元模式和Windows Forms Bac ...

  2. [USACO08JAN]跑步Running dp

    题目描述 The cows are trying to become better athletes, so Bessie is running on a track for exactly N (1 ...

  3. 无法访问http,会强制跳到https

    1. Close Safari. 2. Delete the ~/Library/Cookies/HSTS.plist file. 3. Reopen Safari.

  4. Groovy xlsx

    如果在JMeter安装的“bin”文件夹下有Excel(xlsx)文件,则test.xlsx可以使用以下方法动态填充请求参数: 将tika-app.jar添加到JMeter Classpath 重新启 ...

  5. 同域内的两台电脑,一台访问另一台上搭建的IIS站点无法访问解决方法

    需要在搭建IIS站点的机器上,打开[高级安全Windows防火墙],新建[入站规则],添加外部允许访问的端口号即可.

  6. 有效使用Mock编写java单元测试

    Java单元测试对于开发人员质量保证至关重要,尤其当面对一团乱码的遗留代码时,没有高覆盖率的单元测试做保障,没人敢轻易对代码进行重构.然而单元测试的编写也不是一件容易的事情,除非使用TDD方式,否则编 ...

  7. JAVA对象转换JSON

    1. 把java 对象列表转换为json对象数组,并转为字符串 复制代码 代码如下: JSONArray array = JSONArray.fromObject(userlist); String ...

  8. docker 资源限制

    docker run 时使用-m指定可以使用的内存大小, 记录在cgroup配置文件中 cat /sys/fs/cgroup/memory/memory.limit_in_bytes jvm内存会超过 ...

  9. 【ACM】拦截导弹 - 0-1背包问题

    拦截导弹 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到 ...

  10. postgresql实现插入数据返回当前的主键ID

    <insert id="addUser" parameterType="com.liupan.user"> <selectKey keyPro ...