当前位置: 首页 > news >正文

dockerfile中多个FROM指令的意义(multistage)

从docker17.05版本开始,dockerfile中允许使用多个FROM指令(multistage)。这是docker17.05版本的release note:https://docs.docker.com/engine/release-notes/17.05/

这个特性有什么实际的应用场景?最近需要做一个docker镜像,就用到了该特性。简单来说就是可以使编译环境和发布环境分离

使用多FROM指令可以完成多阶段编译。每一条 FROM 指令都是一个构建阶段,多条 FROM 就是多阶段构建,虽然最后生成的镜像只能是最后一个阶段的结果,但是,能够将前置阶段中产生的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。

比如下面这种场景:

我们要构建一个c++应用程序的镜像,这个c++程序依赖了很多第三方库,那么我们的构建过程大概如下:

# c++语言环境基础镜像
FROM centos:7.0.3

#安装编译工具,gcc g++ gdb cmake ==

#安装第三方库

# 将源码拷贝到镜像中
COPY project /build/

# 指定工作目录
WORKDIR /build

# 使用make编译代码,生成可执行程序


# 指定容器运行时入口程序 server
ENTRYPOINT ["/build/server"]

这样会导致我们编译出来的镜像非常庞大,而我们最终要用的只是一个可执行程序以及它运行时依赖的动态库,不需要编译工具以及编译时依赖的第三方库的源代码。有了多FROM指令后,我们就可以这样实现这个过程:在基础镜像上安装编译工具->下载第三方库源代码->编译安装第三方库->编译自己的模块代码->将编译好的可执行文件拷贝到新的镜像中->将运行时依赖的动态库拷贝到新镜像中->修改新镜像中的环境变量,使之指向运行时依赖库的位置。dockerfile修改如下:

# c++语言环境基础镜像
FROM centos:7.0.3 AS build_base

#安装编译工具,gcc g++ gdb cmake ==

#安装第三方库

# 将源码拷贝到镜像中
COPY project /build/

# 指定工作目录
WORKDIR /build

# 编译镜像时,运行 make生成可执行程序


# 指定容器运行时入口程序 server
ENTRYPOINT ["/build/server"]

#这里重新启动一个镜像,将编译好的可执行文件和运行依赖库拷贝过来就可以了
FROM centos:7.0.3
COPY --from build_base ***.so .
COPY --from build_base /build/server .
#修改环境变量,使之指向动态库的目录
ENV LD_LIBRARY_PATH=./

我们最终用到的镜像就是最后一个FROM后生成的镜像,前边的FROM只是起到了一个辅助产生编译环境的作用。这也是多FROM特性比较常用的一个场景。

相关文章:

  • dockerfile实战:使用dockerfile制作c/c++程序docker镜像
  • c++11并发编程一(std::thread之:thread构造函数)
  • c++11并发编程二(std::thread之:线程入口函数)
  • 身份证校验码计算:根据身份证前17位计算第18位校验码-c++实现
  • c++11并发编程三(使用std::future、std::promise获取线程返回值)
  • mysql删除表时报错:Cannot delete or update a parent row: a foreign key constraint fails 解决办法
  • mysql C API 预处理接口
  • C++多个头文件中可以定义同名的namespace吗?
  • 解决mysql 1602错误:Error Duplicate entry ‘***‘ for key ‘PRIMARY‘
  • 编写Makefile:编译当前文件夹以及子文件夹下所有的ccpp文件并生成可执行文件
  • c++ - boost::program_options:如何忽略未知参数?
  • C++并发编程四:(std::mutex详解)
  • C++ double 转string 精度保持到小数点后15位
  • k8s pod OOMKilled 错误原因
  • 解决 OpenCV Error: Insufficient memory (Failed to allocate 3221225472 bytes) in cv::OutOfMemoryError
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • Consul Config 使用Git做版本控制的实现
  • JavaScript 奇技淫巧
  • LintCode 31. partitionArray 数组划分
  • Linux下的乱码问题
  • Promise初体验
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • vue2.0项目引入element-ui
  • Vue--数据传输
  • 多线程事务回滚
  • 基于Android乐音识别(2)
  • 前端js -- this指向总结。
  • 前嗅ForeSpider教程:创建模板
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (23)Linux的软硬连接
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • ./和../以及/和~之间的区别
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .gitignore文件_Git:.gitignore
  • .Net 6.0 处理跨域的方式
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .netcore 如何获取系统中所有session_ASP.NET Core如何解决分布式Session一致性问题
  • .net中我喜欢的两种验证码
  • @Autowired @Resource @Qualifier的区别
  • @JSONField或@JsonProperty注解使用
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • []新浪博客如何插入代码(其他博客应该也可以)
  • [2015][note]基于薄向列液晶层的可调谐THz fishnet超材料快速开关——
  • [2019.3.20]BZOJ4573 [Zjoi2016]大森林
  • [23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
  • [AIGC] SQL中的数据添加和操作:数据类型介绍
  • [bzoj1901]: Zju2112 Dynamic Rankings
  • [CISCN2019 华东南赛区]Web11
  • [Docker]五.Docker中Dockerfile详解
  • [HDU5685]Problem A
  • [IE编程] IE 是如何决定Accept-Language 属性的
  • [Java][Liferay] File system in liferay