【问题标题】:Golang docker library - mounting host directory volumesGolang docker library - 挂载主机目录卷
【发布时间】:2019-04-17 01:22:37
【问题描述】:

我如何执行相当于:

docker run -v /host/path:/container/path image:tag

从 Go 使用官方 docker 客户端包?

我在 client.ContainerCreate() function 的 HostOption 和 ConfigOption 结构中尝试了不同的 MountsVolumes 选项,但无法完全弄清楚。

特别是,Volumes 成员(map[string]struct{} 类型)特别难以弄清楚如何使用,而且我找不到任何关于结构中应该存在哪些值的文档。

演示我的问题的代码:

package main

import (
    "context"
    "github.com/docker/docker/api/types"
    "github.com/docker/docker/api/types/container"
    //"github.com/docker/docker/api/types/mount"
    "github.com/docker/docker/client"
    "github.com/docker/docker/pkg/stdcopy"
    "log"
    "os"
    "path/filepath"
)

func getThisDir() string {
    dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
    if err != nil {
        panic(err)
    }
    return dir
}

func main() {
    log.Println("Creating client")
    cli, err := client.NewClientWithOpts(client.FromEnv)
    if err != nil {
        panic(err)
    }

    image := "ubuntu:18.04"
    hostPath := getThisDir()
    containerPath := "/host_files"

    log.Printf("             Image: %s\n", image)
    log.Printf("         Host Path: %s\n", hostPath)
    log.Printf("    Container Path: %s\n", containerPath)

    ctx := context.Background()
    cli.NegotiateAPIVersion(ctx)

    log.Println("Creating container")
    var cont container.ContainerCreateCreatedBody
    if cont, err = cli.ContainerCreate(
        context.Background(),
        &container.Config{
            Image:      image,
            Entrypoint: []string{"/bin/bash", "-c", "ls -la " + containerPath},
            Volumes: map[string]struct{}{
                hostPath: {},
            },
        },
        &container.HostConfig{
            Runtime: "runsc",
            /*
                Mounts: []mount.Mount{
                    mount.Mount{
                        Type:   mount.TypeVolume,
                        Source: hostPath,
                        Target: containerPath,
                    },
                },
            */
        },
        nil,
        "TEST_CONTAINER",
    ); err != nil {
        panic(err)
    }

    defer func() {
        log.Println("Cleaning up")
        if err := cli.ContainerRemove(
            context.Background(),
            cont.ID,
            types.ContainerRemoveOptions{
                Force:         true,
                RemoveVolumes: true,
            },
        ); err != nil {
            panic(err)
        }
    }()

    log.Println("Starting container")
    if err = cli.ContainerStart(
        context.Background(),
        cont.ID,
        types.ContainerStartOptions{},
    ); err != nil {
        panic(err)
    }

    log.Println("Waiting for container to exit")
    waitOk, waitErr := cli.ContainerWait(
        ctx,
        cont.ID,
        container.WaitConditionNotRunning,
    )
    select {
    case <-waitOk:
        log.Println("Container exited normally!")
    case err = <-waitErr:
        log.Println("Error waiting")
        panic(err)
    }
    log.Println("Should be done!")

    logOutput, err := cli.ContainerLogs(
        ctx,
        cont.ID,
        types.ContainerLogsOptions{
            ShowStdout: true,
            ShowStderr: true,
            Follow:     false,
        },
    )
    if err != nil {
        panic(err)
    }

    log.Println("Container output:")
    stdcopy.StdCopy(os.Stdout, os.Stderr, logOutput)
}

编译并运行它会产生输出:

2019/04/16 20:42:21 Creating client
2019/04/16 20:42:21              Image: ubuntu:18.04
2019/04/16 20:42:21          Host Path: /home/user/go/src/test
2019/04/16 20:42:21     Container Path: /host_files
2019/04/16 20:42:21 Creating container
2019/04/16 20:42:22 Starting container
2019/04/16 20:42:22 Waiting for container to exit
2019/04/16 20:42:22 Container exited normally!
2019/04/16 20:42:22 Should be done!
2019/04/16 20:42:22 Container output:
ls: cannot access '/host_files': No such file or directory
2019/04/16 20:42:22 Cleaning up

