使用 bind mounts 快速搭建本地开发环境

zr - 2024-02-04 22:52:41 - 所属文档:Docker 快速入门文档

在上一节中,我们讨论并使用了 **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](https://github.com/vieux/docker-volume-sshfs)、[Ceph](https://ceph.com/geen-categorie/getting-started-with-the-docker-rbd-volume-plugin/)、[NetApp](https://netappdvp.readthedocs.io/en/stable/)、[S3](https://github.com/elementar/docker-s3-volume) 等... | | Named Volumes | Bind Mounts | | ---------------------------------------------- | --------------------------- | ------------------------------- | | 在主机上的位置 | 由 Docker 自动选择 | 由你自己决定 | | 挂载示例 (使用 `-v` 标记) | my-volume:/usr/local/data | /path/to/data:/usr/local/data | | 使用容器内容填充新 volume | 是 | 否 | | 支持 Volume 驱动程序 | 是 | 否 | ## 启动一个开发模式的容器 为了运行一个支持开发工作流程的容器,我们将执行以下操作: * 将我们的源代码挂载到容器中 * 安装所有依赖项,包括 `dev` 依赖项 * 启动 `nodemon` 来监听文件变化 让我们开始吧: 1. 删除之前启动的 `todo-app` 容器 2. 执行以下命令: ``` 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 服务) 3. 由于上一条命令会在容器中执行安装依赖的操作,在不同的网络环境下的执行时间可能快也可能慢,因此需要等待一会才能访问我们的服务。可以通过 `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.db Listening on port 3000 ``` 看完日志后,按 `Ctrl + C` 退出。 4. 现在,让我们来再一次修改源代码。将 `src/static/js/app.js` 文件第 109 行的 "Add Item" 改成 "Add" 5. 只需刷新应用的首页,几乎就能立即在浏览器中看到更改。容器内部自动重新启动 Node 服务器可能需要花费几秒钟的时间,因此,如果访问页面出现错误,可以稍等几秒钟后再试。 ![Screenshot of updated label for Add button](https://bianxuebianzuo.oss-cn-shenzhen.aliyuncs.com/uploads/photos/1/2021/08/07/kiT3b1628305588_Screenshot_of_updated_label_for_Add_button1617270009.png) 6. 至此,你可以随时在本机对应用程序源码进行任何更改。完成后,停止容器并使用 `docker build -t todo-app .` 重新构建新镜像。 在本地开发模式下,使用 `bind mounts` 非常普遍。它的优点是使得本地开发机器不需要安装所有构建工具和环境。只需一条 docker run 命令,开发环境就准备就绪了。 ## 回顾 本节我们学习了如何通过 `bind mounts` 快速搭建本地开发环境。 下一节我们准备将数据库从 SQLite 改成更适合生产环境使用的 MySQL。那么问题来了,我们该如何运行 MySQL? 如何让不同容器之间彼此通信?下节再详细说明。 > 原始资料:[Using Bind Mounts](https://docs.docker.com/get-started/06_bind_mounts/)