Docker 镜像多阶段构建实战总结

简介: 通常情况下,构建镜像通常会采用两种方式:1. 将全部组件及其依赖库的编译、测试、打包等流程封装进一个 Docker 镜像中。采用这种方式往往忽略了以下这些问题: - Dockefile 特别长,可维护性降低。 - 镜像的层次多,体积大,部署时间长。 - 源代码存在泄漏的风险。2. 分散到多个 Dockerfile。事先在一个 Dockerfile 将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要我们编写两个 Dockerfile 和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好地规避第一种方式存在的风险,但明显部署过程较复杂。

Docker 镜像多阶段构建实战总结

一 背景

通常情况下,构建镜像通常会采用两种方式:

  1. 将全部组件及其依赖库的编译、测试、打包等流程封装进一个 Docker 镜像中。采用这种方式往往忽略了以下这些问题:

    • Dockefile 特别长,可维护性降低。
    • 镜像的层次多,体积大,部署时间长。
    • 源代码存在泄漏的风险。
  2. 分散到多个 Dockerfile。事先在一个 Dockerfile 将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要我们编写两个 Dockerfile 和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好地规避第一种方式存在的风险,但明显部署过程较复杂。

为了解决以上这些问题,Docker v17.05 开始支持多镜像阶段构建 (multistage builds)。只需要编写一个 Dockerfile 即可。通过一段简单的 C 语言代码的编译、执行来具体演示。demo.c 的内容如下:

# include<stdio.h>
int main()
{
  printf("%s\n","This is a demo!");
  return 0;
}

二 实践步骤

2.1 只通过一个 Dockerfile 来构建【方案一】

查看对应的 Dockerfile:

FROM centos:7.8.2003

ENV VERSION 1.0

WORKDIR /demo

COPY demo.c .

RUN yum install -y gcc && \
    gcc -v
RUN gcc demo.c -o demo && \
    rm -f demo.c && \
    yum erase -y gcc && \
    cp demo /usr/local/bin/

CMD ["demo"]

感兴趣的小伙伴可以直接将上面的 Dockerfile 和 docker-entrypoint.sh 在本地构建目录创建,执行 docker build -t redis:6.0.5-buster 进行尝试。

2.2 多个 Dockerfile 实现多阶段构建【方案二】

多阶段构建一般需要多个 Dockerfile 来完成,由于我们只需要源码编译后的产物。所以我们第一个阶段可以直接使用上文中镜像构建后的产物。第二阶段的 Dockerfile 内容如下:

FROM centos:7.8.2003

ENV VERSION 1.0

WORKDIR /demo

COPY demo /usr/local/bin

CMD ["demo"]

执行构建脚本 bash build.sh, build.sh 的内容如下:

#!/bin/bash
cd stage-1
docker create --name bin demo:1.0
cd ../stage-2
docker cp bin:/usr/local/bin/demo .
docker rm -f bin
docker build -t demo:2.0 .

构建后得到的 Docker 容器运行结果:

$ docker run --rm -it demo:1.0
This is a demo!
$ docker run --rm -it demo:2.0
This is a demo!

两个容器的环境变量:

$ docker run --rm -it demo:1.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=a52af1bec0af
TERM=xterm
VERSION=1.0
HOME=/root
$ docker run --rm -it demo:2.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=f6618fd1244b
TERM=xterm
VERSION=2.0
HOME=/root

2.3 一个 Dockerfile 实现多阶段构建【方案三】

FROM centos:7.8.2003

ENV VERSION 1.0

WORKDIR /demo

COPY demo.c .

RUN yum install -y gcc && \
    gcc -v
RUN gcc demo.c -o demo && \
    rm -f demo.c && \
    yum erase -y gcc && \
    cp demo /usr/local/bin/

FROM centos:7.8.2003
COPY --from=0 /usr/local/bin/demo /usr/local/bin/demo

CMD ["demo"]

这种方式构建的 Docker 容器运行结果:

