无法使用Go Docker Engine API从容器中挂载文件夹到Docker中。

huangapple go评论78阅读模式
英文:

Unable to mount a folder in Docker from container with Go Docker Engine API

问题

我正在尝试使用Go Docker Engine API在容器内部运行Docker。我能够将主机系统中的文件夹挂载到容器中,但只有空文件夹被复制到容器内部的Docker中。如果有其他替代方法,请帮助我解决这个问题。我正在使用以下命令启动我的容器。

docker run --rm -v C:\Users\user\source\repos\game:/app/myrepo -v /var/run/docker.sock:/var/run/docker.sock testimage

附上的代码片段。
Go Docker SDK启动容器的代码

resp, err := cli.ContainerCreate(ctx, &container.Config{
	Image: "hello-image",
	Cmd:   []string{"ls"}, #实际的命令可能不同
	Tty:   true,
}, &container.HostConfig{
	Binds: []string{
		"/app/myrepo:/myrepo",
	},
}, nil, nil, containername)
if err != nil {
	panic(err)
}

更新后的绑定代码,使用绝对路径

resp, err := cli.ContainerCreate(ctx, &container.Config{
	Image: "hello-image",
	Cmd:   []string{"ls"}, #实际的命令可能不同
	Tty:   true,
}, &container.HostConfig{
	Mounts: []mount.Mount{
		{
			Type:   mount.TypeBind,
			Source: "/app/myrepo",
			Target: "/myrepo",
		},
	},
}, nil, nil, containername)
if err != nil {
	panic(err)
}
英文:

I am trying to run docker inside container using Go Docker Engine API. I am able to mount a folder from host system to the container but only empty dir is being copied into the docker inside the container. Please help me out if there is any alternative for the same. I am starting my container using following command.

docker run --rm -v C:\Users\user\source\repos\game:/app/myrepo -v /var/run/docker.sock:/var/run/docker.sock testimage

Attached is the piece of code.
Go Docker SDK code to start container

resp, err := cli.ContainerCreate(ctx, &container.Config{
	Image: "hello-image",
	Cmd:   []string{"ls"}, #the actual cmd would look different
	Tty:   true,
}, &container.HostConfig{
	Binds: []string{
		"/app/myrepo:/myrepo",
	},
}, nil, nil, containername)
if err != nil {
	panic(err)
}

updated Code for binds with absolute path

resp, err := cli.ContainerCreate(ctx, &container.Config{
	Image: "hello-image",
	Cmd:   []string{"ls"}, #the actual cmd would look different
	Tty:   true,
}, &container.HostConfig{
	Mounts: []mount.Mount{
		{
			Type:   mount.TypeBind,
			Source: "/app/myrepo",
			Target: "/myrepo",
		},
	},
}, nil, nil, containername)
if err != nil {
	panic(err)
}

答案1

得分: 0

根据评论中的讨论,OP正在容器中运行一个应用程序。该应用程序通过共享的/var/run/docker.sock连接到主机上的Docker守护程序,并尝试创建一个容器。问题在于请求包含一个挂载点,源路径为/app/myrepo,这是容器内有效的路径,但在主机上无效。

为了帮助理解为什么会出现问题,需要考虑API请求的生成方式。你的代码将生成一个JSON格式的请求;其中会包含类似以下内容:

...
"HostConfig": {
   ...
   "Mounts": [
       {
           "Source": "/app/myrepo",
           "Destination": "/myrepo",        
       }
   ]
}

需要注意的是,Source路径以字符串形式传递,并且Docker守护程序将在主机(例如Windows主机)的上下文中解释它。当它尝试定位请求的路径(/app/myrepo)时,它将找不到,因为该路径在主机上不存在。要纠正这个问题,你需要发送一个有效的路径,例如:

Mounts: []mount.Mount{
   {
      Type:   mount.TypeBind,
      Source: "c:/Users/user/source/repos/game",
      Target: "/myrepo",
    },
}

需要注意的一点是,以这种方式访问Docker API(绑定挂载/var/run/docker.sock)很方便,但如果有人获得容器的访问权限,他们也将完全控制所有容器(因为他们可以访问Docker API)。你可能需要考虑使用代理(例如:https://github.com/Tecnativa/docker-socket-proxy)。

英文:

As discussed in the comments the OP is running an app in a container. The app is connecting to the docker daemon on the host (via shared /var/run/docker.sock) and attempting to create a container. The issue was that the request includes a mount point, the source being /app/myrepo, which a source path that is valid within the container but not on the host.

To aid in understanding why this is an issue you need to consider how the API request is made. Your code will generate a JSON formatted request; this will include something like this:

...
"HostConfig": {
   ...
   "Mounts": [
       {
           "Source": "/app/myrepo",
           "Destination": "/myrepo",        
       }
   ]
}

It's important to note that the Source path is passed as a string and the Docker Daemon will interpret this in the hosts (e.g. the windows box) context. When it attempts to locate the requested path (/app/myrepo) it will not find it because that path does not exist on the host. To correct this you need to send a valid path e.g.

Mounts: []mount.Mount{
   {
      Type:   mount.TypeBind,
      Source: "c:/Users/user/source/repos/game",
      Target: "/myrepo",
    },
}

One note of caution; accessing the Docker API in this way (bind mount /var/run/docker.sock:) is convenient but if someone gains access to the container then they also gain full control of all containers (because they can access the Docker API). You may want to consider using a proxy (for example).

huangapple
  • 本文由 发表于 2022年8月22日 02:05:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/73437046.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定