我想使用容器內運行的 go 代碼將壓縮檔案從主機復制到容器。該設定已在安裝了 docker.sock 的容器中運行代碼。這個想法是將 zip 檔案從主機復制到運行 go 代碼的容器。路徑引數在主機上。在主機上的命令列看起來像這樣
docker cp hostFile.zip myContainer:/tmp/
docker-client 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,
})
uj5u.com熱心網友回復:
有各種各樣的東西可以實作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
}
}
}
As I hinted earlier and showed in the code, this approach bypasses all controls on the host; I've decided to read back the host's /etc/shadow encrypted password file because I can, and nothing would stop me from writing it back with my choice of root password using basically the same approach. Owners, permissions, and anything else don't matter: the Docker daemon runs as root and most containers run as root by default (and you can explicitly request it if not).
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/457423.html
上一篇:Cgo:對[C函式]的未定義參考
