使用绑定挂载

第4部分中,您使用了卷挂载来持久化 数据库中的数据。当您需要一个持久化的地方来存储 应用程序数据时,卷挂载是一个很好的选择。

挂载卷是另一种类型的挂载,它允许您将主机文件系统中的目录共享到容器中。在开发应用程序时,您可以使用挂载卷将源代码挂载到容器中。容器会立即看到您对代码所做的更改,一旦您保存文件。这意味着您可以在容器中运行监视文件系统更改并对其做出响应的进程。

在本章中,您将看到如何使用绑定挂载和名为 nodemon 的工具来监视文件更改,然后自动 重新启动应用程序。大多数其他语言和框架中也有类似的工具。

快速卷类型比较

以下是使用 --mount 的命名卷和绑定挂载的示例:

  • 命名卷: type=volume,src=my-volume,target=/usr/local/data
  • 绑定挂载: type=bind,src=/path/to/data,target=/usr/local/data

下表概述了卷挂载和绑定挂载之间的主要区别。

命名卷挂载绑定
主机位置Docker 选择您决定
用容器内容填充新卷No
支持卷驱动程序No

尝试使用绑定挂载

在了解如何使用绑定挂载来开发应用程序之前, 你可以运行一个快速实验,以实际理解绑定挂载 的工作原理。

  1. 验证您的 getting-started-app 目录是否位于 Docker Desktop 文件共享设置中定义的目录内。该设置定义了您可以与容器共享的文件系统的哪些部分。有关访问设置的详细信息,请参阅 文件共享

  2. 打开终端并切换目录到 getting-started-app 目录。

  3. 运行以下命令以在带有绑定挂载的 ubuntu 容器中启动 bash


    $ docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash
    
    $ docker run -it --mount "type=bind,src=%cd%,target=/src" ubuntu bash
    
    $ docker run -it --mount type=bind,src="/$(pwd)",target=/src ubuntu bash
    
    $ docker run -it --mount "type=bind,src=$($pwd),target=/src" ubuntu bash
    

    --mount type=bind 选项告诉 Docker 创建一个绑定挂载,其中 src 是您主机上的当前工作目录(getting-started-app),而 target 是该目录在容器内部应出现的位置(/src)。

  4. 运行该命令后,Docker 会在容器文件系统的根目录中启动一个交互式的 bash 会话。

    root@ac1237fad8db:/# pwd
    /
    root@ac1237fad8db:/# ls
    bin   dev  home  media  opt   root  sbin  srv  tmp  var
    boot  etc  lib   mnt    proc  run   src   sys  usr
    
  5. 将目录更改为 src 目录。

    这是您在启动容器时挂载的目录。列出此目录的内容将显示与您主机上的 getting-started-app 目录相同的文件。

    root@ac1237fad8db:/# cd src
    root@ac1237fad8db:/src# ls
    Dockerfile  node_modules  package.json  spec  src  yarn.lock
    
  6. 创建一个名为 myfile.txt 的新文件。

    root@ac1237fad8db:/src# touch myfile.txt
    root@ac1237fad8db:/src# ls
    Dockerfile  myfile.txt  node_modules  package.json  spec  src  yarn.lock
    
  7. 在主机上打开 getting-started-app 目录,并观察到 myfile.txt 文件在该目录中。

    ├── getting-started-app/
    │ ├── Dockerfile
    │ ├── myfile.txt
    │ ├── node_modules/
    │ ├── package.json
    │ ├── spec/
    │ ├── src/
    │ └── yarn.lock
  8. 从主机中,删除 myfile.txt 文件。

  9. 在容器中,再次列出 app 目录的内容。观察发现文件现在已经消失了。

    root@ac1237fad8db:/src# ls
    Dockerfile  node_modules  package.json  spec  src  yarn.lock
    
  10. 使用 Ctrl + D 停止交互式容器会话。

这就是关于绑定挂载的简要介绍。此过程演示了主机和容器之间如何共享文件,以及更改如何立即在双方反映出来。现在您可以使用绑定挂载来开发软件。

开发容器

使用绑定挂载在本地开发环境中非常常见。其优点是开发机器无需安装所有构建工具和环境。只需一个 docker run 命令,Docker 就会拉取依赖项和工具。

在开发容器中运行您的应用程序

以下步骤描述了如何运行带有绑定挂载的开发容器,该挂载执行以下操作:

  • 将源代码挂载到容器中
  • 安装所有依赖项
  • 启动 nodemon 以监视文件系统更改

