告别 Docker Volumes👋
有没有尝试过在 Web 应用中使用 Docker 卷进行热加载?如果你也有和我一样糟糕的体验,那么 Docker 刚刚发布的最新功能docker-compose watch一定会让你爱不释手!接下来,我将向你展示如何升级现有项目,打造一个让你的团队乐在其中的 Docker 开发环境🤩
TL;DR:查看此docker-compose文件和官方文档
让我们开始吧!
介绍
Docker 刚刚发布了Docker Compose Watch,其中包含Docker Compose 2.22 版本。借助此新功能,您可以使用 ,docker-compose watch
并docker-compose up
自动将本地源代码与 Docker 容器中的代码同步,而无需使用卷!
让我们通过我之前写过的一个项目来看看它在实际项目中是如何运作的。
在这个项目中,我有一个 monorepo,它有前端、后端以及一些用于 UI 和数据库的附加库。
├── apps
│ ├── api
│ └── web
└── packages
├── database
├── eslint-config-custom
├── tsconfig
└── ui
两个应用程序(api
和)均已 dockerized ,web
并且 Dockerfiles 位于项目的根目录中(1、2)
该docker-compose.yml
文件看起来如下:
services:
web:
build:
dockerfile: web.Dockerfile
ports:
- "3000:3000"
depends_on:
- api
api:
build:
dockerfile: api.Dockerfile
ports:
- "3001:3000"from within the Docker network
这已经很不错了,但正如你所知,在开发过程中使用它是一件很麻烦的事。每当你修改代码时,你都必须重建 Docker 镜像,即使你的应用程序可能支持开箱即用的热加载(如果不支持,可以使用Nodemon之类的工具)。
为了改善这种情况,Docker Compose Watch引入了一个名为 的新属性watch
。watch 属性包含一个所谓的规则列表,每个规则都包含一个它们正在监视的路径以及路径中文件发生变化时执行的操作。
同步
如果您希望在主机和容器之间同步文件夹,您可以添加:
services:
web: # shortened for clarity
build:
dockerfile: web.Dockerfile
develop:
watch:
- action: sync
path: ./apps/web
target: /app/apps/web
每当主机上路径中的文件./apps/web/
发生更改时,它将同步(复制)到您的容器中/app/apps/web
。目标路径中的附加应用程序是必需的,因为它是在DockerfileWORKDIR
中定义的。如果您有可热重载的应用程序,这可能是您主要使用的东西。
重建
如果您有需要编译的应用程序或需要重新安装的依赖项,还有一个名为rebuild的操作。它不是简单地在主机和容器之间复制文件,而是会重建并重新启动容器。这对您的 npm 依赖项非常有帮助!让我们添加以下内容:
services:
web: # shortened for clarity
build:
dockerfile: web.Dockerfile
develop:
watch:
- action: sync
path: ./apps/web
target: /app/apps/web
- action: rebuild
path: ./package.json
target: /app/package.json
每当我们的 package.json 发生变化时,我们都会重建整个 Dockerfile 来安装新的依赖项。
同步+重启
除了同步和重建之外,还有一个介于两者之间的操作,称为同步+重启。此操作将首先同步目录,然后立即重启容器而无需重建。大多数框架通常都包含一些配置文件(例如next.config.js
),这些配置文件无法热重载(仅同步是不够的),但也不需要缓慢的重建。
这会将您的撰写文件更改为:
services:
web: # shortened for clarity
build:
dockerfile: web.Dockerfile
develop:
watch:
- action: sync
path: ./apps/web
target: /app/apps/web
- action: rebuild
path: ./package.json
target: /app/package.json
- action: sync+restart
path: ./apps/web/next.config.js
target: /app/apps/web/next.config.js
注意事项
一如既往,天下没有免费的午餐,但也有一些注意事项😬
新属性最大的问题watch
是路径仍然非常基础。文档指出,目前还不支持 Glob 模式,如果要更具体一些,则可能需要大量的规则。
以下是一些有效和无效的示例:
✅apps/web
这将匹配(例如,但也)中的所有文件./apps/web
./apps/web/README.md
./apps/web/src/index.tsx
❌build/**/!(*.spec|*.bundle|*.min).js
遗憾的是(目前?)不支持 Glob
❌~/Downloads
所有路径都相对于项目根目录!
后续步骤
如果您仍然对您的 Docker 设置不满意,仍然有很多方法可以改进它!
协作是软件开发的重要组成部分,而各自为政可能会严重损害您的团队。缓慢的 Docker 构建和复杂的设置更是雪上加霜!为了解决这个问题并促进协作文化,您可以使用 Docker 扩展程序(例如Livecycle)立即与团队成员共享本地 docker-compose 应用。由于您已经在使用 Docker 和 docker-compose,因此只需安装Docker 桌面扩展程序并点击共享开关即可。您的应用将被隧道传输到互联网,您可以与团队分享您的专属 URL 来获取反馈!如果您想了解更多 Livecycle 的用例,我在这篇文章中对此进行了更详细的介绍 :)
与往常一样,请确保您的 Dockerfile 遵循最佳实践,尤其是在多阶段构建和缓存方面。虽然这可能会增加编写初始 Dockerfile 的难度,但它会让您的 Docker 应用在开发过程中更加易于使用。
创建一个基本.dockerignore
文件并将依赖项安装与代码构建分开大有帮助!
结论
一如既往,希望你今天学到了新东西!如果你需要任何 Docker 项目设置方面的帮助,或者有其他反馈,请告诉我。
干杯,
Jonas 联合创始人sliplane.io