使用绑定挂载
在 第4部分中,您使用了卷挂载来持久化数据库中的数据。当您需要一个持久的地方来存储应用程序数据时,卷挂载是一个很好的选择。
绑定挂载是另一种类型的挂载,它允许你将主机文件系统中的目录共享到容器中。在开发应用程序时,你可以使用绑定挂载将源代码挂载到容器中。容器会立即看到你对代码所做的更改,只要你保存了文件。这意味着你可以在容器中运行进程,这些进程会监视文件系统的更改并对其作出响应。
在本章中,您将看到如何使用绑定挂载和一个名为nodemon的工具来监视文件更改,然后自动重新启动应用程序。在大多数其他语言和框架中也有类似的工具。
快速卷类型比较
以下是使用--mount的命名卷和绑定挂载的示例:
- 命名卷:
type=volume,src=my-volume,target=/usr/local/data - 绑定挂载:
type=bind,src=/path/to/data,target=/usr/local/data
下表概述了卷挂载和绑定挂载之间的主要区别。
| Named volumes | Bind mounts | |
|---|---|---|
| Host location | Docker chooses | You decide |
| Populates new volume with container contents | Yes | No |
| Supports Volume Drivers | Yes | No |
尝试绑定挂载
在了解如何使用绑定挂载来开发应用程序之前,您可以运行一个快速实验,以实际理解绑定挂载的工作原理。
请确认您的
getting-started-app目录位于 Docker Desktop 文件共享设置中定义的目录内。此设置定义了您可以与容器共享的文件系统的哪些部分。有关访问此设置的详细信息,请参阅 文件共享。打开终端并切换到
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$ 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- same as before. Run in detached (background) mode and create a port mapping-w /app- sets the "working directory" or the current directory that the command will run from--mount type=bind,src="$(pwd)",target=/app- bind mount the current directory from the host into the/appdirectory in the containernode:18-alpine- the image to use. Note that this is the base image for your app from the Dockerfilesh -c "yarn install && yarn run dev"- the command. You're starting a shell usingsh(alpine doesn't havebash) and runningyarn installto install packages and then runningyarn run devto start the development server. If you look in thepackage.json, you'll see that thedevscript startsnodemon.
你可以使用
docker logs查看日志。当你看到以下内容时,你就知道已经准备好了:$ 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- same as before. Run in detached (background) mode and create a port mapping-w /app- sets the "working directory" or the current directory that the command will run from--mount "type=bind,src=$pwd,target=/app"- bind mount the current directory from the host into the/appdirectory in the containernode:18-alpine- the image to use. Note that this is the base image for your app from the Dockerfilesh -c "yarn install && yarn run dev"- the command. You're starting a shell usingsh(alpine doesn't havebash) and runningyarn installto install packages and then runningyarn run devto start the development server. If you look in thepackage.json, you'll see that thedevscript startsnodemon.
你可以使用
docker logs查看日志。当你看到以下内容时,你就知道已经准备好了:$ 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- same as before. Run in detached (background) mode and create a port mapping-w /app- sets the "working directory" or the current directory that the command will run from--mount "type=bind,src=%cd%,target=/app"- bind mount the current directory from the host into the/appdirectory in the containernode:18-alpine- the image to use. Note that this is the base image for your app from the Dockerfilesh -c "yarn install && yarn run dev"- the command. You're starting a shell usingsh(alpine doesn't havebash) and runningyarn installto install packages and then runningyarn run devto start the development server. If you look in thepackage.json, you'll see that thedevscript startsnodemon.
你可以使用
docker logs查看日志。当你看到以下内容时,你就知道已经准备好了:$ 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- same as before. Run in detached (background) mode and create a port mapping-w //app- sets the "working directory" or the current directory that the command will run from--mount type=bind,src="/$(pwd)",target=/app- bind mount the current directory from the host into the/appdirectory in the containernode:18-alpine- the image to use. Note that this is the base image for your app from the Dockerfilesh -c "yarn install && yarn run dev"- the command. You're starting a shell usingsh(alpine doesn't havebash) and runningyarn installto install packages and then runningyarn run devto start the development server. If you look in thepackage.json, you'll see that thedevscript startsnodemon.
您可以使用
docker logs查看日志。当您看到以下内容时,您就知道已经准备好了:$ 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桌面中选择Containers。
- 选择您的容器名称。
当你看到这个时,你就知道你已经准备好了:
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?如何让容器之间相互通信?你将在下一节中学习这些内容。