Docker: Strange behaviour of bind mount

99封情书 提交于 2021-02-08 07:42:35

问题


I have a compose file:

version: "3"
services:

  db:
    image: postgres:12.5
    ports:
      - "15432:5432"
    restart: always  
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: test
    volumes:
      - ./postgres-data:/var/lib/postgresql/data

  backend:
    image: backend
    depends_on:
      - db
    restart: always
    ports:
      - "6969:8000"
    volumes:
      - ./app:/app

When I run docker-compose up to start the 2 containers, I notice that:

  • Docker auto creates the directory postgres-data, and it transfers the content of /var/lib/postgresql/data from container to host directory postgres-data
  • With the backend service, Docker also auto creates the directory ./app, but instead of transfer the content of the /app directory (from container) to the ./app directory in host, it did the opposite: it transfer the content from the ./app directory in host to the /app in container.

Both service uses bind mount, and as I understand: bind mount always transfer the content from the host directory to the container. But this does not happen in the case of the db service

So where did I understand wrong here ?

Thanks in advance


回答1:


Nothing ever gets "transferred". The contents of the host directory always hide what was in the underlying image, and once the container has started, the host and container directories are "the same"; writes in one side should be visible in the other.

The Docker Hub database images in particular know to look at their data directories at startup time. The sequence is roughly like this:

  1. Docker creates a container, with the host's $PWD/postgres-data directory replacing /var/lib/postgresql/data in the container.
  2. The postgres image's entrypoint script looks at the data directory and sees it is totally empty. It then creates a new database and runs any first-time-initialization scripts. Since that directory is a bind-mounted host directory, this content is also visible on the host.
  3. The database starts up normally with whatever its data directory is.

This work is done on the mounted directory at container startup time, so it happens to be visible on the host as well. (If you docker run --rm -it --entrypoint /bin/sh postgres and look around, bypassing its entrypoint script, you'll probably find the /var/lib/postgresql/data directory is totally empty; there is nothing there to be "transferred to the host".)

This also means that your bind mount over the application container's /app directory hides whatever the Dockerfile does; if you run a build sequence it will get lost, and if the directory layouts in the host and container aren't identical, you will have non-reproducible problems. This further means you can't directly use volumes to copy file out of an image; you have to run a container that runs a cp command.




回答2:


I must admit that I thought this behaviour only worked with volume mounts and not bind mounts. The documentation for the volume long syntax indicates the copy mode is only available to volume mounts.



来源:https://stackoverflow.com/questions/65955098/docker-strange-behaviour-of-bind-mount

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!