使用绑定挂载
在 第 5 部分 中,您使用了一个卷挂载来持久化数据库中的数据。当您需要一个持久的位置来存储您的应用程序数据时,卷挂载是一个不错的选择。
绑定挂载是另一种类型的挂载,它允许您将主机文件系统中的目录共享到容器中。在处理应用程序时,您可以使用绑定挂载将源代码挂载到容器中。容器会立即看到您对代码所做的更改,只要您保存了文件。这意味着您可以在容器中运行观察文件系统更改并响应它们的进程。
在本章中,您将了解如何使用绑定挂载和一个名为 nodemon 的工具来观察文件更改,然后自动重启应用程序。在大多数其他语言和框架中都有等效的工具。
快速卷类型比较
以下是使用 --mount
的命名卷和绑定挂载的示例。
- 命名卷:
type=volume,src=my-volume,target=/usr/local/data
- 绑定挂载:
type=bind,src=/path/to/data,target=/usr/local/data
下表概述了卷挂载和绑定挂载之间的主要区别。
命名卷 | 绑定挂载 | |
---|---|---|
主机位置 | Docker 选择 | 您决定 |
使用容器内容填充新卷 | 是 | 否 |
支持卷驱动程序 | 是 | 否 |
尝试使用绑定挂载
在查看如何使用绑定挂载来开发您的应用程序之前,您可以进行一个快速实验,以获得对绑定挂载工作原理的实际了解。
验证您的
getting-started-app
目录是否位于 Docker Desktop 文件共享设置中定义的目录中。此设置定义了您可以与容器共享的文件系统哪些部分。有关访问设置的详细信息,请参阅 Mac、Windows 或 Linux 的主题。打开终端并更改目录到
getting-started-app
目录。运行以下命令以使用绑定挂载在
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
--mount type=bind
选项告诉 Docker 创建一个绑定挂载,其中src
是您主机上的当前工作目录 (getting-started-app
),而target
是该目录应该出现在容器中的位置 (/src
)。运行该命令后,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
更改目录到
src
目录。这是您在启动容器时挂载的目录。列出此目录的内容将显示与主机上的
getting-started-app
目录中相同的文件。root@ac1237fad8db:/# cd src root@ac1237fad8db:/src# ls Dockerfile node_modules package.json spec src yarn.lock
创建一个名为
myfile.txt
的新文件。root@ac1237fad8db:/src# touch myfile.txt root@ac1237fad8db:/src# ls Dockerfile myfile.txt node_modules package.json spec src yarn.lock
打开主机上的
getting-started-app
目录并观察myfile.txt
文件是否在目录中。├── getting-started-app/ │ ├── Dockerfile │ ├── myfile.txt │ ├── node_modules/ │ ├── package.json │ ├── spec/ │ ├── src/ │ └── yarn.lock
从主机中删除
myfile.txt
文件。在容器中,再次列出
app
目录的内容。观察该文件现在是否消失了。root@ac1237fad8db:/src# ls Dockerfile node_modules package.json spec src yarn.lock
使用
Ctrl
+D
停止交互式容器会话。
这只是对绑定挂载的简要介绍。此过程演示了文件如何在主机和容器之间共享,以及更改如何立即反映在双方。现在您可以使用绑定挂载来开发软件。
开发容器
使用绑定挂载对于本地开发设置很常见。优点是开发机器不需要安装所有构建工具和环境。使用单个 docker run 命令,Docker 会拉取依赖项和工具。
在开发容器中运行您的应用程序
以下步骤描述了如何运行带有绑定挂载的开发容器,该容器执行以下操作
- 将您的源代码挂载到容器中
- 安装所有依赖项
- 启动
nodemon
来观察文件系统更改
您可以使用 CLI 或 Docker Desktop 运行带有绑定挂载的容器。
确保您没有当前正在运行的任何
getting-started
容器。从
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
。
您可以使用
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
容器。从
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
。
您可以使用
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
容器。从
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
。
您可以使用
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
容器。从
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
。
您可以使用
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
容器。
使用绑定挂载运行镜像。
选择 Docker Desktop 顶部的搜索框。
在搜索窗口中,选择镜像选项卡。
在搜索框中,指定容器名称
getting-started
。提示
使用搜索过滤器过滤镜像,只显示本地镜像。
选择您的镜像,然后选择运行。
选择可选设置。
在主机路径中,指定主机上
getting-started-app
目录的路径。在容器路径中,指定
/app
。选择运行。
您可以使用 Docker Desktop 观察容器日志。
- 在 Docker Desktop 中选择容器。
- 选择您的容器名称。
当您看到以下内容时,您就知道可以开始了
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
使用开发容器开发您的应用程序
更新主机上的应用程序,并查看更改是否反映在容器中。
在
src/static/js/app.js
文件中,在第 109 行,将“添加项目”按钮更改为仅显示“添加”。- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
保存文件。
刷新网页浏览器中的页面,您应该会看到更改几乎立即反映出来,因为使用了绑定挂载。Nodemon 检测到更改并重启服务器。Node 服务器可能需要几秒钟才能重启。如果您遇到错误,请尝试在几秒钟后刷新。
随意进行您想做的任何其他更改。每次您进行更改并保存文件时,更改都会反映在容器中,因为使用了绑定挂载。当 Nodemon 检测到更改时,它会自动重启容器中的应用程序。完成操作后,使用以下命令停止容器并构建您的新镜像
$ docker build -t getting-started .
总结
在这一点上,您可以持久化数据库,并在开发过程中看到应用程序的更改,而无需重新构建镜像。
除了卷挂载和绑定挂载之外,Docker 还支持其他挂载类型和存储驱动程序,用于处理更复杂和专门的用例。
相关信息
下一步
为了将您的应用程序准备好在生产环境中使用,您需要将数据库从使用 SQLite 迁移到能够更好地扩展的数据库。为了简单起见,您将继续使用关系型数据库,并将您的应用程序切换为使用 MySQL。但是,您应该如何运行 MySQL?您如何允许容器相互通信?您将在下一节中了解这些内容。