【问题标题】:How does "volumes" override the docker image's original files with docker-compose?“volumes”如何用 docker-compose 覆盖 docker 镜像的原始文件?
【发布时间】:2020-10-08 23:05:34
【问题描述】:

让我们使用这个docker-compose.yml

version: '2'
services:
   db:
     image: mysql:5.7
     volumes:
       - ./mysql:/var/lib/mysql                # <- important
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress
   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     volumes:
       - ./wp:/var/www/html                    # <- important
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress

我注意到:

  • 什么时候做

    mkdir wp
    docker-compose up
    # create a basic Wordpress website from the browser
    # stop the containers from the command-line with CTRL+C
    

    然后,./wp/(最初为空)将填充新的 Wordpress 文件 (**)。这是正常的。

  • 那就开始吧

     docker rm wordpress_1 db_1   # remove the existing containers but keep 
                                  # ./wp/ as it has been created in the previous step (**)
     docker-compose up
    

    在重新创建容器期间,./wp/ 不会被新的 Wordpress 文件覆盖,而是保留上一步 (**) 中的先前文件!为什么?

    它如何神奇地知道 Wordpress 文件应该被写入,而是应该保留以前的文件?

问题:docker 如何决定 volumes: 中列出的 /hostdir/:/containerdir/ 是否应该覆盖原始 docker 映像中已经存在的文件?

【问题讨论】:

标签: wordpress docker docker-compose


【解决方案1】:

使用该语法绑定挂载总是会覆盖映像中存在的文件。这与普通 Linux mount(8) 命令的作用相同:如果您在源目录的一部分上挂载 USB 磁盘之类的东西,则挂载设备的内容会隐藏文件系统中的原始内容, 而所有的读写都使用挂载的设备。

当容器启动时,这意味着它可以查看其数据目录是否为空,如果是,则在其中安装一些初始数据。你引用Docker Hub wordpress image;有一个entrypoint script 有一个明确的检查

if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then
    echo >&2 "WordPress not found in $PWD - copying now..."
    # ... some code that creates sourceTarArgs and targetTarArgs ...
    tar "${sourceTarArgs[@]}" . | tar "${targetTarArgs[@]}"
    echo >&2 "Complete! WordPress has been successfully copied to $PWD"
fi

mysql 图像有类似的检查来查看其数据目录是否为空。如果是,则进行首次初始化,包括处理/docker-entrypoint-initdb.d 目录;如果不是,则假定那里有预先存在的数据并完全跳过初始化步骤。

一般来说,您应该尝试为实际数据保留绑定装载和类似的卷,而不是在那里复制您的代码。对于wordpress 映像,由于它会在卷中复制应用程序,因此如果您尝试升级底层映像会发生什么并不完全清楚:卷优先,升级可能会被忽略。

命名的 Docker 卷(与绑定挂载不同)将从底层映像复制内容,但如果它是命名卷而不是某种其他类型的挂载, 在 Docker 上(不在 Kubernetes 中),在卷完全为空的情况下(这是您第一次运行容器)。避免依赖这种行为,因为它不是特别便携,并且会忽略底层图像中的更新。

【讨论】:

  • 感谢您的精彩回答! PS:究竟什么是“绑定挂载”? (不熟悉这个术语)。 Here我看到是关于bindfs的,但就我而言,我只是想链接一个本地目录
  • 在 Docker 中,该术语意味着将主机文件系统的一部分挂载到容器文件系统空间中。 Docker 文档讨论了bind mountsnamed volumes
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多