无法使用Docker SDK中的端口范围语法进行端口转发

时间:2020-08-03 20:40:53

标签: docker go port docker-run

我正在尝试使用Go SDK运行Docker容器。从终端,我可以毫无问题地运行以下命令:

docker run -d --memory 1024M --name "cdb1" -p 2001-2006:8091-8096 -p 11210-11211:11210-11211 couchbase

我想使用Docker SDK for Go实现相同的目的,但是找不到如何重现-p 2001-2006:8091-8096部分。这是我的ContainerCreate调用:

cont, err := cli.ContainerCreate(
    context.Background(),
    &container.Config{
        Image: "couchbase",
        ExposedPorts: nat.PortSet{
            "2001-2006": struct{}{},
            "11210-11211": struct{}{},
        },
    },
    &container.HostConfig{
        PortBindings: nat.PortMap{
            "8091-8096": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "2001-2006",
                },
            },
            "11210-11211": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "11210-11211",
                },
            },
        },
        Resources: container.Resources{
            Memory: 1024 * 1000000,
        },
    },
    nil,
    "cdb1",
)

但是运行此命令总是会引发相同的错误:

Error response from daemon: invalid port specification: "8091-8096"

进行更多测试,该错误似乎特别来自PortBindings部分(如果我删除这一部分并保留暴露的端口,则可以正常工作。)

我在Docker文档中找不到关于此的任何内容。

2 个答案:

答案 0 :(得分:2)

nat.PortSet是一个以nat.Port为其键类型的地图:

type PortSet map[Port]struct{}

您的"2001-2006"的“端口”规范在语法上起作用,因为它是未类型化的字符串常量,可以转换为以nat.Port作为其基础类型的string,但是此字符串文字缺少协议规范(例如tcpudp)。

代替使用nat.NewPort()函数来创建密钥:

ports1, err := nat.NewPort("tcp", "2001-2006")   // check err
ports2, err := nat.NewPort("tcp", "11210-11211") // check err

ExposedPorts: nat.PortSet{
    ports1: struct{}{},
    ports2: struct{}{},
},

请注意,预期的“原始”字符串格式为"2001-2006/tcp",也可以接受,但是最好将此内部详细信息保留为nat.NewPort()

要构建nat.PortMap,请使用nat.ParsePortSpec()实用程序功能。这是组装PortBindings的方式:

portBindings := nat.PortMap{}

for _, rawMapping := range []string{
    "0.0.0.0:2001-2006:8091-8096",
    "0.0.0.0:11210-11211:11210-11211",
} {
    mappings, err := nat.ParsePortSpec(rawMapping)
    if err != nil {
        panic(err)
    }
    for _, pm := range mappings {
        portBindings[pm.Port] = []nat.PortBinding{pm.Binding}
    }

}

然后,您可以在portBindings字段中使用上面的HostConfig.PortBindings

&container.HostConfig{
    PortBindings: portBindings ,
    Resources: container.Resources{
        Memory: 1024 * 1000000,
    },
},

答案 1 :(得分:1)

尝试单独添加每个端口而不是端口范围:

cont, err := cli.ContainerCreate(
    context.Background(),
    &container.Config{
        Image: "couchbase",
        ExposedPorts: nat.PortSet{
            "2001": struct{}{},
            "2002": struct{}{},
            "2003": struct{}{},
            "2004": struct{}{},
            "2005": struct{}{},
            "2006": struct{}{},
            "11210": struct{}{},
            "11211": struct{}{}
        },
    },
    &container.HostConfig{
        PortBindings: nat.PortMap{
            "8091": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "2001",
                },
            },
            "8092": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "2002",
                },
            },
            "8093": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "2003",
                },
            },
            "8094": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "2004",
                },
            },
            "8095": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "2005",
                },
            },
            "8096": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "2006",
                },
            },
            "11210": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "11210",
                },
            },
            "11211": []nat.PortBinding{
                {
                    HostIP: "0.0.0.0",
                    HostPort: "11211",
                },
            }
        },
        Resources: container.Resources{
            Memory: 1024 * 1000000,
        },
    },
    nil,
    "cdb1",
)