我希望使用在容器中运行的go代码将压缩文件从主机复制到容器。安装程序在安装了docker.sock的容器中运行go代码。其想法是将zip文件从主机复制到运行go代码的容器。路径参数位于主机上。在主机命令行上,如下所示
docker cp hostFile.zip myContainer:/tmp/码头-客户端CopyToContainer的文档看起来
func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader, options types.CopyToContainerOptions) error如何创建content io.Reader参数?
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
panic(err)
}
// TODO
// reader := io.Reader()
// reader := file.NewReader()
// tar.NewReader()
cli.CopyToContainer(context.Background(), containerID, dst, reader, types.CopyToContainerOptions{
AllowOverwriteDirWithFile: true,
CopyUIDGID: true,
})发布于 2022-04-05 11:46:49
实现io.Reader的东西种类繁多。在这种情况下,通常的方法是使用os.Open打开一个文件,然后生成的*os.File指针是一个io.Reader。
但是,正如您在注释中所指出的,这只会帮助您从“本地”文件系统中读取和写入内容。访问主机的Docker套接字是非常强大的,但它不能直接让您对主机文件系统进行读写访问。( @mkopriva在一条评论中指出,使用docker run -v /host/path:/container/path绑定挂载启动容器要简单得多,并且避免了我将要讨论的大量安全问题。)
您需要做的是启动第二个容器,绑定-挂载您需要的内容,并从容器中读取文件。听起来像是在尝试将它写到本地文件系统中,这简化了一些事情。在容器内的docker exec shell提示符中,您可能会执行以下操作
docker run --rm -v /:/host busybox cat /host/some/path/hostFile.zip \
> /tmp/hostFile.zip 在Go中,它涉及更多,但仍然非常可行(未经测试,没有进口)
ctx := context.Background()
cid, err := client.ContainerCreate(
ctx,
&container.Config{
Image: "docker.io/library/busybox:latest",
Cmd: strslice.StrSlice{"cat", "/host/etc/shadow"},
},
&container.HostConfig{
Mounts: []mount.Mount{
{
Type: mount.TypeBind,
Source: "/",
Target: "/host",
},
},
},
nil,
nil,
""
)
if err != nil {
return err
}
defer client.ContainerRemove(ctx, cid.ID, &types.ContainerRemoveOptions{})
rawLogs, err := client.ContainerLogs(
ctx,
cid.ID,
types.ContainerLogsOptions{ShowStdout: true},
)
if err != nil {
return err
}
defer rawLogs.close()
go func() {
of, err := os.Create("/tmp/host-shadow")
if err != nil {
panic(err)
}
defer of.Close()
_ = stdcopy.StdCopy(of, io.Discard, rawLogs)
}()
done, cerr := client.ContainerWait(ctx, cid.ID, container. WaitConditionNotRunning)
for {
select {
case err := <-cerr:
return err
case waited := <-done:
if waited.Error != nil {
return errors.New(waited.Error.Message)
} else if waited.StatusCode != 0 {
return fmt.Errorf("cat container exited with status code %v", waited.StatusCode)
} else {
return nil
}
}
}正如我在前面所暗示并在代码中显示的那样,这种方法绕过了主机上的所有控件;我决定返回主机的/etc/shadow加密密码文件,因为我可以,没有什么可以阻止我使用基本相同的方法选择根密码来编写它。所有者、权限和其他任何事情都无关紧要: Docker守护进程作为root运行,大多数容器默认以root形式运行(如果没有,您可以显式地请求它)。
https://stackoverflow.com/questions/71746994
复制相似问题