内容简介:最近在调整公司项目的 CI,目前主要使用 GitLab CI,在尝试多阶段构建中踩了点坑,然后发现了一些有意思的玩意本文参考:公司目前主要使用 GitLab CI 作为主力 CI 构建工具,而且由于机器有限,我们对一些包管理器的本地 cache 直接持久化到了本机;比如 maven 的
最近在调整公司项目的 CI,目前主要使用 GitLab CI,在尝试多阶段构建中踩了点坑,然后发现了一些有意思的玩意
本文参考:
一、起因
公司目前主要使用 GitLab CI 作为主力 CI 构建工具,而且由于机器有限,我们对一些包管理器的本地 cache 直接持久化到了本机;比如 maven 的 .m2
目录,nodejs 的 .npm
目录等;虽然我们创建了对应的私服,但是在 build 时毕竟会下载,所以当时索性调整 GitLab Runner 在每个由 GitLab Runner 启动的容器中挂载这些缓存目录(GitLab CI 在 build 时会新启动容器运行 build 任务);今天调整 nodejs 项目浪了一下,直接采用 Dockerfile 的 multi-stage build 功能进行 “Build => Package(docker image)” 的实现,基本 Dockerfile 如下
FROM gozap/build as builder COPY . /xxxx WORKDIR /xxxx RUN source ~/.bashrc \ && cnpm install \ && cnpm run build FROM gozap/nginx-react:v1.0.0 LABEL maintainer="mritd <mritd@linux.com>" COPY --from=builder /xxxx/public /usr/share/nginx/html EXPOSE 80 STOPSIGNAL SIGTERM CMD ["nginx", "-g", "daemon off;"]
本来这个 cnpm
命令是带有 cache 的( 见这里
),不过运行完 build 以后发现很慢,检查宿主机 cache 目录发现根本没有 cache…然后突然感觉
仔细想想,情况应该是这样事儿的…
+------------+ +-------------+ +----------------+ | | | | | | | | | build | | Multi-stage | | Runner +--------------->+ conatiner +----------->+ Build | | | | | | | | | | | | | +------------+ +------+------+ +----------------+ ^ | | | | +------+------+ | | | Cache | | | +-------------+
后来经过查阅文档,发现 Dockerfile 是有扩展语法的(当然最终我还是没用),具体请见
IF ELSE
语法、直接挂载宿主机目录等功能
二、开启 Dockerfile 扩展语法
2.1、开启实验性功能
目前这个扩展语法还处于实验性功能,所以需要配置 dockerd 守护进程,修改如下
ExecStart=/usr/bin/dockerd -H unix:// \ --init \ --live-restore \ --data-root=/data/docker \ --experimental \ --log-driver json-file \ --log-opt max-size=30m \ --log-opt max-file=3
主要是 --experimental
参数,参考 官方文档
;
同时在 build 前声明 export DOCKER_BUILDKIT=1
变量
2.2、修改 Dockerfile
开启实验性功能后,只需要在 Dockerfile 头部增加 # syntax=docker/dockerfile:experimental
既可;为了保证稳定性,你也可以指定具体的版本号,类似这样
# syntax=docker/dockerfile:1.1.1-experimental FROM tomcat
2.3、可用的扩展语法
-
RUN --mount=type=bind
这个是默认的挂载模式,这个允许将上下文或者镜像以可都可写/只读模式挂载到 build 容器中,可选参数如下(不翻译了)
Option | Description |
---|---|
target
(required) |
Mount path. |
source
|
Source path in the from
. Defaults to the root of the from
. |
from
|
Build stage or image name for the root of the source. Defaults to the build context. |
rw
, readwrite
|
Allow writes on the mount. Written data will be discarded. |
-
RUN --mount=type=cache
专用于作为 cache 的挂载位置,一般用于 cache 包管理器的下载等
Option | Description |
---|---|
id
|
Optional ID to identify separate/different caches |
target
(required) |
Mount path. |
ro
, readonly
|
Read-only if set. |
sharing
|
One of shared
, private
, or locked
. Defaults to shared
. A shared
cache mount can be used concurrently by multiple writers. private
creates a new mount if there are multiple writers. locked
pauses the second writer until the first one releases the mount. |
from
|
Build stage to use as a base of the cache mount. Defaults to empty directory. |
source
|
Subpath in the from
to mount. Defaults to the root of the from
. |
Example: cache Go packages
# syntax = docker/dockerfile:experimental FROM golang ... RUN --mount=type=cache,target=/root/.cache/go-build go build ...
Example: cache apt packages
# syntax = docker/dockerfile:experimental FROM ubuntu RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt \ apt update && apt install -y gcc
-
RUN --mount=type=tmpfs
专用于挂载 tmpfs 的选项
Option | Description |
---|---|
target
(required) |
Mount path. |
-
RUN --mount=type=secret
这个类似 k8s 的 secret,用来挂载一些不想打入镜像,但是构建时想使用的密钥等,例如 docker 的 config.json
,S3 的 credentials
Option | Description |
---|---|
id
|
ID of the secret. Defaults to basename of the target path. |
target
|
Mount path. Defaults to /run/secrets/
+ id
. |
required
|
If set to true
, the instruction errors out when the secret is unavailable. Defaults to false
. |
mode
|
File mode for secret file in octal. Default 0400. |
uid
|
User ID for secret file. Default 0. |
gid
|
Group ID for secret file. Default 0. |
Example: access to S3
# syntax = docker/dockerfile:experimental FROM python:3 RUN pip install awscli RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://... ...
注意: buildctl
是 BuildKit 的命令,你要测试的话自己换成 docker build
相关参数
$ buildctl build --frontend=dockerfile.v0 --local context=. --local dockerfile=. \ --secret id=aws,src=$HOME/.aws/credentials
-
RUN --mount=type=ssh
允许 build 容器通过 SSH agent 访问 SSH key,并且支持 passphrases
Option | Description |
---|---|
id
|
ID of SSH agent socket or key. Defaults to “default”. |
target
|
SSH agent socket path. Defaults to /run/buildkit/ssh_agent.${N}
. |
required
|
If set to true
, the instruction errors out when the key is unavailable. Defaults to false
. |
mode
|
File mode for socket in octal. Default 0600. |
uid
|
User ID for socket. Default 0. |
gid
|
Group ID for socket. Default 0. |
Example: access to Gitlab
# syntax = docker/dockerfile:experimental FROM alpine RUN apk add --no-cache openssh-client RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan gitlab.com >> ~/.ssh/known_hosts RUN --mount=type=ssh ssh -q -T git@gitlab.com 2>&1 | tee /hello # "Welcome to GitLab, @GITLAB_USERNAME_ASSOCIATED_WITH_SSHKEY" should be printed here # with the type of build progress is defined as `plain`.
$ eval $(ssh-agent) $ ssh-add ~/.ssh/id_rsa (Input your passphrase here) $ buildctl build --frontend=dockerfile.v0 --local context=. --local dockerfile=. \ --ssh default=$SSH_AUTH_SOCK
你也可以直接使用宿主机目录的 pem 文件,但是带有密码的 pem 目前不支持
目前根据文档测试,当前的挂载类型比如 cache
类型,仅用于 multi-stage 内的挂载,比如你有 2+ 个构建步骤, cache
挂载类型能帮你在各个阶段内共享文件;但是它目前无法解决直接将宿主机目录挂载到 multi-stage 的问题(可以采取些曲线救国方案,但是很不优雅);但是未来还是很有展望的,可以关注一下
转载请注明出处,本文采用 CC4.0 协议授权
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 批量下载 BCompare 的语法高亮扩展包
- SG :一个简单的PHP语法糖扩展
- 在ES6中使用扩展语法有什么好处?它与rest语法有什么不同?
- iBoxDB.NET Linq 查询语法扩展库 0.5 发布
- 嵌入式C语言自我修养(01):Linux 内核中的 C 语言语法扩展
- Swift语法快速入门(一)之 Swift基础语法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。