草庐IT

docker - Golang docker library - 挂载主机目录卷

coder 2024-07-08 原文

我如何执行相当于:

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

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

我试过不同的 MountsVolumes client.ContainerCreate() function 的 HostOption 和 ConfigOption 结构中的选项, 但不太明白。

特别是 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

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

更新1

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

更新2

Rubber duck debugging我想是的。删除 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

最佳答案

删除 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 实际上是 绑定(bind)挂载, 或者不是。

关于docker - Golang docker library - 挂载主机目录卷,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55718603/

有关docker - Golang docker library - 挂载主机目录卷的更多相关文章

  1. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  2. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  3. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  4. ruby-on-rails - 如何在 Gem 中获取 Rails 应用程序的根目录 - 2

    是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在

  5. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  6. ruby-on-rails - 没有这样的文件或目录 - 用 Mini Magick 识别 - 2

    在我让另一个人重做我的前端UI之前,我的Rails应用程序运行平稳。我已经尝试解决此错误3天了。这是错误:Nosuchfileordirectory-identifyExtractedsource(aroundline#59):575859606162@post=Post.find(params[:id])authorize@postif@post.update_attributes(post_params)flash[:notice]="Postwasupdated."redirect_to[@topic,@post]else{"utf8"=>"✓","_method"=>"patc

  7. ruby - 允许主机名包含下划线的 URI.parse 的替代方法 - 2

    我正在使用DMOZ的listofurltopics,其中包含一些具有包含下划线的主机名的url。例如:608609TheOuterHeaven610InformationandimagegalleryofMcFarlane'sactionfiguresforTrigun,Akira,TenchiMuyoandotherJapaneseSci-Fianimations.611Top/Arts/Animation/Anime/Collectibles/Models_and_Figures/Action_Figures612虽然此url可以在网络浏览器中使用(或者至少在我的浏览器中可以使用:

  8. ruby - Sinatra 找不到 View 目录 - 2

    我正在尝试以一种更类似于普通RubyGem结构的方式构建我的Sinatra应用程序。我有以下文件树:.├──app.rb├──config.ru├──Gemfile├──Gemfile.lock├──helpers│  ├──dbconfig.rb│  ├──functions.rb│  └──init.rb├──hidden│  └──Rakefile├──lib│  ├──admin.rb│  ├──api.rb│  ├──indexer.rb│  ├──init.rb│  └──magnet.rb├──models│  ├──init.rb│  ├──invite.rb│  ├─

  9. ruby - 如何在 ruby​​ 中复制目录结构,不包括某些文件扩展名 - 2

    我想编写一个ruby​​脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"

  10. Ruby 服务器在本地主机(teambox)之外非常慢 - 2

    我刚刚在我的Ubuntu9.10服务器上安装了TeamBox。我使用提供的服务器脚本在端口3000上启动并运行它。它的运行速度非常慢,从另一台计算机连接时每个HTTP请求最多需要30秒。我使用链接从shell加载TeamBox,一点也不花时间。然后我设置了一个SSH隧道,它再次运行得非常快。我通过此服务器上的apache以及SAMBA等运行了大约30个虚拟主机,没有任何问题。我该如何解决这个问题? 最佳答案 我的redmine(ruby,webrick)太慢了。现在我解决了这个问题:apt-getinstallmongrelruby

随机推荐