Dind

🏠 首页 / Docker / Docker in Docker

Docker in Docker #

docker

Docker-in-Docker 的意思是在 Docker 容器中使用 docker,就像和在宿主机上使用 docker 一样,你可以理解为套娃

场景:

如果你的 Jenkins 是使用 Docker 容器的方式运行的,如果你想使用 Jenkins 的 Docker 插件来为 Jenkins Job 提供运行容器,这时候你就需要用到 Docker-in-Docker;

一般这个技术使用在应用的程序集成中 CI/CD

1. 挂载主机 /var/run/docker.sock #

docker-in-docker-01

Docker 容器

docker run -v /var/run/docker.sock:/var/run/docker.sock --name docker-in-docker -it docker

在运行起来的容器中使用docker:

$ docker run -v /var/run/docker.sock:/var/run/docker.sock --name docker-in-docker -it docker
/ # docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

可以看到,在该容器中可以像在宿主机一样运行 docker 容器。

但是,使用 docker ps -a 命令可以查看到宿主机的运行容器,这说明容器的权限是很大的,存在一定的安全隐患:

image-20201208143849939

Kubernetes Pod

准备 docker-in-docker.yaml 文件如下:

apiVersion: v1
kind: Pod
metadata:
  name: docker-in-docker
spec:
  containers:
    - name: docker
      image: docker
      command: ["/bin/sh", "-c"]
      args:
        - sleep 300s;
      volumeMounts:
        - name: docker-sock
          mountPath: /var/run/docker.sock
  volumes:
    - name: docker-sock
      hostPath:
        path: /var/run/docker.sock
kubectl apply -f docker-in-docker.yaml
kubectl exec -it docker-in-docker -c docker /bin/sh

同样,这种方式也能获取到宿主机的容器。

image-20210115093238930

2. 使用 Docker-Dind #

docker-in-docker-02

Docker 容器

docker run --privileged -d --name docker-in-docker docker:dind
docker exec -it docker-in-docker /bin/sh

与上面方式不同的是,这种方式运行起来的 docker-in-docker 无法看到宿主机上的容器。

image-20210115090727784

Kubernetes Pod

准备 docker-in-docker.yaml 文件如下:

apiVersion: v1
kind: Pod
metadata:
  name: docker-in-docker
spec:
  containers:
    - name: docker
      image: docker:18
      imagePullPolicy: Always
      env:
        - name: DOCKER_HOST
          value: tcp://localhost:2375
      command: ["/bin/sh", "-c"]
      args:
        - sleep 300s;
    - name: docker-dind
      image: docker:18-dind
      securityContext:
        privileged: true
  restartPolicy: OnFailure

注意:

需要两个容器,第一容器由 docker 镜像运行,第二容器由 docker:dind 镜像运行;

第一容器需要设置环境变量:DOCKER_HOST=tcp://localhost:2375

第二容器使用特权模式运行。

kubectl apply -f docker-in-docker.yaml
kubectl exec -it docker-in-docker -c docker /bin/sh

3. 结束语 #

前面提到了,由于第一种方式挂载主机 /var/run/docker.sock,在容器视角依然能获取到宿主机的容器,也能运行或删除容器,存在一定的安全隐患,更推荐使用第二种方式,Over!


« container-diff 工具的使用

» docker buildx