How to specify a docker container's network in go SDK

Viewed 27

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 Answers

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).

Related