由于已经有好几年了,该站点使用Jekyll静态站点生成器。 生成整个站点大约需要15分钟。 不久前,我决定设置Gulp以最小化HTML,以加快读者的页面浏览速度。 这项更改使构建时间增加了大约10分钟,总共约25分钟,这是很长的时间...太长了。 我想减少构建时间,所以我决定尝试一下。
初始状态
Docker映像用于构建站点。 该图像基于JRuby图像 :Ruby是Jekyll的基本技术堆栈,而Java是AsciiDoctor的PlantUML插件所必需的。
在该图像中,设置了以下堆栈:
- 邦德勒
- Node.js
- 古尔普
FROM jruby:9
RUN gem install bundler \ (1)
&& curl -sL https://deb.nodesource.com/setup_9.x | bash - \ (2)
&& apt-get install -y nodejs graphviz \ (3)
&& npm install -g gulp-cli (4)
- 安装捆绑器
- 将Node.js存储库添加到APT
- 安装Node.js和Graphviz(这是PlantUML依赖项)
- 安装Gulp命令行界面
该图像被上传到私有Docker注册表中,供站点生成使用。
GitLab构建文件将安装必需的Gems和NPM软件包。 看起来如下:
image:registry.gitlab.com/nfrankel/nfrankel.gitlab.io:latest
before_script:
-bundle install (1)
-npm set progress=false && npm install (2)
pages:
stage:deploy
script:gulp
only:
-master
- 从Gemfile安装宝石
package.json
- 安装NPM软件包
问题在于,每次构建站点时,都需要安装Gems和NPM软件包。 这是一个问题,因为即使该站点至少每周构建一次,依存关系也相当稳定。 但是,安装成本将在每次构建期间支付。
分层所有的东西!
将以上依赖项从构建文件移至Docker层似乎是一个好主意。
第一步是将先前的图像移动到另一个位置, 例如, registry.gitlab.com/nfrankel/nfrankel.gitlab.io/base:latest
: registry.gitlab.com/nfrankel/nfrankel.gitlab.io/base:latest
。
第二步,在项目文件夹中创建第二个Dockerfile:
FROM registry.gitlab.com/nfrankel/nfrankel.gitlab.io/base:latest
ADD Gemfile /builds/nfrankel/nfrankel.gitlab.io/Gemfile (1)
ADD Gemfile.lock /builds/nfrankel/nfrankel.gitlab.io/Gemfile.lock (1)
ADD package.json /builds/nfrankel/nfrankel.gitlab.io/package.json (1)
ADD package-lock.json /builds/nfrankel/nfrankel.gitlab.io/package-lock.json (1)
RUN cd /builds/nfrankel/nfrankel.gitlab.io \
&& bundle install\ (2)
&& npm set progress=false \
&& npm install (3)
- 将必要的文件添加到上下文
- 安装宝石
- 安装NPM软件包
经验丰富的Docker用户可能会意识到,在构建映像时,所有文件夹的内容都会发送到守护程序。 但是,仅需要上述4个文件。
为防止这种情况,第三步是创建一个.dockerignore
文件,以仅发送那些文件:
** (1)
!Dockerfile (2)
!Gemfile (3)
!Gemfile.lock (3)
!package.json (3)
!package-lock.json (3)
- 忽略每个文件
Dockerfile
- 本身
- 添加所需文件
现在可以构建依赖项的映像:
docker build-t registry.gitlab.com/nfrankel/nfrankel.gitlab.io/withdeps:latest .
最后,让我们更新GitLab构建文件:
image:registry.gitlab.com/nfrankel/nfrankel.gitlab.io/withdeps:latest (1)
(2)
pages:
stage:deploy
script:gulp
only:
-master
- 使用依赖项引用Docker映像
- 删除依赖项获取步骤
结论
首先是第一件事:新的构建并没有提供任何明显的速度改进...主要是因为大部分构建时间都花在了最小化HTML上,而不是获取依赖项。 从好的方面来说,构建日志文件要短得多,并且更易于分析。
当然,此过程不仅是特定于Jekyll的,它也可以通过Maven构建来完成。
翻译自: https://blog.frankel.ch/layering-docker-images-dependencies/