I am trying to run a Docker container using Go SDK. From the terminal, I can run the following command with no issues :
docker run -d --memory 1024M --name "cdb1" -p 2001-2006:8091-8096 -p 11210-11211:11210-11211 couchbase
I want to achieve the same thing using the Docker SDK for Go but cannot find how to reproduce the -p 2001-2006:8091-8096
part. Here is my ContainerCreate call :
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",
)
But running this always throw the same error :
Error response from daemon: invalid port specification: "8091-8096"
Doing some more testing, the error seems to come specifically from the PortBindings
part (if I remove this one and leave the exposed ports, it works fine).
I couldn't find anything about this on Docker documentation.
nat.PortSet
is a map with nat.Port
being its key type:
type PortSet map[Port]struct{}
Your "port" specification of "2001-2006"
syntactically works because it's an untyped string constant and can be converted to nat.Port
which has string
as its underlying type, but this string literal lacks the protocol specification (e.g. tcp
or udp
).
Instead use the nat.NewPort()
function to create the key:
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{}{},
},
Note that the expected "raw" string format is "2001-2006/tcp"
which would also be accepted, but it's better to leave this internal detail to nat.NewPort()
.
And to construct a nat.PortMap
, use the nat.ParsePortSpec()
utility function. This is how you can assemble your 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}
}
}
Then you can use the portBindings
above for HostConfig.PortBindings
field:
&container.HostConfig{
PortBindings: portBindings ,
Resources: container.Resources{
Memory: 1024 * 1000000,
},
},