我刚刚完成了我的角度应用程序的基本管道,它在docker中的Node图像中运行。因此,该过程如下工作:推送到Gitlab> Hook to Jenkins Build>部署脚本到docker build
图片并推送到Quay>发布脚本以提示Rancher服务升级容器并刷新图像>完整。
现在,我遇到的问题是基本节点图像非常大,这意味着当我推动一个简单的更改时,需要很长时间才能完成构建管道(约8分钟)。对于每一个微小的变化来说这似乎都是不合理的,对Quay的推动以及随后向Rancher平台的发布意味着我要向码头移动250mb,向Rancher移动250mb。
我有几个"微服务"计划部署,但如果每次我想将一个部署到开发环境并每次移动那么多的数据,它似乎有点反效果......我做错了什么,我错过了什么,是否有任何构建/部署/托管基于容器的服务时的最佳实践指南?
答案 0 :(得分:5)
首先介绍图像,构建,注册表和客户端的信息。
Docker图像构建与图层一起使用。 Dockerfile
中的每个步骤都会提交一个覆盖在前一个上面的图层。
FROM node ---- a6b9ffdcf522
RUN apt-get update -y --- 72886b467bd2
RUN git clone whatever -- 430615b3487a
RUN npm install - 4f8ddac8d3b5 mynode:latest
构成图像的每个图层都由sha256校验和单独标识。 IMAGE ID
中的docker images -a
是一个简短的片段。
在构建主机上运行dockviz images -t
可以让您更好地了解可以构建的图层树。在构建正在运行时,您可以看到分支增长,然后最终层最终被标记,但该层保留在树中并保持与其父级的链接。
默认情况下,每个构建步骤都会缓存Docker构建。如果泊坞窗文件中的RUN
命令没有更改,或者您正在复制的COPY
源文件未被更改,那么该构建步骤不需要再次运行。该层保持不变,sha256校验和ID和docker尝试构建下一层。
当docker到达需要重建的步骤时,图像"树" dockviz present将分支以创建具有新校验和的新图层。之后的任何步骤都需要再次运行并在新分支上创建一个图层。
注册管理机构也了解这种分层。如果您只更改新标记图像中的最顶层,那么这是唯一需要上传到注册表的层(There are caveats to this, it works best with a recent docker-1.10.1+ and registry 2.3+)注册表已经拥有大部分图像的副本构成你的新图像"并且只需要发送新图层。
Docker注册表客户端以相同的方式处理图层。拉动图像时,它实际上会下载构成图像的各个图层(blob)。您可以在docker pull
或docker run
新图片时打印的图片ID列表中看到此信息。同样,如果大多数图层都相同,那么更新只需要下载已更改的最顶层,节省宝贵的时间。
所以你想要关注的事情是
节省时间的主要方法是首先没有任何事情要做。 图像中的数据越少越好。
如果您可以避免使用完整的操作系统,请执行此操作。当您可以在busybox
或alpine
图片上运行应用时,它会让Docker众神微笑。 alpine + node.js build小于50MB。 Go二进制文件也是最小化大小的一个很好的例子。它们可以静态编译,并且没有依赖关系,因此甚至可以在空白scratch
图像上运行。
将最常更改的文物(很可能是您的代码)作为Dockerfile
中的后期条目,这一点非常重要。如果构建必须为一个小文件更改更新完整的50MB数据,那么构建将变慢,这会使构建步骤的缓存无效。
总会有一些更改使整个缓存失效(例如更新基础node
图像)。这些你只需要偶尔住一下。
不经常更新的构建中的任何其他内容都应该转到Dockerfile
的顶部。
尽管从Docker 1.10开始已经对图像校验和进行了一定程度的修复,但使用公共父图像可以保证从使用FROM
的图像开始,您将从相同的共享图像ID开始。
在Docker 1.10之前,图片ID只是一个随机的uuid。如果您在多个主机上运行构建,则可以根据构建它们的主机来使图层无效和替换。即使这些层实际上是同一件事。
当您拥有多个服务且多个Dockerfile
大致相同时,常用父图像也会有所帮助。每当您开始在多个Dockerfile
中重复构建步骤时,请将这些步骤拉出到公共父图像中,以便在所有服务之间明确共享图层。您基本上已经使用node
图片作为基础来获取此功能。
如果在代码部署每个构建之后运行npm install
并且您有许多依赖项,那么npm install
会导致大量重复工作,而实际上每个构建都没有多少变化。在代码更改之前建立node_modules
工作流程可能是值得的。然后npm install
只需在package.json
更新
FROM node
WORKDIR /app
COPY package.json /app/package.json
RUN npm install && rm -rf ~/.npm
COPY . /app/
CMD [ "node", "/app/server.js" ]
如果你依赖带有本机模块的npm包,你有时需要在容器中安装一个完整的构建链来运行npm install
。现在,分阶段构建可以轻松地从运行映像中分离构建映像。
FROM node:8 AS build
WORKDIR /build
RUN apt-get update \
&& apt-get install build-essential;
COPY package.json /build/package.json
RUN npm install; \
&& rm -rf ~/.npm;
# Stage 2 app image
FROM node:8-slim
WORKDIR /app
COPY --from=build /build/node_modules /app/node_modules
COPY . /app/
CMD [ "node", "/app/server.js" ]
确保您的构建主机具有ssd和良好的互联网连接,因为将是您必须进行完全重建的时间,因此越快越好。 AWS通常运行良好,因为您提取和推送的软件包和映像也可能托管在AWS上。 AWS还仅为存储成本提供映像注册服务(ECR)。