“volumes”如何使用 docker-compose 覆盖 docker 镜像的原始文件?

Bas*_*asj 4 wordpress docker docker-compose

让我们用这个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
Run Code Online (Sandbox Code Playgroud)

我注意到:

  • 做的时候

    mkdir wp
    docker-compose up
    # create a basic Wordpress website from the browser
    # stop the containers from the command-line with CTRL+C
    
    Run Code Online (Sandbox Code Playgroud)

    然后,./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
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

Dav*_*aze 8

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

当容器启动时,这意味着它可以查看其数据目录是否为空,如果是,则在其中安装一些初始数据。您引用了Docker Hubwordpress镜像;具有一个具有显式检查的入口点脚本

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

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

一般来说,您应该尝试为实际数据保留绑定安装和类似的卷,而不是在那里复制代码。就映像而言wordpress,由于它在卷中创建了应用程序的副本,因此如果您尝试升级基础映像,会发生什么并不完全明显:卷优先,升级可能会被忽略。

命名的 Docker 卷(与绑定挂载不同)将从底层映像复制内容,但前提是它是命名卷而不是其他类型的挂载,在 Docker 本身上(而不是在 Kubernetes 中),并且当该卷完全是空(这是您第一次运行容器)。避免依赖此行为,因为它不是特别可移植并且会忽略底层映像中的更新。