Unexpected Volume Occurs When Using Docker Compose [duplicate]

Solution 1:

You are not making use of named volumes. When the left side of your volume configuration refers to an existing host path, this is a "bind mount", not a named volume. When you start your compose stack, this configuration:

    volumes:
    - /data/postgres:/data/postgres

Means that the host path /data/postgres is mounted on /data/postgres in the container.

A named volume configuration would look like this:

version: "3"

services:
      
  postgres:
    container_name: postgres
    image: postgres:latest
    ports:
    - "5432:5432"
    volumes:
    - postgres_data:/data/postgres
    env_file:
    - docker.env
    networks:
    - postgres

volumes:
  postgres_data:

You can read more about volumes in the documentation. The docker-compose syntax is in the syntax reference.

The other volumes you see in the output of e.g. docker volumes probably correspond to anonymous volumes configured in the images you're using. For example, the pgadmin image has a volume mounted at /var/lib/pgadmin:

$ docker pull docker.io/dpage/pgadmin4
$ docker inspect docker.io/dpage/pgadmin4 | jq .[0].ContainerConfig.Volumes
{
  "/var/lib/pgadmin": {}
}

Solution 2:

The Docker Hub postgres image keeps its data in /var/lib/postgresql/data (see "Where to store data" in the extended description). You need to change the bind mount so that's the second directory named there.

volumes:
  - /data/postgres:/var/lib/postgresql/data
  #                ^^^^^^^^^^^^^^^^^^^^^^^^
  #            second half must be this exact path

This is why you're not seeing data persisted in the host directory; it's getting mounted on the wrong path.

Meanwhile, the image's Dockerfile contains a VOLUME declaration for that directory. That causes Docker to create an anonymous volume for that directory if nothing else is mounted there. The docker-compose down documentation notes:

Anonymous volumes are not removed by default [by docker-compose down]. However, as they don’t have a stable name, they will not be automatically mounted by a subsequent up.

So that's why you're also not seeing database data preserved across restarts either; fixing the mount path will address this.

(In an earlier question you were asking where the extra volumes came from, and it's the anonymous volumes created by the Dockerfile VOLUME. @larsks's answer has a good discussion on the different between named volumes and bind mounts; the anonymous volumes they refer to at the end of their answer are the same VOLUME mechanic.)