如果取消注释与安装相关的行,则会得到以下输出:

2019/04/16 20:23:32 Creating client
2019/04/16 20:23:32              Image: ubuntu:18.04
2019/04/16 20:23:32          Host Path: /home/user/go/src/test
2019/04/16 20:23:32     Container Path: /host_files
2019/04/16 20:23:32 Creating container
panic: Error response from daemon: create /home/user/go/src/test: "/home/user/go/src/test" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path

goroutine 1 [running]:
main.main()
        /home/user/go/src/test/container.go:66 +0xb0c

错误消息没有意义,因为我 am 使用的是绝对路径。也许我应该重新阅读ContainerCreate 的文档。

更新 1

The docker engine API documentation 包含有关卷的更多详细信息 - 我开始认为我对 docker -v /host/path:/container/path 的工作方式有误 - 也许这实际上是绑定挂载而不是卷挂载。

更新 2

Rubber duck debugging FTW 我猜。删除Volumes 设置,重新添加Mounts 并将Type 更改为mount.TypeBind 使其工作:

2019/04/16 20:53:18 Creating client
2019/04/16 20:53:18              Image: ubuntu:18.04
2019/04/16 20:53:18          Host Path: /home/user/go/src/test
2019/04/16 20:53:18     Container Path: /host_files
2019/04/16 20:53:18 Creating container
2019/04/16 20:53:18 Starting container
2019/04/16 20:53:19 Waiting for container to exit
2019/04/16 20:53:19 Container exited normally!
2019/04/16 20:53:19 Should be done!
2019/04/16 20:53:19 Container output:
total XXXX
drwxr-xr-x  7 1000 1000     4096 Apr 17 03:51 .
drwxr-xr-x 34 root root     4096 Apr 17 03:53 ..
-rw-r--r--  1 1000 1000    10390 Apr 16 12:16 Gopkg.lock
-rw-r--r--  1 1000 1000     1021 Apr 16 12:16 Gopkg.toml
-rwxr-xr-x  1 1000 1000 12433827 Apr 17 03:53 container
-rw-r--r--  1 1000 1000     2421 Apr 17 03:51 container.go
2019/04/16 20:53:19 Cleaning up

【问题讨论】:

    标签: docker go


    【解决方案1】:

    删除Volumes 设置,重新添加Mounts 并将Type 更改为mount.TypeBind 使其工作:

    2019/04/16 20:53:18 Creating client
    2019/04/16 20:53:18              Image: ubuntu:18.04
    2019/04/16 20:53:18          Host Path: /home/user/go/src/test
    2019/04/16 20:53:18     Container Path: /host_files
    2019/04/16 20:53:18 Creating container
    2019/04/16 20:53:18 Starting container
    2019/04/16 20:53:19 Waiting for container to exit
    2019/04/16 20:53:19 Container exited normally!
    2019/04/16 20:53:19 Should be done!
    2019/04/16 20:53:19 Container output:
    total XXXX
    drwxr-xr-x  7 1000 1000     4096 Apr 17 03:51 .
    drwxr-xr-x 34 root root     4096 Apr 17 03:53 ..
    -rw-r--r--  1 1000 1000    10390 Apr 16 12:16 Gopkg.lock
    -rw-r--r--  1 1000 1000     1021 Apr 16 12:16 Gopkg.toml
    -rwxr-xr-x  1 1000 1000 12433827 Apr 17 03:53 container
    -rw-r--r--  1 1000 1000     2421 Apr 17 03:51 container.go
    2019/04/16 20:53:19 Cleaning up
    

    叹息。

    我唯一不能 100% 确定的是 docker -v /host/path:/container/path image:tag 实际上是绑定挂载还是不是。

    【讨论】:

    • 是的,它是绑定挂载(因为它引用了特定的主机端路径),而不是命名卷挂载。
    猜你喜欢
    • 2021-07-04
    • 1970-01-01
    • 2017-06-19
    • 2017-04-15
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多