前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 Docker Multi-stage 高效构建镜像

使用 Docker Multi-stage 高效构建镜像

作者头像
dys
发布2020-08-28 17:00:35
1.6K0
发布2020-08-28 17:00:35
举报
文章被收录于专栏:性能与架构

使用 Docker 时,构建高效的 image 镜像是非常重要的,image 最好尽可能的小一点,这样实际部署的时候才能更高效。

这篇文章的目的是展示如何使用 Docker 的 multi-stage 来高效构建镜像。

下面是文章的主要内容:

  • 示例项目说明
  • 使用 Dockerfile 构建镜像
  • 这种构建方式的问题
  • Builder Pattern 是什么?
  • Builder Pattern 的问题
  • Multi-stage 构建方式是什么?
  • 使用 Multi-stage 构建镜像

1. 示例项目

非常简单的 web 应用,Angular ➕ Nodejs 实现的。

有兴趣可以试试:

代码语言:javascript
复制
// 下载项目
git clone https://github.com/bbachi/docker-multibuild-example.git

// 进入项目目录
cd WebApp

// 编译
npm run build

// 启动 nodejs server
cd ..
npm start

2. 使用 Dockerfile 构建镜像

构建时需要做的事儿:

  • 基础镜像使用 node:10
  • 拷贝所有项目源码
  • 安装前后端 nodejs server 和 Angular 相关依赖
  • 代码编译构建

Dockerfile 内容:

代码语言:javascript
复制
FROM node:10

# set the work directory
WORKDIR /usr/src/app

# copy package.json
COPY package*.json ./

# copy webapp folder
COPY WebApp/package*.json ./WebApp/

# RUN npm install for node js dependencies
RUN npm install \
   && cd WebApp \
   && npm install @angular/cli \
   && npm install

# Bundle app source
COPY . .

# builing Angular UI
RUN cd WebApp && npm run build

EXPOSE 3070

ENTRYPOINT ["node"]
CMD ["index.js"]

执行 build 命令:

代码语言:javascript
复制
docker build -t nodewebapp:v1 .

指定了一个 tag:nodewebapp:v1

需要耐心等待一会儿。

最后的输出结果:

下面启动起来:

代码语言:javascript
复制
docker run -it -d -p 3070:3070 nodewebapp:v1

启动后就可以访问了:

3. 常规构建方式的问题

使用 docker images 命令查看一下镜像列表:

1.21GB,也太大了吧。

而且这个镜像里面包含了很多无用的文件,例如一些依赖包。

4. Builder Pattern 是什么?

Builder Pattern 会使用2个 Dockerfile,一个用于开发阶段,一个用于线上产品阶段。

开发阶段的镜像中包含所有东西,产品阶段的镜像中只包含运行所需的必要内容。

可以使用一个脚本文件 dockerbuild.sh,先构建开发阶段的版本,然后拷贝出必要的层/文件,再构建出产品版本的镜像。

那么我们就需要3个文件了。

Dockerfile.dev

这是用于构建开发版本的,会包含所有东西,例如 angular、nodejs server 所需要的 node_modules。

其实这和上面的 Dockerfile 是一样的,为了节省篇幅就不重复贴了。

Dockerfile

这是用于构建产品版本的,只包含项目运行所必备的内容。

代码语言:javascript
复制
FROM node:10

# set the work directory
WORKDIR /root/

COPY package*.json ./

# copy the UI static assets
COPY dist ./WebApp/dist

# RUN npm install for node js dependencies
RUN npm install

# copy index.js file
COPY index.js .

EXPOSE 3070

ENTRYPOINT ["node"]
CMD ["index.js"]

dockerbuild.sh

这是一个脚本文件,主要有3个步骤:

(1)通过 Dockerfile.dev 构建出一个全套的镜像

(2)把镜像中的必备文件拷贝出来,放到一个本地目录

(3)基于这个目录,通过 Dockerfile 构建出产品版本的镜像

脚本内容:

代码语言:javascript
复制
#!/bin/sh
echo Building nodewebapp from Dockerfile.dev

docker build -t nodewebapp:v1 -f Dockerfile.dev .

echo Creating Conatiner Out of Image
docker container create --name extract nodewebapp:v1
docker container cp extract:/usr/src/app/WebApp/dist ./dist
docker container rm -f extract

echo Building nodewebapp version 2

docker build --no-cache -t nodewebapp:v2 .
rm ./dist

运行脚本:

代码语言:javascript
复制
sh dockerbuild.sh

会创建出2个镜像,tag 分别为 v1 和 v2。

v1 是开发版本镜像,v2 是产品版本镜像。

可以看到产品版本小了很多。

5. Builder Pattern 的问题

Builder Pattern 虽然可以让镜像变小,但也带来不便,例如:

  • 我们必须写2个Dockerfile,外加一个shell 脚本。
  • 执行脚本之后,会产生 2 个 image 镜像。
  • 必须使用 &&\ 来合并多个 RUM 命令来避免产生额外的层,容易出错。

6. 什么是 Multi-stage Build?

multi-stage 是 Docker 17.05 版本推出的构建方式,使用 multi-stage build 方式的话,可以使用多个 FROM 来构建每个阶段。

最后可以得到与 builder pattern 方式同样小的 image,但复杂度大大降低了。

Dockerfile 内容:

代码语言:javascript
复制
FROM node:10 AS ui-build
WORKDIR /usr/src/app
COPY WebApp/ ./WebApp/
RUN cd WebApp && npm install @angular/cli && npm install && npm run build

FROM node:10 AS server-build
WORKDIR /root/
COPY --from=ui-build /usr/src/app/WebApp/dist ./WebApp/dist
COPY package*.json ./
RUN npm install
COPY index.js .

EXPOSE 3070

ENTRYPOINT ["node"]
CMD ["index.js"]

构建结果:

可以看到,大小与 builder pattern 是一样的。

7. Multi-stage 优势

builder pattern 中我们需要维护 2 个Dockerfile 文件和一个 shell 脚本文件,而 multi-stage 中,在一个 Dockerfile 文件中就可以完成。

builder pattern 中,我们需要自己把必须的文件捣腾到本地文件夹,而 multi-stage 中,可以使用 --from 把文件从一个阶段复制到另一个阶段。

builder pattern 中,必须创建一个中间镜像,结果就是构建出2个image,而 multi-stage 中不需要。

小结

builder pattern 与 multi-stage 都是有效的镜像构建方式,可以根据自己的情况选择。

最后,感谢阅读,希望能对你有所帮助,最好您能动动尊贵的小手帮忙点赞转发,谢谢啦。

本文翻译整理自:

https://blog.bitsrc.io/a-guide-to-docker-multi-stage-builds-206e8f31aeb8

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA高性能架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 示例项目
  • 2. 使用 Dockerfile 构建镜像
  • 3. 常规构建方式的问题
  • 4. Builder Pattern 是什么?
  • 5. Builder Pattern 的问题
  • 6. 什么是 Multi-stage Build?
  • 7. Multi-stage 优势
  • 小结
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档