从何而起
最近偶尔有同学说项目运行出错了, 一排查往往是切换了 node 版本, 比如需要重新编译一下 node-sass (其实脚手架早换成了 dart-sass, 太低版本突然升级有些许风险), 以及少部分使用 windows 开发的同学因为删除 node_modules 清缓存时常出现“假删”的现象, 想着是否有必要本地开发使用 CI 构建的镜像来保证环境的一致性, 况且其他大厂的 云IDE 听说也是进行得比较火热, 我们只是落地本地 docker 开发或许会容易很多
目标
考虑到大部分同学对 docker 不是很了解, 本次的目标希望是能够一行命令让 docker 把项目运行起来
如何达成目标
docker 中运行 git 命令需要生成 ssh key 怎么办 ?
每次进入 docker 都需要重新配置下环境, 终究还是不妥当, 后面想了一会决定通过 docker 数据卷 volumes 去把本地的 .ssh 目录给映射到 docker, 让本机和 docker 共享一份配置
团队的 npm 还有权限控制怎么办 ?
其实和上面问题的解决办法是一致的, 再把 .npmrc 文件也通过 docker 数据卷 volumes 去映射一下
如何编写代码
如果大家是在 docker 中编写代码的话, 可能需要比较厚实的 vim 功底, 还是通过 vscode 的 VS Code Remote Development 去做了,感觉比较麻烦,况且现在都在本机,不如还是通过 docker 数据卷 volumes 把当前项目的目录给映射过去, 大家还是保持现在的 vscode 开发, 图示的内容我们都没有做 😅
好像问题都解决了
最后也是顺利运行起了 docker 命令, 但发现本地浏览器访问开发的地址始终是服务无响应, 问题出在哪了 ?
debug
主机到容器的端口映射的问题 ?
起一个简单的 http server 就能验证了, 最后发现下面的方式是能有响应的。
1 | const http = require('http') |
那就是 WebpackDevServer 的问题了
WebpackDevServer 启动的代码类似于下面, 和上面的简单的 http server 的区别在于 listen 参数 host 传了值
1 | const devServer = new WebpackDevServer(compiler, devServerConfig) |
debug 一看这里的 host 值为 localhost, 而 localhost 只是一个本地通常使用的域名, 在 /etc/hosts 文件中进行了绑定, 它的背后其实是 127.0.0.1
1 | 127.0.0.1 localhost |
即如果 docker 中监听 127.0.0.1 将会造成上面说的本机访问服务无响应的问题
没有传 host 参数的默认值是什么了
现在让我们回头再看简单的 http server 不传 host 参数默认值会是什么, 通过下面的代码也发现了默认会去绑定 :: 或者 0.0.0.0, 后面我们以 0.0.0.0 为例, 关于 ip 协议可以继续阅读 是时候说说到底什么是IPv4和IPv6了!
1 | // lib/net.js |
127.0.0.1 与 0.0.0.0
可以仔细阅读一下两者的官方解释, 简单概括就是
- 127.0.0.1 通常用于本机中各个应用之间的网络交互, 与其他主机关联访问会存在障碍
- 0.0.0.0 可以代表本机的所有 IPv4 地址, 适用性会更广, 当在 docker 监听时, 外部能够访问得到, 再比如监听 0.0.0.0 时, 可通过 ifconfig 命令用本机的 ip 地址去访问,而前者则不行
127.0.0.1
127.0.0.1是回送地址,指本地机,一般用来测试使用。回送地址(127.x.x.x)是本机回送地址(Loopback Address),即主机IP堆栈内部的IP地址,主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,协议软件立即返回,不进行任何网络传输。
0.0.0.0
0.0.0.0,在这里意味着 “本地机器上的所有IP地址”(实际上可能是 “本地机器上的所有IPv4地址”)。因此,如果你的webserver机器有两个IP地址,192.168.1.1和10.1.2.1,而你允许像apache这样的webserver守护程序监听0.0.0.0,它在这两个IP地址上都可以到达。但是,只有能与这些IP地址和网络端口联系的才可以。
开始开发
到这里终于可以愉快的在 docker 中进行开发了, 最后记录下 docker 运行的命令
- 把配置文件映射到 docker 中
- 把当前项目目录映射到 docker 的 temp 目录中
- 本机与 docker 端口进行一下映射
- 运行某个镜像的 id
1
2
3
4
5
6
7docker run -t -i \
-v ~/.ssh:/root/.ssh \
-v ~/.npmrc:/root/.npmrc \
-v $(pwd):/temp \
-p 3000:3000 \
00eb8ccbb6d0 \
/bin/bash
小结
docker 中构建时间会明显长一些, 编译大型项目有些许卡顿, 快速运行一个 puppeteer 镜像进行一些测试是个不错的选择~