skip to Main Content

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?

2

Answers


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

    Login or Signup to reply.
  2. 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",
        )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search