$ docker run --rm -it demo:3.0
This is a demo!
$ docker run --rm -it demo:3.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=7839b3d568db
TERM=xterm
HOME=/root

三个镜像大小对比:

$ docker images|grep demo
demo                3.0                  8766031d380a        39 seconds ago           203MB
demo                2.0                  7d9c479cb421        10 minutes ago           203MB
demo                1.0                  af331209572f        38 minutes ago           350MB

三 总结

  • 3.1 通过观察,方案一构建得到镜像远比方案二和方案三大得多,方案二和方案三的镜像一样大小。
  • 3.2 方案三并不会继承第一阶段构建的镜像的环境变量等配置,仅仅是复制了第一阶段的构建成果,需要特别注意。

四 参考文档

相关文章
|
27天前
|
运维 Kubernetes Docker
利用Docker和Kubernetes构建微服务架构
利用Docker和Kubernetes构建微服务架构
|
1月前
|
缓存 Linux 网络安全
docker的镜像无法下载如何解决?
【10月更文挑战第31天】docker的镜像无法下载如何解决?
1241 29
|
1月前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
108 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
2月前
|
缓存 监控 持续交付
|
27天前
|
存储 关系型数据库 Linux
【赵渝强老师】什么是Docker的镜像
Docker镜像是一个只读模板,包含应用程序及其运行所需的依赖环境。镜像采用分层文件系统,每次修改都会以读写层形式添加到原只读模板上。内核bootfs用于加载Linux内核,根镜像相当于操作系统,上方为应用层。镜像在物理存储上是一系列文件的集合,默认存储路径为“/var/lib/docker”。
|
1月前
|
存储 监控 Linux
docker构建镜像详解!!!
本文回顾了Docker的基本命令和管理技巧,包括容器和镜像的增删改查操作,容器的生命周期管理,以及如何通过端口映射和数据卷实现容器与宿主机之间的网络通信和数据持久化。文章还详细介绍了如何使用Docker部署一个简单的Web应用,并通过数据卷映射实现配置文件和日志的管理。最后,文章总结了如何制作自定义镜像,包括Nginx、Python3和CentOS镜像,以及如何制作私有云盘镜像。
126 2
|
1月前
|
关系型数据库 MySQL Docker
docker环境下mysql镜像启动后权限更改问题的解决
在Docker环境下运行MySQL容器时,权限问题是一个常见的困扰。通过正确设置目录和文件的权限,可以确保MySQL容器顺利启动并正常运行。本文提供了多种解决方案,包括在主机上设置正确的权限、使用Dockerfile和Docker Compose进行配置、在容器启动后手动更改权限以及使用 `init`脚本自动更改权限。根据实际情况选择合适的方法,可以有效解决MySQL容器启动后的权限问题。希望本文对您在Docker环境下运行MySQL容器有所帮助。
104 1
|
2月前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
本文介绍了Docker和Kubernetes在构建高效微服务架构中的应用,涵盖基本概念、在微服务架构中的作用及其实现方法。通过具体实例,如用户服务、商品服务和订单服务,展示了如何利用Docker和Kubernetes实现服务的打包、部署、扩展及管理,确保微服务架构的稳定性和可靠性。
95 7
|
1月前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【10月更文挑战第22天】随着云计算和容器技术的快速发展,微服务架构逐渐成为现代企业级应用的首选架构。微服务架构将一个大型应用程序拆分为多个小型、独立的服务,每个服务负责完成一个特定的功能。这种架构具有灵活性、可扩展性和易于维护的特点。在构建微服务架构时,Docker和Kubernetes是两个不可或缺的工具,它们可以完美搭档,为微服务架构提供高效的支持。本文将从三个方面探讨Docker和Kubernetes在构建高效微服务架构中的应用:一是Docker和Kubernetes的基本概念;二是它们在微服务架构中的作用;三是通过实例讲解如何使用Docker和Kubernetes构建微服务架构。
62 6
|
14天前
|
JavaScript Linux 持续交付
深入探索容器化技术——Docker 的实战应用
深入探索容器化技术——Docker 的实战应用
44 0