您可以使用 CLI 或 Docker Desktop 通过绑定挂载来运行您的容器。


  1. 确保您当前没有运行任何 getting-started 容器。

  2. getting-started-app 目录中运行以下命令。

    $ docker run -dp 127.0.0.1:3000:3000 \
        -w /app --mount type=bind,src="$(pwd)",target=/app \
        node:18-alpine \
        sh -c "yarn install && yarn run dev"
    

    以下是对该命令的详细解析:

    • -dp 127.0.0.1:3000:3000 - 与之前相同。以后台模式运行并 创建端口映射
    • -w /app - 设置“工作目录”或命令将运行的当前目录
    • --mount type=bind,src="$(pwd)",target=/app - 将主机的当前目录挂载到容器中的 /app 目录
    • node:18-alpine - 要使用的镜像。请注意,这是 Dockerfile 中用于您应用程序的基础镜像
    • sh -c "yarn install && yarn run dev" - 该命令。您正在使用 sh 启动一个 shell(alpine 没有 bash),然后运行 yarn install 安装软件包,接着运行 yarn run dev 启动开发服务器。如果您查看 package.json,会发现 dev 脚本启动了 nodemon
  3. 您可以使用 docker logs <container-id> 查看日志。当您看到以下内容时,您就知道可以开始了:

    $ docker logs -f <container-id>
    nodemon -L src/index.js
    [nodemon] 2.0.20
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching path(s): *.*
    [nodemon] watching extensions: js,mjs,json
    [nodemon] starting `node src/index.js`
    Using sqlite database at /etc/todos/todo.db
    Listening on port 3000
    

    当您查看完日志后,通过按下 Ctrl+C 退出。

  1. 确保您当前没有运行任何 getting-started 容器。

  2. getting-started-app 目录中运行以下命令。

    $ docker run -dp 127.0.0.1:3000:3000 `
        -w /app --mount "type=bind,src=$pwd,target=/app" `
        node:18-alpine `
        sh -c "yarn install && yarn run dev"

    以下是对该命令的详细解析:

    • -dp 127.0.0.1:3000:3000 - 与之前相同。以后台模式运行并 创建端口映射
    • -w /app - 设置“工作目录”或命令将运行的当前目录
    • --mount "type=bind,src=$pwd,target=/app" - 将主机的当前目录挂载到容器中的 /app 目录
    • node:18-alpine - 要使用的镜像。请注意,这是 Dockerfile 中用于您应用程序的基础镜像
    • sh -c "yarn install && yarn run dev" - 该命令。您正在使用 sh 启动一个 shell(alpine 没有 bash),然后运行 yarn install 安装软件包,接着运行 yarn run dev 启动开发服务器。如果您查看 package.json,会发现 dev 脚本启动了 nodemon
  3. 您可以使用 docker logs <container-id> 查看日志。当您看到以下内容时,您就知道可以开始了:

    $ docker logs -f <container-id>
    nodemon -L src/index.js
    [nodemon] 2.0.20
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching path(s): *.*
    [nodemon] watching extensions: js,mjs,json
    [nodemon] starting `node src/index.js`
    Using sqlite database at /etc/todos/todo.db
    Listening on port 3000
    

    当您查看完日志后,通过按下 Ctrl+C 退出。

  1. 确保您当前没有运行任何 getting-started 容器。

  2. getting-started-app 目录中运行以下命令。

    $ docker run -dp 127.0.0.1:3000:3000 ^
        -w /app --mount "type=bind,src=%cd%,target=/app" ^
        node:18-alpine ^
        sh -c "yarn install && yarn run dev"
    

    以下是对该命令的详细解析:

    • -dp 127.0.0.1:3000:3000 - 与之前相同。以后台模式运行并 创建端口映射
    • -w /app - 设置“工作目录”或命令将运行的当前目录
    • --mount "type=bind,src=%cd%,target=/app" - 将主机的当前目录挂载到容器中的 /app 目录
    • node:18-alpine - 要使用的镜像。请注意,这是 Dockerfile 中用于您应用程序的基础镜像
    • sh -c "yarn install && yarn run dev" - 该命令。您正在使用 sh 启动一个 shell(alpine 没有 bash),然后运行 yarn install 安装软件包,接着运行 yarn run dev 启动开发服务器。如果您查看 package.json,会发现 dev 脚本启动了 nodemon
  3. 您可以使用 docker logs <container-id> 查看日志。当您看到以下内容时,您就知道可以开始了:

    $ docker logs -f <container-id>
    nodemon -L src/index.js
    [nodemon] 2.0.20
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching path(s): *.*
    [nodemon] watching extensions: js,mjs,json
    [nodemon] starting `node src/index.js`
    Using sqlite database at /etc/todos/todo.db
    Listening on port 3000
    

    当您查看完日志后,通过按下 Ctrl+C 退出。

  1. 确保您当前没有运行任何 getting-started 容器。

  2. getting-started-app 目录中运行以下命令。

    $ docker run -dp 127.0.0.1:3000:3000 \
        -w //app --mount type=bind,src="/$(pwd)",target=/app \
        node:18-alpine \
        sh -c "yarn install && yarn run dev"
    

    以下是对该命令的详细解析:

    • -dp 127.0.0.1:3000:3000 - 与之前相同。以后台模式运行并 创建端口映射
    • -w //app - 设置“工作目录”或命令将运行的当前目录
    • --mount type=bind,src="/$(pwd)",target=/app - 将主机的当前目录挂载到容器中的 /app 目录
    • node:18-alpine - 要使用的镜像。请注意,这是 Dockerfile 中用于您应用程序的基础镜像
    • sh -c "yarn install && yarn run dev" - 该命令。您正在使用 sh 启动一个 shell(alpine 没有 bash),然后运行 yarn install 安装软件包,接着运行 yarn run dev 启动开发服务器。如果您查看 package.json,会发现 dev 脚本启动了 nodemon
  3. 您可以使用 docker logs <container-id> 查看日志。当您看到以下内容时,您就知道可以开始了:

    $ docker logs -f <container-id>
    nodemon -L src/index.js
    [nodemon] 2.0.20
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching path(s): *.*
    [nodemon] watching extensions: js,mjs,json
    [nodemon] starting `node src/index.js`
    Using sqlite database at /etc/todos/todo.db
    Listening on port 3000
    

    当您查看完日志后,通过按下 Ctrl+C 退出。

确保您当前没有运行任何 getting-started 容器。

使用绑定挂载运行镜像。

  1. 选择 Docker Desktop 顶部的搜索框。

  2. 在搜索窗口中,选择 镜像 标签页。

  3. 在搜索框中,指定容器名称,getting-started

    提示

    使用搜索过滤器来筛选镜像,仅显示本地镜像

  4. 选择您的镜像,然后选择 运行

  5. 选择可选设置

  6. 主机路径 中,指定您主机上 getting-started-app 目录的路径。

  7. 容器路径 中,指定 /app

  8. 选择 运行

您可以使用 Docker Desktop 查看容器日志。

  1. 在 Docker Desktop 中选择容器
  2. 选择您的容器名称。

当您看到以下内容时,您就知道已经准备就绪了:

nodemon -L src/index.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000

使用开发容器开发您的应用程序

在主机上更新您的应用程序,并在容器中查看反映的更改。

  1. src/static/js/app.js 文件中,在第 109 行,将“添加项目”按钮更改为仅显示“添加”:

    - {submitting ? 'Adding...' : 'Add Item'}
    + {submitting ? 'Adding...' : 'Add'}
    

    保存文件。

  2. 在您的网络浏览器中刷新页面,由于挂载绑定的原因,您应该能立即看到更改已生效。Nodemon 检测到更改并重新启动服务器。Node 服务器重新启动可能需要几秒钟的时间。如果出现错误,请在几秒钟后尝试刷新。

    Screenshot of updated label for Add button
  3. 您可以随意进行任何您想要的其他更改。每次您更改并保存文件时,由于绑定挂载,更改会反映在容器中。当 Nodemon 检测到更改时,它会自动重新启动容器内的应用程序。完成后,停止容器并使用以下命令构建新镜像:

    $ docker build -t getting-started .
    

摘要

此时,您可以持久化数据库,并在开发过程中查看应用程序的更改,而无需重新构建镜像。

除了卷挂载和绑定挂载之外,Docker还支持其他挂载类型和存储驱动程序,以处理更复杂和专业的用例。

相关信息:

后续步骤

为了让您的应用程序准备好投入生产环境,您需要将数据库从 SQLite 迁移到一种能更好地扩展的数据库。为了简单起见,您将继续使用关系型数据库,并将应用程序切换为使用 MySQL。但是,应该如何运行 MySQL?如何让容器之间相互通信?您将在下一节中了解到这些内容。