Docker:绑定安装的奇怪行为

moe*_*man 1 docker docker-compose docker-volume

我有一个撰写文件:

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
Run Code Online (Sandbox Code Playgroud)

当我运行 docker-compose up 来启动 2 个容器时,我注意到:

  • Docker 自动创建目录 postgres-data,并将 /var/lib/postgresql/data 的内容从容器传输到主机目录postgres-data
  • 通过后端服务,Docker 还会自动创建目录 ./app,但它不是将 /app 目录(从容器)的内容传输到主机中的 ./app 目录,而是执行相反的操作将内容从容器传输到主机中。主机中的 ./app 目录到容器中的 /app

这两个服务都使用绑定挂载,据我了解:绑定挂载始终将内容从主机目录传输到容器。但在 db 服务的情况下不会发生这种情况

那么我这里哪里理解错了呢?

提前致谢

Dav*_*aze 5

没有任何东西会被“转移”。主机目录的内容始终隐藏底层镜像中的内容,一旦容器启动,主机和容器目录就是“相同的”;一侧的写入应该在另一侧可见。

Docker Hub 数据库镜像尤其知道在启动时查看其数据目录。顺序大致是这样的:

  1. Docker 创建一个容器,并在容器中$PWD/postgres-data替换主机的目录。/var/lib/postgresql/data
  2. 图像postgres的入口点脚本查看数据目录,发现它完全是空的。然后,它创建一个新数据库并运行任何首次初始化脚本。由于该目录是绑定安装的主机目录,因此该内容在主机上也是可见的。
  3. 无论数据库的数据目录是什么,数据库都会正常启动。

这项工作是在容器启动时在挂载的目录上完成的,因此它恰好在主机上也是可见的。(如果您docker run --rm -it --entrypoint /bin/sh postgres环顾四周,绕过其入口点脚本,您可能会发现该/var/lib/postgresql/data目录完全是空的;没有任何内容可以“传输到主机”。)

这也意味着您在应用程序容器/app目录上的绑定挂载隐藏了 Dockerfile 所做的任何事情;如果您运行构建序列,它将丢失,并且如果主机和容器中的目录布局不相同,您将遇到不可重现的问题。这进一步意味着您不能直接使用卷从映像中复制文件;您必须运行一个运行cp命令的容器。