Why does this volumes section in a service in docker compose create a single anonymous volume?

I have a compose file that says:

    volumes:
      - dir:/unifi
      - data:/unifi/data
      - log:/unifi/log
      - cert:/unifi/cert
      - init:/unifi/init.d
      - run:/var/run/unifi
      # Mount local folder for backups and autobackups
      - ./backup:/unifi/data/backup
      # Enable updating of TLS cert inside running container
      - ./import_unifi_ssl_docker.sh:/import_unifi_ssl_docker.sh
      - /etc/letsencrypt:/etc/letsencrypt:ro

The named volumes are easily recognisable, but every time I run this service anew, an anynous container is created and this leads to a lot of dangling volumes.

I have three non-named volume statements. Do these lead somehow to this anonymous volume being needlessly created? Other services in the same compose only use named volumes and they do not create an anonymous volume. It is this one, that I have been able to determine.

Anonymous volumes are created if the Dockerfile declares a path as VOLUME, but neither a volume, nor a bind is mapped into this path for a container instance of this image. This is the result of the design choices an image maintainer did for their image and your choice to not mount anything into that path.

Btw.: mapping a host path into a container path is actually a bind, not a volume at all. It is literary a bind mount of a host directory into a container directory.

Thank you. I just had found this out as well.

The question then becomes: if I run this container from a compose file, how do I tell compose that it should do a removal of the anonymous volume mentioned in the Dockerfile during docker compose down? I cannot use docker compose down -v because that removes all the volumes, including the named ones (and these specifically exist to be persistent).

Or I should turn this into a named volume in my compose file.

If you mean “find out which container path requires a volume/bind mapping”, then yes. The problem is not whether you map a named volume or a bind to a container path. It is the absence of a required mapping that leads to the anonymous volume being created and used.

Just so you know your options: if you use Portainer to manage your docker host, it will highlight dangling containers and allow to only remove those.