如何在Go SDK中指定Docker容器的网络?

huangapple go评论72阅读模式
英文:

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

您可以通过在EndpointSettingsNetworkID字段中使用名称来指定先前创建的网络。

例如,要创建一个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).

huangapple
  • 本文由 发表于 2022年8月18日 23:30:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/73405757.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定