在上一节中,我们讨论并使用了 named volume 将数据持久保存在数据库中。如果我们只想简单的存储数据,那么 named volume 就够用了,因为我们不必关心数据的存储位置。
这一节,将在介绍另外一种 volume 类型,即:bind mounts
使用 bind mounts 我们可以控制主机上的准确挂载点。虽然也可以用它来保存数据,但是通常是用它来向容器提供额外数据。比如:我们可以使用 bind mounts 将主机上的源代码挂载到容器中,以便容器可以及时感知源代码的变更。
对于基于 Node.js 的应用程序,[nodemon](https://npmjs.com/package/nodemon)是监视文件更改然后重新启动应用程序的好工具。大多数其他语言和框架都有类似的工具。
两种不同 Volume 类型的比较
named volumes 和 bind mounts 是 Docker 引擎内置的两种主要 Volume 类型。也可以使用其他类型的 Volume 驱动程序来支持其他使用场景,如 SFTP、Ceph、NetApp、S3 等…
| Named Volumes | Bind Mounts | |
|---|---|---|
| 在主机上的位置 | 由 Docker 自动选择 | 由你自己决定 |
挂载示例 (使用 -v 标记) |
my-volume:/usr/local/data | /path/to/data:/usr/local/data |
| 使用容器内容填充新 volume | 是 | 否 |
| 支持 Volume 驱动程序 | 是 | 否 |
启动一个开发模式的容器
为了运行一个支持开发工作流程的容器,我们将执行以下操作:
- 将我们的源代码挂载到容器中
- 安装所有依赖项,包括
dev依赖项 - 启动
nodemon来监听文件变化
让我们开始吧:
- 删除之前启动的
todo-app容器 执行以下命令:
docker run -dp 3000:3000 \-w /app \-v "$(pwd):/app" \node:12-alpine \sh -c "yarn install && yarn run dev"
如果使用的是 PowerShell,执行下面这条命令(只是
多行输入的分隔符不一样而已)docker run -dp 3000:3000 `-w /app `-v "$(pwd):/app" `node:12-alpine `sh -c "yarn install && yarn run dev"
-dp 3000:3000- 之前遇到过了,表示让容器保持在后台运行并做好端口映射-w /app- 设置 “working directory” - 工作目录-v "$(pwd):/app"-bind mount主机上的当前目录挂载到容器上的/app目录node:12-alpine- 使用的镜像sh -c "yarn install && yarn run dev"- 在容器中执行两条命令。由于 alpine 没有 bash,所以通过 sh 执行这两条命令,第一条:yarn install安装我们程序用到的依赖;第二条:yarn run dev启动服务。如果我们查看package.json文件就会发现dev脚本正是使用能够监听文件变化并自动重启服务的nodemon(一旦主机上的源码有变化,它能及时监听到,并自动重启 todo-app 服务)
由于上一条命令会在容器中执行安装依赖的操作,在不同的网络环境下的执行时间可能快也可能慢,因此需要等待一会才能访问我们的服务。可以通过
docker logs命令查看容器日志,先执行docker image ls查看容器ID,再执行docker logs -f <container-id>命令,如果看到日志输出了Listening on port 3000就代表我们的程序已经启动成功。docker logs -f <container-id>yarn install ...[1/4] Resolving packages...[2/4] Fetching packages.........[3/4] Linking dependencies...[4/4] Building fresh packages...Done in 93.42s.......$ nodemon src/index.js[nodemon] 1.19.2[nodemon] to restart at any time, enter `rs`[nodemon] watching dir(s): *.*[nodemon] starting `node src/index.js`Using SQLite database at /etc/todos/todo.dbListening on port 3000
看完日志后,按
Ctrl + C退出。- 现在,让我们来再一次修改源代码。将
src/static/js/app.js文件第 109 行的 “Add Item” 改成 “Add” - 只需刷新应用的首页,几乎就能立即在浏览器中看到更改。容器内部自动重新启动 Node 服务器可能需要花费几秒钟的时间,因此,如果访问页面出现错误,可以稍等几秒钟后再试。

- 至此,你可以随时在本机对应用程序源码进行任何更改。完成后,停止容器并使用
docker build -t todo-app .重新构建新镜像。
在本地开发模式下,使用bind mounts非常普遍。它的优点是使得本地开发机器不需要安装所有构建工具和环境。只需一条 docker run 命令,开发环境就准备就绪了。
回顾
本节我们学习了如何通过bind mounts快速搭建本地开发环境。
下一节我们准备将数据库从 SQLite 改成更适合生产环境使用的 MySQL。那么问题来了,我们该如何运行 MySQL? 如何让不同容器之间彼此通信?下节再详细说明。原始资料:Using Bind Mounts
