英文:
How to specify a docker container's network in go SDK
问题
我正在尝试在使用Golang编写的应用程序中启动一个Docker容器。
在这个问题中,感谢答案,我知道如何使用以下代码创建自定义网络:
resp, err := dn.cl.NetworkCreate(context.Background(), "mynet", types.NetworkCreate{
Driver: "bridge",
IPAM: &network.IPAM{
Config: []network.IPAMConfig{{
Subnet: "128.0.1.9/16",
}},
},
})
它们应该等同于docker network create -d bridge --subnet=128.0.1.9/16 mynet
。
我想使用Golang SDK执行以下命令的等效操作:
docker run -d \
--name=mydocker \
--ip=128.0.1.9 \
--hostname=roach1 \
--net=mynet \
-p 1234:1234 -p 8080:8080 \
myimage/myimage-ci:latest
我正在编写以下代码:
containerConfig := container.Config{
Hostname: containerName,
Image: imageName,
Env: envSetting,
ExposedPorts: nat.PortSet{"8080": struct{}{}, "1234": struct{}{}},
Cmd: cmd,
}
hostConfig := container.HostConfig{
Binds: volSetting,
PortBindings: map[nat.Port][]nat.PortBinding{
nat.Port("8080"): {{HostIP: "128.0.1.9", HostPort: "8080"}},
nat.Port("1234"): {{HostIP: "128.0.1.9", HostPort: "1234"}},
},
}
resp, err := dn.cl.ContainerCreate(
ctx,
&containerConfig,
&hostConfig,
nil,
nil,
containerName,
)
但是它不起作用。我收到了以下错误:
cannot start container: Error response from daemon: Ports are not available: exposing port TCP 128.0.1.9:1234 -> 0.0.0.0:0: listen tcp 128.0.1.9:1234: bind: can't assign requested address
我还检查了我创建的网络:
[
{
"Name": "mynet",
"Id": "d009c6f68492abfa0257c2980dcfaaa425338740327ef811b209xxxxxxxxx",
"Created": "2022-08-1T16:42:14.880121815Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "128.0.1.9/16"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
我怀疑这是因为我没有指定容器应该加入mynet
网络。但是如何使用SDK实现这一点呢?
英文:
I'm trying to start a docker container in my app written in Golang.
In this question, thanks for the answers, I know how to create my customized network with
resp, err := dn.cl.NetworkCreate(context.Background(), "mynet", types.NetworkCreate{
Driver: "bridge",
IPAM: &network.IPAM{
Config: []network.IPAMConfig{{
Subnet: "128.0.1.9/16",
}},
},
})
They should be the equivalent of docker network create -d bridge --subnet=128.0.1.9/16 mynet
And I'd like to use the golang SDK to do the equivalent of
docker run -d \
--name=mydocker \
--ip=128.0.1.9 \
--hostname=roach1 \
--net=mynet \
-p 1234:1234 -p 8080:8080 \
myimage/myimage-ci:latest
And I'm writing this
containerConfig := container.Config{
Hostname: containerName,
Image: imageName,
Env: envSetting,
ExposedPorts: nat.PortSet{"8080": struct{}{}, "1234": struct{}{}},
Cmd: cmd,
}
hostConfig := container.HostConfig{
Binds: volSetting,
PortBindings: map[nat.Port][]nat.PortBinding{
nat.Port("8080"): {{HostIP: "128.0.1.9", HostPort: "8080"}},
nat.Port("1234"): {{HostIP: "128.0.1.9", HostPort: "1234"}},
},
}
resp, err := dn.cl.ContainerCreate(
ctx,
&containerConfig,
&hostConfig,
nil,
nil,
containerName,
)
But it's not working. I got the following error:
cannot start container: Error response from daemon: Ports are not available: exposing port TCP 128.0.1.9:1234 -> 0.0.0.0:0: listen tcp 128.0.1.9:1234: bind: can't assign requested address
I also inspected the network I created
[
{
"Name": "mynet",
"Id": "d009c6f68492abfa0257c2980dcfaaa425338740327ef811b209xxxxxxxxx",
"Created": "2022-08-1T16:42:14.880121815Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "128.0.1.9/16"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
I suspect it's because I didn't specify that the container should join the mynet
network. But how to do that with the SDK?
答案1
得分: 1
您可以通过在EndpointSettings
的NetworkID
字段中使用名称来指定先前创建的网络。
例如,要创建一个kafka容器并添加orchestration
网络:
resp, err := m.DockerManager.Client.ContainerCreate(ctx,
&container.Config{
Image: kafka,
Env: []string{"KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181", "ALLOW_PLAINTEXT_LISTENER=yes"},
},
&container.HostConfig{
PortBindings: nat.PortMap{nat.Port("9092"): []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: "9092"}}},
Mounts: []mount.Mount{{Type: mount.TypeVolume, Source: "kafka_data", Target: "/bitnami"}},
},
&network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{"orchestration": {NetworkID: "orchestration"}}},
nil,
"kafka",
)
英文:
You can specify an previously created network by just using the name in the NetworkID
field of the EndpointSettings
.
For instance, to create a kafka container and add the orchestration
network:
resp, err := m.DockerManager.Client.ContainerCreate(ctx,
&container.Config{
Image: kafka,
Env: []string{"KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181", "ALLOW_PLAINTEXT_LISTENER=yes"},
},
&container.HostConfig{
PortBindings: nat.PortMap{nat.Port("9092"): []nat.PortBinding{{HostIP: "0.0.0.0", HostPort: "9092"}}},
Mounts: []mount.Mount{{Type: mount.TypeVolume, Source: "kafka_data", Target: "/bitnami"}},
},
&network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{"orchestration": {NetworkID: "orchestration"}}},
nil,
"kafka",
)
答案2
得分: 0
HostIP
字段指定在主机上使用的IP地址以用于发布端口。它必须是主机系统上配置的IP地址之一,不能随意指定一个地址。最常见的设置是将其设置为"127.0.0.1"
,如果你希望从Docker空间之外的主机系统访问已发布的端口,但不希望其他主机访问。这相当于docker run -p
选项中偶尔使用的IP地址部分,例如docker run -p 127.0.0.1:8080:8080
。
你错误消息的直接原因是HostIP
地址不是主机上配置的地址,最简单的解决方法是删除该选项(它将默认为"0.0.0.0"
)。
另外,(*Client).ContainerCreate()
的第四个参数是一个network.NetworkingConfig
结构。你应该可以使用它将容器连接到自定义网络。
networkConfig := network.NetworkingConfig{
"mynet": &network.EndpointSettings{},
}
resp, err := dn.cl.ContainerCreate(
ctx,
&containerConfig,
&hostConfig,
&networkConfig,
nil,
containerName,
)
EndpointSettings
包括一个EndpointIPAMConfig
结构。如果你需要覆盖Docker的设置并在此处手动分配IP地址,你可以这样做。然而,由于Docker内部的IP地址并不特别有用,我建议让Docker为你选择一个地址(同样,我会跳过docker run --ip
选项)。
英文:
The HostIP
fields specify an IP address on the host machine to use for publishing ports. That has to be one of the IP addresses configured on the host system, you can't make up an address there. The most common thing you'd set it to is "127.0.0.1"
, if you want a published port to be accessible from the host system from outside of Docker space but not from other hosts. This is equivalent to the occasionally-used IP address part of the docker run -p
option, like docker run -p 127.0.0.1:8080:8080
.
The immediate cause of your error message is that the HostIP
address isn't one configured on the host, and the easiest solution is to just delete that option (it will default to "0.0.0.0"
).
Separately, the fourth parameter to (*Client).ContainerCreate()
is a network.NetworkingConfig
structure. You should be able to use this to attach the container to your custom network
networkConfig := network.NetworkingConfig{
"mynet": &network.EndpointSettings{},
}
resp, err := dn.cl.ContainerCreate(
ctx,
&containerConfig,
&hostConfig,
&networkConfig,
nil,
containerName,
)
The EndpointSettings
includes an EndpointIPAMConfig
structure. If you needed to override Docker's setup and manually assign IP addresses here, you could. However, since the Docker-internal IP addresses aren't especially useful, I'd let Docker pick an address for you (and, similarly, I'd skip the docker run --ip
option).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论