当前位置: 首页 > 后端技术 > Node.js

Windows下使用Docker部署Node.js开发环境

时间:2023-04-03 16:30:22 Node.js

开始部署Windows下的nodejs开发环境,真是坑坑洼洼。每次遇到问题,我都要google一下原因,想办法解决。而如果你要把自己写的应用程序交给别人跑来跑去,他可能也需要折腾很久,才能真正跑到他的环境里去。被坑了半天,终于放弃,转战Docker。关于Docker的介绍本文不再赘述。基本概念请参考Docker——从入门到实践。在中可以看到运行结果,方便后续调试。我可以把开发好的程序和运行环境打包在一起做成Docker镜像,交给小伙伴运行或者直接发布到服务器。安装和启动Docker引擎其核心是在Linux操作系统上运行的Linux容器。所以要在Windows上使用Docker容器,首先要提供一个Linux运行环境。到Docker官网下载msi安装程序。如果你的系统版本(如64位的Windows10专业版、企业版和教育版)支持Hyper-V虚拟化技术,那么你不需要使用额外的虚拟机(VirtualBox),安装程序会自动为你安装。完整的Docker(适用于Windows的Docker)。必须为DockerforWindows启用Hyper-V包才能工作。如果需要,DockerforWindows安装程序将为您启用它。(这需要重新启动)。如果您的系统不满足这些要求,您可以安装DockerToolbox,它使用OracleVirtualBox而不是Hyper-V。如果不能使用Hyper-V虚拟化技术,Docker项目组还提供了DockerToolBox工具,可以方便的在Windows环境下安装Docker。更多详细信息,请参考Docker官方文档-toolbox。本文执行系统为Win7,因此使用Docker工具箱。安装过程中还会安装OracleVMVirtualBox虚拟机,如下图所示:Kitematic是Docker的一个GUI管理工具。打开DockerTerminal即可快速启动Docker。可以发现此时Docker已经为默认机器分配了一个IP:192.168.99.100。我们可以直接在这个终端下执行Docker命令。由于在Windows中运行Docker多了一层虚拟机,所以有几个概念需要了解:Docker主机指的是Linux虚拟机,也就是说Docker主机的IP地址(即Linux虚拟机)此时是192.168.99.100。和一般的ssh访问虚拟机一样,我们也可以使用ssh通过这个IP登录Docker主机执行命令。(用户名:docker;密码:tcuser)如果想以root权限执行Linux命令(如mount),需要打开VirtualBox。构建镜像新安装的Docker主机中没有镜像(dockerimages查看已有镜像)。要运行节点应用程序,您需要构建节点环境映像。可以从DockerHub拉取一个轻量级的Linux镜像作为基础镜像(比如CentOS),然后在上面手动安装node;也可以直接拉取安装了node的镜像(dockerpullpulltakeamirrorimage)。从DockerHub下载镜像可能会很慢,可以使用国内云服务商(如daocloud.io)下载。现在假设我们拉取一个不包含节点环境的CentOS镜像。$dockerrun-itcentosbash启动一个容器,进入容器的bash进行交互操作。安装node的方法和CentOS下一样。exit在安装完成后退出容器。请放心,如果不使用dockerrm或者在dockerrun时不添加--rm参数,即使退出容器,容器本身及其修改也不会消失。您可以使用dockerps-a查看所有容器,使用dockerps查看正在运行的容器。$dockercommit将之前修改的容器提交到新的镜像中。镜像就是已经安装好node环境(命名为nodejs)的镜像。在后续的开发中,我们可以使用dockerrun-itnodejsbash来启动容器。Windows与虚拟机共享文件我们现在需要在Docker容器中运行源码,而Docker容器在Docker宿主机中,所以首先要保证Docker宿主机(即Linux虚拟机)机)可以访问Windows源代码文件。打开VirtualBox,点击“设置”->“共享文件夹”,指定路径和名称,勾选“自动挂载”和“固定分配”。“自动挂载”可以让虚拟机下次启动时自动挂载该文件夹,否则每次启动都需要手动重新挂载。顺利的话,重启虚拟机,输入mount命令,就可以看到共享文件夹挂载到哪里了,进入目录就可以看到与Windows同步的文件了。如果自动挂载遇到问题,取消该选项,使用以下命令手动挂载:mount-tvboxsfdocker_share在Docker容器中运行节点代码首先编辑Windows共享文件夹下的测试代码app.js:varhttp=require('http');http.createServer(function(req,res){res.writeHead(200,{'Content-Type':'text/plain'});res.end('HelloWorld\n');}).listen(1337);console.log('服务器运行在http://0.0.0.0:1337/');该文件可以在Docker主机中看到。使用nodejs图像启动容器。我们希望容器能够以源代码的形式访问Docker宿主机中的文件,也希望在Windows下能够访问运行的执行端口查看结果。使用以下命令启动容器:$dockerrun-v/docker_share:/app-p1337:1337-itnodejsbash-vhostdirectory:containerdatavolumedirectory使host目录挂载到容器中并可以访问由容器。-phostport:containerport使容器端口映射到主机并可从容器外部访问。注意:可以重复使用多个-p命令来映射多个端口。(Docker0.11及以上版本可以使用--net=host参数来映射Docker主机上容器中的所有端口。因此,也可以使用:)$dockerrun-v/docker_share:/app--net=host-itnodejsbash进入容器中对应的数据卷目录,在Windows下执行nodeapp.js,通过浏览器访问192.168.99.100:1337可以看到结果。至此,基本的node应用已经可以在Docker下运行了~进一步开发工作1.npminstall在node项目中一般都有node_modules依赖,需要用npminstall安装。在Docker下,这个命令也可以在应用程序期望运行的容器中执行。但要注意添加--no-bin-links指令以避免创建软链接。npm安装--no-bin-links2。关联其他服务和容器互联很多节点应用都会关联redis、mysql等服务。直接的,我们可以像windows下一样开启同一个容器的多个终端分别运行服务或者执行代码。使用如下命令进入一个正在运行的容器:$dockerexec-itbash更优雅的是,我们在不同的容器上运行不同的服务,然后使用--linkname:aliascontainerinterconnection将它们关联起来,看这篇博客了解详情。3、实时响应代码变更在开发过程中,如果每次修改代码都需要终止node进程,然后重启,会很麻烦。可以使用nodemon工具来实现监听代码变化并自动重启进程的效果,这样只需要在浏览器下刷新就可以看到新的运行效果。安装nodemon:npminstall-gnodemon还是以app.js为例,在容器中运行app.js时使用命令:nodemon-Lapp.js注意:如果不是在容器下运行,使用nodemonapp。js,并且在容器中,需要使用-L或者--legacy-watch参数开启Chokidar轮询,以便监控挂载目录下文件的变化。尝试更改app.js的内容。保存后可以发现nodemon自动重启了:刷新浏览器可以看到修改后的结果:关于nodemon,更详细的使用方法见GitHub-nodemon。将源码和环境打包为Image,编辑项目目录下的Dockerfile和.dockerignore文件。Dockerfile:从nodejs#创建应用程序目录RUNmkdir-p/usr/src/appWORKDIR/usr/src/app#安装应用程序依赖项COPYpackage.json/usr/src/app/RUNnpminstall#BundleappsourceCOPY。/usr/src/appEXPOSE8080CMD["npm","start"]FROM指定基础镜像,然后列出基于基础镜像需要做的操作命令。搭建新的镜像环境(包括复制源码和执行npminstall),可以参考node官方文档和这篇博文。.dockerignore:node_modulesnpm-debug.log在构建新图像时忽略其中的文件。在Docker宿主机的项目目录(Dockerfile所在目录)中,使用命令:$dockerbuild-t。//注意末尾的点不能省略,得到的是自建镜像。镜像会自动添加到你的dockerhost中,你可以直接启动新镜像的容器来运行代码(镜像中包含代码,不需要重复挂载到数据卷,但是不能在Windows下修改),或者您可以将图像分享给您的朋友。综上所述,应该可以满足基本的开发需求。虽然在Windows下使用Docker因为多了一层虚拟机会有点别扭,但是Docker本身使用容器和镜像来封装和隔离开发环境,还是带来了很多便利。以上是我初接触Docker的折腾结果。如有错误或更方便的方法,欢迎交流指正。