Docker - 套接字文件的卷映射是否为覆盖行为?
Docker - Is volume mapping of socket file an override behavior?
下面是从 here:
中截取的 jenkins 图像的代码片段
# Install Docker Engine
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D && \
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" | tee /etc/apt/sources.list.d/docker.list && \
apt-get update -y && \
apt-get purge lxc-docker* -y && \
apt-get install docker-engine=${DOCKER_ENGINE:-1.10.2}-0~trusty -y && \
usermod -aG docker jenkins && \
usermod -aG users jenkins
在 jenkins 映像中安装 docker 引擎。我的理解是,由于安装了 docker 引擎,var/run/docker.sock
是使用 Jenkins 容器创建的。
下面是 卷映射语法 摘自 here:
volumes:
- jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
在 EC2 主机上启动 jenkins 容器(上图)。
EC2 主机也有 docker 守护进程 运行。
因此,EC2 主机中有 docker 守护程序 运行。 docker container(Jenkins)
中还有一个 docker 守护进程 运行
在 docker-compose(以上)套接字文件中使用此语法(/var/run/docker.sock:/var/run/docker.sock
),
Jenkins 容器中的 docker 守护进程是否使用 EC2 主机中存在的套接字文件覆盖其自身的套接字文件?如果是...它的含义是什么?
容器中的 /var/run/docker.sock
是主机的 Docker 套接字,除此之外别无他物。这是因为:
- Docker 容器不会 运行 除了在其入口点 and/or 命令中明确启动的程序之外的任何程序,而且几乎总是只有一个应用程序。
- 您可能不会特意启动 Docker 守护进程,因此它已安装但未 运行ning。
- Unix 套接字文件只有在守护程序启动后才会创建,并且它绑定(2) 套接字到特定文件。
docker run -v
选项总是 "push" 主机的内容到容器中,这发生在任何容器进程之前 运行。
所以在您描述的场景中,它不能是主机 Docker 套接字以外的任何东西,因为没有第二个 Docker 守护进程。
为了争论起见,假设您实际上正在以这种方式启动第二个守护进程。
这里的操作顺序是 (1) Docker 设置容器文件系统,(2) Docker 启动 运行ning 入口点,(3) 入口点启动守护进程,(4) 守护进程尝试创建套接字文件。在守护进程启动时,它的套接字文件已经存在。我相信这会导致 bind(2) 调用失败并显示 EADDRINUSE
,并且守护进程不会启动。希望这会导致您的容器启动失败。
你可能想在容器中启动一个守护进程,它发布一个你想从主机访问的 Unix 套接字。要完成这项工作,您需要将一个目录挂载到容器中,并将守护进程指向它。它可能不能在任何一侧 /var/run
(主机 /var/run
中有很多东西;安装目录会隐藏容器中的现有内容,您可能需要容器的 /var/run
也)。它必须是目录而不是套接字文件名,因为 Docker 如果它不存在将创建一个空目录; 某些东西 将存在于该路径的容器中,绑定将失败。
因此,如果您想在容器内启动一个假设的 foo 守护进程,它大致如下所示
docker run \
--name foo \ # container name
-v $PWD/socket:/socket \ # bind mount a directory
foo \ # image name
food \ # command to run in the container
--foreground \ # don't daemonize; keep the container alive
--bind fd://socket/foo.sock # put the socket in the shared directory
在主机上,您需要设置 FOO_SOCKET_PATH=$PWD/socket/foo.sock
或指向此特定文件。
来自docs:
Docker-engine is a client-server application
请注意,当您安装 docker-engine
时,您会安装 docker-daemon(服务器)和 docker cli(客户端)。
这意味着如果 docker 守护进程不是 运行ning 你仍然可以 运行 docker cli 命令:
docker info
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
您共享的 Jenkins 映像没有 运行 docker 引擎的说明。所以我假设它不在容器内 运行ning。
/var/run/docker.sock:/var/run/docker.sock
卷映射 docker 主机的 docker 引擎套接字到容器。
所以容器中的 docker cli 命令 运行 控制 docker 引擎 运行 在 docker 主机上运行。
如果您从容器化的 Jenkins 中在您的主机上执行 CI/CD,这是有道理的。
Jenkins 管道可以使用 docker、docker-compose 和 docker swarm 命令来 运行 测试、构建工件和部署新版本的应用程序。
下面是从 here:
中截取的 jenkins 图像的代码片段# Install Docker Engine
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D && \
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" | tee /etc/apt/sources.list.d/docker.list && \
apt-get update -y && \
apt-get purge lxc-docker* -y && \
apt-get install docker-engine=${DOCKER_ENGINE:-1.10.2}-0~trusty -y && \
usermod -aG docker jenkins && \
usermod -aG users jenkins
在 jenkins 映像中安装 docker 引擎。我的理解是,由于安装了 docker 引擎,var/run/docker.sock
是使用 Jenkins 容器创建的。
下面是 卷映射语法 摘自 here:
volumes:
- jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
在 EC2 主机上启动 jenkins 容器(上图)。
EC2 主机也有 docker 守护进程 运行。
因此,EC2 主机中有 docker 守护程序 运行。 docker container(Jenkins)
中还有一个 docker 守护进程 运行在 docker-compose(以上)套接字文件中使用此语法(/var/run/docker.sock:/var/run/docker.sock
),
Jenkins 容器中的 docker 守护进程是否使用 EC2 主机中存在的套接字文件覆盖其自身的套接字文件?如果是...它的含义是什么?
/var/run/docker.sock
是主机的 Docker 套接字,除此之外别无他物。这是因为:
- Docker 容器不会 运行 除了在其入口点 and/or 命令中明确启动的程序之外的任何程序,而且几乎总是只有一个应用程序。
- 您可能不会特意启动 Docker 守护进程,因此它已安装但未 运行ning。
- Unix 套接字文件只有在守护程序启动后才会创建,并且它绑定(2) 套接字到特定文件。
docker run -v
选项总是 "push" 主机的内容到容器中,这发生在任何容器进程之前 运行。
所以在您描述的场景中,它不能是主机 Docker 套接字以外的任何东西,因为没有第二个 Docker 守护进程。
为了争论起见,假设您实际上正在以这种方式启动第二个守护进程。
这里的操作顺序是 (1) Docker 设置容器文件系统,(2) Docker 启动 运行ning 入口点,(3) 入口点启动守护进程,(4) 守护进程尝试创建套接字文件。在守护进程启动时,它的套接字文件已经存在。我相信这会导致 bind(2) 调用失败并显示 EADDRINUSE
,并且守护进程不会启动。希望这会导致您的容器启动失败。
你可能想在容器中启动一个守护进程,它发布一个你想从主机访问的 Unix 套接字。要完成这项工作,您需要将一个目录挂载到容器中,并将守护进程指向它。它可能不能在任何一侧 /var/run
(主机 /var/run
中有很多东西;安装目录会隐藏容器中的现有内容,您可能需要容器的 /var/run
也)。它必须是目录而不是套接字文件名,因为 Docker 如果它不存在将创建一个空目录; 某些东西 将存在于该路径的容器中,绑定将失败。
因此,如果您想在容器内启动一个假设的 foo 守护进程,它大致如下所示
docker run \
--name foo \ # container name
-v $PWD/socket:/socket \ # bind mount a directory
foo \ # image name
food \ # command to run in the container
--foreground \ # don't daemonize; keep the container alive
--bind fd://socket/foo.sock # put the socket in the shared directory
在主机上,您需要设置 FOO_SOCKET_PATH=$PWD/socket/foo.sock
或指向此特定文件。
来自docs:
Docker-engine is a client-server application
请注意,当您安装 docker-engine
时,您会安装 docker-daemon(服务器)和 docker cli(客户端)。
这意味着如果 docker 守护进程不是 运行ning 你仍然可以 运行 docker cli 命令:
docker info
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
您共享的 Jenkins 映像没有 运行 docker 引擎的说明。所以我假设它不在容器内 运行ning。
/var/run/docker.sock:/var/run/docker.sock
卷映射 docker 主机的 docker 引擎套接字到容器。
所以容器中的 docker cli 命令 运行 控制 docker 引擎 运行 在 docker 主机上运行。
如果您从容器化的 Jenkins 中在您的主机上执行 CI/CD,这是有道理的。
Jenkins 管道可以使用 docker、docker-compose 和 docker swarm 命令来 运行 测试、构建工件和部署新版本的应用程序。