Dockerfile 目前可扩展的语法

栏目: 编程工具 · 发布时间: 5年前

内容简介:最近在调整公司项目的 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…然后突然感觉

Dockerfile 目前可扩展的语法

仔细想想,情况应该是这样事儿的…

+------------+                +-------------+            +----------------+
|            |                |             |            |                |
|            |                |    build    |            |   Multi-stage  |
|   Runner   +--------------->+  conatiner  +----------->+     Build      |
|            |                |             |            |                |
|            |                |             |            |                |
+------------+                +------+------+            +----------------+
                                     ^
                                     |
                                     |
                                     |
                                     |
                              +------+------+
                              |             |
                              |    Cache    |
                              |             |
                              +-------------+

Dockerfile 目前可扩展的语法

后来经过查阅文档,发现 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,用来挂载一些不想打入镜像,但是构建时想使用的密钥等,例如 dockerconfig.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 协议授权


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

小团队构建大网站:中小研发团队架构实践

小团队构建大网站:中小研发团队架构实践

张辉清 等 / 电子工业出版社 / 2019-1 / 69

《小团队构建大网站:中小研发团队架构实践》结合作者近几年的工作经验,总结了一套可直接落地、基于开源、成本低、可快速搭建的中小研发团队架构实践方法。《小团队构建大网站:中小研发团队架构实践》共5篇22章,开篇是本书的导读;架构篇是设计思想的提升,包括企业总体架构、应用架构设计、统一应用分层等;框架篇主讲中间件和工具的使用,包括消息队列、缓存、Job、集中式日志、应用监控和微服务等;公共应用篇是技术与......一起来看看 《小团队构建大网站:中小研发团队架构实践》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试