What is the result of mounting `/var/run/docker.sock` in a Docker in Docker scenario?

我只是一个虾纸丫 提交于 2021-02-08 19:22:32

问题


I've read Can anyone explain docker.sock to understand what /var/run/docker.sock does, but its use in GitLab CI's Use Docker socket binding has me confused.

Here is their example command for the gitlab-runner registration:

sudo gitlab-runner register -n \
  --url https://gitlab.com/ \
  --registration-token REGISTRATION_TOKEN \
  --executor docker \
  --description "My Docker Runner" \
  --docker-image "docker:19.03.12" \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

I see two places that the resulting container could obtain docker from.

  1. The unix socket /var/run/docker.sock.
  2. The docker binary included in the base image docker:19.03.12.

Isn't this a PATH conflict? I thought it should be one or the other, where I obtain the ability to use docker from either the host's unix socket or the base image.

I would think that --docker-image should instead be ubuntu:latest or something along those lines that doesn't come with docker, since the PATH's docker would already come from the host socket. Alternatively, the docker socket mount would be removed.

What is actually happening here in regards to this double inclusion of docker?


回答1:


The Unix socket file /var/run/docker.sock is normally created by the Docker daemon. If you run something else as the main container process, the socket won't get created. You can directly look by running a container with a non-Docker main process, like /bin/ls:

docker run --rm docker:19.03.12 ls -l /var/run
docker run --rm docker:19.03.12 ls -l /run

The /usr/bin/docker binary must exist in the container filesystem, if you're going to use it. Containers can never call binaries that are on the host, and the socket API won't produce a binary either. (Some of the very early "use the host's Docker socket" posts advocated bind-mounting the binary into the container, but this leads to trouble with library dependencies and makes images not be self-contained.)

So if all you actually need is a Docker container, with a docker binary, that can invoke the host's Docker socket, you need an image like docker where the image has a /usr/bin/docker, plus you need to bind-mount the host's /var/run/docker.sock into the container.

docker run \
  --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  docker:19.03.12 \
  docker ps

The GitLab setup you link to seems rather contrived. Using the docker image to run jobs means that pretty much the only thing a build step can run is a docker command. At a technical level, you can't start the docker container without already having a docker binary and access to a running Docker daemon; the shell-executor approach described at the top of that page seems simpler and there aren't really any downsides to it.

You also also might find it convenient to have a Docker image of build-time dependencies (compilers, header files, static checking tools, ...). That would let you update these dependencies without having to roll out an update to your entire build cluster. If your build scripts themselves need to invoke docker then your build-tools image needs to install Docker, just using a normal RUN apt-get install command. You need to push the host's Docker socket into the container in the same way, and so you don't need to start a separate Docker daemon.




回答2:


First of all you need to understand how docker works in order to understand this flow the docker has a server and a client docker-cli and docker daemon the client communicate with the docker daemon using APIS.

the docker.sock is the UNIX socket that ensure connection between a the docker client and the daemon (server).

Since docker container unlike Virtual machine don't have a kernel each container run in docker uses the host's kernel and build the container in top of the host's kernel. a container doesn't have a kernel itself so you can't build a docker inside a docker unless you use the host's kernel.

the gitlab-runner has many exectors : shell ssh docker etc ...

using the docker executer means the runner will create a container and than clone you repo inside this container and run the scripts you pass and then destroys this container.

the gitlan-runner needs a base image in order to create the container that will run the scripts. you don't have to use docker:19.03.12 or mount /var/run/docker.sock volume unless your script has docker commands (or in general you need to have access to the docker ) and both of the strategies are differents you should know that mounting the docker.sock is not a docker in docker.

in order to achieve docker in docker you need to add --privileged flag to a container which basically makes root in your container be full root on the host. it can manage kernel params, it has all capabilities .

here's a good reference on this subject



来源:https://stackoverflow.com/questions/63201603/what-is-the-result-of-mounting-var-run-docker-sock-in-a-docker-in-docker-scen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!