容器内构建镜像的几种方式
背景
在云原生趋势下,用容器的方式来进行软件产品交付越来越普通,对于云原生的DevOps,它的CICD环境完全运行在容器中,镜像的构建也是在容器中完成的。而我们不仅要考虑如何在容器中成功构建镜像,也需要考虑如何以更安全的方式来构建容器镜像。
容器内构建镜像的方式
容器中构建镜像一般分为两种:
- 在Docker容器中运行Docker,依赖Docker Daemon
- Kaniko -K8s中构建镜像,不依赖Docker Daemon
在Docker容器中运行Docker
这两种方式,一种需要root权限,一种需要privileged特权,从安全角度来看是有风险的。特别是在K8S多租户的场景下,这种方式不能被接受。同时当一台机器上同时运行多个docker build流水线时,因为这批流水线用的是宿主机上同一个docker进程,会出现阻塞的情况。
- 通过挂载docker.sock运行docker:需要root权限
通过挂载docker.sock运行docker,使用默认Unix套接字docker.sock作为卷的情况下运行docker 。
缺点:只有root权限才能访问docker daemon进程,在docker daemon无法暴露或者用户没有权限获取docker daemon进程的前提下,用 docker build 来构建镜像就不可行了。 - dind(docker in docker):需要privileged特权
docker build镜像就是需要docker命令可以成功运行,只要在容器里面安装一个docker就可以。这种方式不需要挂载宿主机的socket文件,但是需要以 –privileged 权限来以dind镜像创建一个容器
缺点:该方式需要提供特权,可能会看到宿主机上的一些设备,并且可以执行mount命令。
Kaniko构建
前提
- Kubernetes(K8S)运行环境
- dockerhub账号或者私有镜像仓库,用于push镜像
准备Dockerfile
登录到K8S集群主节点,创建一个本地目录,该目录将被挂载到kaniko容器作为构建环境,在改目录创建一个简单的Dockerfile文件。
1
2
3
4
5
6
7
8
9
10[root@VM-20-7-centos ~]# mkdir kaniko && cd kaniko
[root@VM-20-7-centos kaniko]# pwd
/root/kaniko
[root@VM-20-7-centos kaniko]# cat > Dockerfile << EOF
FROM ubuntu
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]
EOF
[root@VM-20-7-centos kaniko]# cat Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]创建docker secret秘钥
Kubernetes集群使用docker-registry类型的Secret来验证docker registry,用于推送镜像。
1 | kubectl create secret docker-registry <secret-name> --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email> |
docker秘钥名称 是你的私有 Docker Registry FQDN。 是你的 Docker 用户名。 是你的 Docker 密码。 是你的 Docker 电子邮件。
- 创建资源清单
创建manifests目录,在该目录下创建所需的资源清单
1 | mkdir manifests && cd manifests |
volume.yaml
1 | touch volume.yaml && vi volume.yaml |
1 | apiVersion: v1 |
volume-claim.yml
1 | touch volume-claim.yml && vi volume-claim.yml |
1 | apiVersion: v1 |
pod.yml
1 | touch pod.yml && vi pod.yml |
1 | apiVersion: v1 |
- 在Kubernetes中创建资源
1 | [root@VM-20-7-centos kaniko]# kubectl apply -f manifests/ |
- 查看Pod运行日志当看到日志中出现
1
2
3
4
5
6
7
8
9
10
11
12
13[root@VM-20-7-centos kaniko]# kubectl logs -f kaniko
# Pod日志内容
INFO[0005] Retrieving image manifest ubuntu
INFO[0005] Retrieving image ubuntu from registry index.docker.io
INFO[0025] Built cross stage deps: map[]
INFO[0025] Retrieving image manifest ubuntu
INFO[0025] Returning cached image manifest
INFO[0025] Executing 0 build triggers
INFO[0025] Building stage 'ubuntu' [idx: '0', base-idx: '-1']
INFO[0025] Skipping unpacking as no commands require it.
INFO[0025] ENTRYPOINT ["/bin/bash", "-c", "echo hello"]
INFO[0025] Pushing image to bunny123/test-kanik0
INFO[0039] Pushed index.docker.io/bunny123/test-kanik0@sha256:996220f9fb96b96fdeefb796d0fe02a8995a07b61c2e0ed9d74134e0c0e6ece8Pushed,表示镜像已经构建成并推送至指定仓库。
