1 回答

TA貢獻1847條經驗 獲得超7個贊
有各種各樣的東西可以實現io.Reader。在這種情況下,正常的方法是打開一個文件os.Open,然后得到的*os.File指針是一個io.Reader.
但是,正如您在評論中指出的那樣,這只會幫助您從“本地”文件系統讀取和寫入內容。訪問主機的 Docker 套接字非常強大,但它不會直接為您提供對主機文件系統的讀寫訪問權限。(正如@mkopriva 在評論中建議的那樣,使用docker run -v /host/path:/container/path綁定安裝啟動容器要簡單得多,并且避免了我將要討論的大量安全問題。)
您需要做的是啟動第二個容器來綁定您需要的內容,然后從容器中讀取文件。聽起來您正在嘗試將其寫入本地文件系統,這樣可以簡化操作。在容器內的docker execshell 提示符下,您可能會執行類似的操作
docker run --rm -v /:/host busybox cat /host/some/path/hostFile.zip \
> /tmp/hostFile.zip
在 Go 中,它涉及更多但仍然非??尚校ㄎ唇洔y試,省略了導入)
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加密密碼文件,因為我可以,并且沒有什么能阻止我使用基本相同的方法用我選擇的 root 密碼寫回它。所有者、權限和其他一切都無關緊要:Docker 守護進程以 root 身份運行,大多數容器默認以 root 身份運行(如果不是,您可以明確請求)。
- 1 回答
- 0 關注
- 90 瀏覽
添加回答
舉報