The process cannot access the file error with Docker Compose

I came across this error the other day when I was working on windows with Docker

 Cannot start service db: failed to create endpoint dotnet-album-viewer_db_1 on network nat: failed during hnsCallRawResponse: hnsCall failed in Win32: The process cannot access the file because it is being used by another process. (0x20)

To say it’s misleading would be charitable – I was confused by this confusing message. Found the answer but it was a bit scattered over the internet so I thought I would bring it together.

The error

Consider this docker-compose.yml file

version: '3.2'

services:
  db:
    image: dockersamples/tidb:nanoserver-sac2016
    ports:
      - "3306:4000"

  app:
    image: dockersamples/dotnet-album-viewer
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
      - "80:80"
    environment:
      - "Data:Provider=MySQL"
      - "Data:ConnectionString=Server=db;Port=4000;Database=AlbumViewer;User=root;SslMode=None"      
    depends_on:
      - db

networks:
  default:
    external:
      name: nat

We are running a database container (db) and an application container (app). When we run

docker-compose up -d

to bring up the containers we get the error

Cannot start service db: failed to create endpoint dotnet-album-viewer_db_1 on network nat: failed during hnsCallRawResponse: hnsCall failed in Win32: The process cannot access the file because it is being used by another process. (0x20)

It makes it seem like the container is locked in some way, perhaps two instances running concurrently. That’s not the issue.

The cause

The problem is that we are running the containers on ports that have been taken by other processes. So, in my case it is both the database container and the application server that are at fault

Database container

  db:
    image: dockersamples/tidb:nanoserver-sac2016
    ports:
      - "3306:4000"

The database container connects on port 4000 in the network internal to the containers.  The second port 3306 is what is exposed to the host machine. It’s port 3306 that is already taken by another process. To find which application is running on that port use netstat and PowerShell i.e.

netstat -aon | findstr 3306

which gives

MySql is on port 3306 hence I can’t run a container on that port and I get the weird ‘process cannot access file’ error. That does make sense as the image dockersamples/tidb:nanoserver-sac2016 is a MySQL compatible database – so it’s on the same port.

Application container

The application server is also targeting an in-use port

  app:
    image: dockersamples/dotnet-album-viewer
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
      - "80:80"

The application container will use port 80 internally and also port 80 externally. I don’t need to go the trouble of running netstat. I know I’ve got a webserver (IIS) on that machine which has a default website running on port 80. I should have spotted that straight away and been a bit less baffled.

The resolution

I can either kill the processes that are taking that port or change the external port that the docker containers are going to use. I don’t really want to kill MySQL or IIS so I need 2 new ports.

I tend to use ports above 49200 as they are dynamic ports and are less likely to be in use (though I tend to use them up myself, so I still get clashes). Specifically

Well-known ports range from 0 through 1023.
Registered ports are 1024 to 49151.
Dynamic ports (also called private ports) are 49152 to 65535.

Once you’ve identified a port you can check if it’s in use by using netstat again

netstat -aon | findstr 49301

And see if you get a result. So, the final resolution is

version: '3.2'

services:
  db:
    image: dockersamples/tidb:nanoserver-sac2016
    ports:
      - "49301:4000"

  app:
    image: dockersamples/dotnet-album-viewer
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
      - "49250:80"
    environment:
      - "Data:Provider=MySQL"
      - "Data:ConnectionString=Server=db;Port=4000;Database=AlbumViewer;User=root;SslMode=None"      
    depends_on:
      - db

networks:
  default:
    external:
      name: nat

So db and app external ports are now in the dynamic range and when I run

docker-compose up -d

the error is gone, and my containers and the application come up. Lovely.

Useful links

The examples in this post come from here https://github.com/docker/labs/blob/master/windows/windows-containers/WindowsContainers.md

Useful post on how to check if your ports are in use. Further detail and explanation to what I’ve posted here.

List of well known ports https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers. Searching for port 3306 on Wikipedia would have shown me that it’s in use by MySQL. I guess a lot of people would have just known this. I didn’t.

Stack overflow answer as a reminder on which port in the docker-compose file is the external port and which one is the one used internally by docker. Spoiler alert: the first one is the externally exposed port and the second one is use by the applications running inside of the docker containers. It’s the first port that is causing us the problems.

Leave a Reply

Your email address will not be published. Required fields are marked *