Search code examples
gowindows-10permission-denieddocker-for-windows

Go net.Listen() cannot bind to a docker service port after updating to docker version 19.03.2


I am using docker-compose to expose a docker service in my windows 10 machine.

Also, using a function in golang to check whether the service is completely up or not:

package main
import (
"fmt"
"net"
)

func main() {
    err := ping(9800)
    fmt.Println(err)
}


func ping(port uint16) (err error) {
    fmt.Println("checking port:", port)
    conn, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
    if err != nil {
        return
    }
    conn.Close()
    return
}

Docker and Go versions used now are:

C:\>docker version

Client: Docker Engine - Community
 Version:           19.03.2
 API version:       1.40
 Go version:        go1.12.8
 Git commit:        6a30dfc
 Built:             Thu Aug 29 05:26:49 2019
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.2
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.8
  Git commit:       6a30dfc
  Built:            Thu Aug 29 05:32:21 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.6
  GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
 runc:
  Version:          1.0.0-rc8
  GitCommit:        425e105d5a03fabd737a126ad93d62a9eeede87f
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683


C:\>go version

go version go1.13.1 windows/amd64

The container is up and the service is exposed via hostPort 50014:

C:\>docker ps

CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS         PORTS                      NAMES
48eeb27f5ddc   d.reg.io/adata   "/usr/local/bin/adat…"   7 seconds ago   Up 4seconds  0.0.0.0:50014->50014/tcp   desktop_adata_1

When running the go script to bind to the port 50014, it returns error:

C:\>go run ping.go

checking port: 50014
listen tcp 127.0.0.1:50014: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

This happens only after the update to docker-for-windows version 19.03.2.

Can someone help me to solve this issue?

UPDATE:

There is a question: What is Administered port exclusions in windows 10?

It is true that the port 50014 comes in administered port exclusions range.

I thought removing the port from that exclusion list or using any other port will work. But I used host ports 80, 8080, 50014 and 9800 one by one to expose the service and tried to bind them. But every time it failed.

Port 80 and 8080 are non-excluded ports. The container is up and the service is listening on the port. But gives error while trying to bind using the go function:

 checking port: 80
 listen tcp 127.0.0.1:80: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

Port 50014 is in administered port exclusion range. The container is up and the service is listening on the port. It also gives the same error while trying to bind:

 checking port: 80
 listen tcp 127.0.0.1:80: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

Port 9800 is in the normal port exclusion range. The difference is, this time the container will not be up. Docker cannot use that host port to expose a service. It will give an error when running docker-compose up -d :

Creating desktop_adata_1 ... error                                                                                                                                                                                                      
ERROR: for desktop_adata_1  Cannot start service adata: driver failed programming external connectivity on endpoint desktop_adata_1 (1a5978c5fbf35cb08fce14c8d5192756b3de8a77bd815f490e3e8ce542abaeaa): Error starting userland proxy: listen tcp 0.0.0.0:9800: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

That means, in my case, the reason for the error would be the net.Listen() fails to bind to a port that is used for a docker container service.


Solution

  • After docker update, net.Listen() was not able to ping to a port that is already used to expose a Docker container service.

    As a workaround, I used net.Dial() instead of net.Listen() in the go code. It works as expected.