一步步教你利用Docker设置Node.js


Posted in Javascript onNovember 20, 2018

前言

docker是一个开源的应用容器引擎,可以为我们提供安全、可移植、可重复的自动化部署的方式。docker采用虚拟化的技术来虚拟化出应用程序的运行环境。如上图一样。docker就像一艘轮船。而轮船上面的每个小箱子可以看成我们需要部署的一个个应用。使用docker可以充分利用服务器的系统资源,简化了自动化部署和运维的繁琐流程,减少很多因为开发环境中和生产环境中的不同引发的异常问题。从而提高生产力。

docker三个核心概念如下:

  • 镜像(images):一个只读的模板,可以理解为应用程序的运行环境,包含了程序运行所依赖的环境和基本配置。相当于上图中的每个小箱子里面装的东西。
  • 仓库(repository):一个用于存放镜像文件的仓库。可以看做和gitlab一样。
  • 容器(container):一个运行应用程序的虚拟容器,他和镜像最大的区别在于容器的最上面那一层是可读可写的。 相当于上图中的每个小箱子里。

本文主要是教大家了解如何在Docker容器中设置Node JS:

有一个可运行工作的NodeJS应用程序

通过确保进程在出错时不退出,使节点应用程序具有弹性

通过在代码更改时自动重新启动服务器,使Node应用程序易于使用

利用Docker:

  • 快速设置与生产相同的开发环境。
  • 轻松地能够在本地和服务器上切换节点版本
  • Docker的所有其他 好处

先决条件

Docker已经安装好了

至少入门级节点知识和NPM

1.获取一个简单的Node应用程序

我们将使用Express,因为它的设置是容易的。

在一个干净的目录中,让我们从初始化NPM开始,继续运行此命令并按照提示进行操作:

npm init

安装Express:

npm install --save-prod express

编制代码src/index.js

<b>const</b> express = require('express')
<b>const</b> app = express()
<b>const</b> port = 3000

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => {console.log(`Example app listening on port ${port}!`))

启动一个侦听端口3000并使用Hello World响应的"/"这个URL路由。

2.设置Docker以运行我们的Node应用程序

我们将使用docker-compose.yml文件来启动和停止我们的Docker容器,而不是键入长长的Docker命令。您可以将此文件视为多个Docker容器的配置文件。

docker-compose.yml:

version: "3"
services:
 app:
 container_name: app # How the container will appear when listing containers from the CLI
 image: node:10 # The <container-name>:<tag-version> of the container, in this case the tag version aligns with the version of node
 user: node # The user to run as in the container
 working_dir: "/app" # Where to container will assume it should run commands and where you will start out if you go inside the container
 networks:
 - app # Networking can get complex, but for all intents and purposes just know that containers on the same network can speak to each other
 ports:
 - "3000:3000" # <host-port>:<container-port> to listen to, so anything running on port 3000 of the container will map to port 3000 on our localhost
 volumes:
 - ./:/app # <host-directory>:<container-directory> this says map the current directory from your system to the /app directory in the docker container
 command: "node src/index.js" # The command docker will execute when starting the container, this command is not allowed to exit, if it does your container will stop

networks:
 app:

让我们用这个命令启动docker容器。在后台运行(-d)

docker-compose up -d

在浏览器中访问http://localhost:3000并看到 Hello World!

3. 使得应用变得弹性

如果您之前使用过Node,那么您可能知道如果应用程序中发生错误(如未捕获的异常),那么它将关闭该Node进程。这对我们来说真的是个坏消息,因为我们的代码中肯定会有一个错误,并且无法保证我们的代码100%无错误。此问题的解决方案通常是另一个监视我们的Node应用程序并在其退出时重新启动它的过程。有这么多的解决方案,比如linux的supervisord,NPM包永远和PM2等......我们只需要为本指南选择一个。

将专注于 PM2, 因为我最熟悉它,除了进程管理之外还有一些其他功能,例如文件监视,这将在下一节中派上用场。

安装PM2

npm install --save-prod pm2

PM2可以通过命令行使用,但我们将设置一个简单的配置文件,就像我们使用docker-compose.yml文件一样,以防止我们重复输入长命令

ecosystem.config.js:

const path = require('path')

module.exports = {
 apps: [{
 name: 'app',
 script: 'src/index.js', // Your entry point
 instances: 1,
 autorestart: true, // THIS is the important part, this will tell PM2 to restart your app if it falls over
 max_memory_restart: '1G'
 }]
}

现在我们应该更改docker-compose.yml文件以使用PM2启动我们的应用程序,而不是直接从index.js启动它。

docker-compose.yml(仅更改了的选项)

version: "3"
services:
 app:
 container_name: app # How the container will appear when listing containers from the CLI
 image: node:10 # The <container-name>:<tag-version> of the container, in this case the tag version aligns with the version of node
 user: node # The user to run as in the container
 working_dir: "/app" # Where to container will assume it should run commands and where you will start out if you go inside the container
 networks:
 - app # Networking can get complex, but for all intents and purposes just know that containers on the same network can speak to each other
 ports:
 - "3000:3000" # <host-port>:<container-port> to listen to, so anything running on port 3000 of the container will map to port 3000 on our localhost
 volumes:
 - ./:/app # <host-directory>:<container-directory> this says map the current directory from your system to the /app directory in the docker container
 command: "npx pm2 start ecosystem.config.js --no-daemon" # The command docker will execute when starting the container, this command is not allowed to exit, if it does your container will stop

networks:
 app:

更改docker-compose.yml文件不会影响已经运行的容器。为了进行更改,您应该重新启动容器:

docker-compose restart

4.使我们的应用程序易于开发

您可能已经注意到,一旦Node进程启动,那么在重新启动Node进程之前,更改代码实际上并没有做任何事情,对于我们而言,每次都会涉及重新启动Docker容器以激活我们做出的改变。如果我们在进行代码更改时自动为我们重新启动Node进程,那将是理想的选择。

在过去,我已经完成了诸如引入文件监视实用程序和使用该文件监视实用程序来重新启动Docker进行文件更改之类的操作,或者我会使用Nodemon但是在使用Docker时会有一些警告。

最近,当文件发生变化时,我一直在使用PM2来重新启动我的Node进程,而且由于我们已经从上一步中获取了它,因此我们不必安装另一个依赖项。

ecosystem.config.js(仅添加了watch选项):

const path = require('path')

module.exports = {
 apps: [{
  name: 'app',
  script: 'src/index.js',
  instances: 1,
  autorestart: true,
  watch: process.env.NODE_ENV !== 'production' ? path.resolve(__dirname, 'src') : false,
  max_memory_restart: '1G'
 }]
}

如果我们没有将NODE_ENV环境变量设置为production,则上面的配置文件现在将监视src目录。您可以通过更改index.js文件来测试它,除了Hello World之外还可以将其他内容打印到浏览器中!。在此之前,您需要重新启动Docker容器,因为您更改了PM2运行容器的方式:

docker-compose restart

重新启动Node进程可能需要一秒钟才能完成,如果你想观察它何时完成,你可以看到你的Docker日志告诉PM2何时完成重启你的Node Process:

docker-compose logs -f

总结

  • 我们的目标之一是能够轻松更改Node版本,您可以通过更改docker-compose.yml文件中的image选项来完成此操作。
  • 本地安装依赖项是使用本地NPM和Node版本完成的,如果您的本地版本与Dockers不同,有时可能会导致冲突。使用相同的Docker容器来安装依赖项更安全。您可以使用此命令来使用该容器来安装依赖项,然后将其删除
docker run --rm -i -v <absolute-path-to-your-project-locally>:/app -w /app node:10 npm install
  • 如上所述,具有与Docker运行的Node不同的本地版本可能是有问题的。最好在容器内部运行命令以保持一致性。你可以进入一个容器
docker exec -it app bash

上面的命令将把你放到容器中,这样你就可以继续从里面运行命令,即npm run start或npm run test

如果您不想进入容器内部,可以运行这样的命令

docker exec -t app bash -c "npm run start"

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JavaScript中函数声明优先于变量声明的实例分析
Mar 01 Javascript
js实现的map方法示例代码
Jan 13 Javascript
JavaScript操作Cookie详解
Feb 28 Javascript
两种JS实现屏蔽鼠标右键的方法
Aug 20 Javascript
基于Vuejs实现购物车功能
Aug 02 Javascript
js中常用的Math方法总结
Jan 12 Javascript
angular实现图片懒加载实例代码
Jun 08 Javascript
详解一个小实例理解js原型和继承
Apr 24 Javascript
React路由鉴权的实现方法
Sep 05 Javascript
浅谈layui 绑定form submit提交表单的注意事项
Oct 25 Javascript
解决vue.js提交数组时出现数组下标的问题
Nov 05 Javascript
vue项目接口域名动态获取操作
Aug 13 Javascript
JS滚轮控制图片缩放大小和拖动的实例代码
Nov 20 #Javascript
vue中的适配px2rem示例代码
Nov 19 #Javascript
JS监听事件的叠加和移除功能
Nov 19 #Javascript
微信小程序自定义弹窗wcPop插件
Nov 19 #Javascript
Vue.js 使用v-cloak后仍显示变量的解决方法
Nov 19 #Javascript
Vue.js 中的 v-cloak 指令及使用详解
Nov 19 #Javascript
浅析Vue.js 中的条件渲染指令
Nov 19 #Javascript
You might like
为php4加入动态flash文件的生成的支持
2006/10/09 PHP
PHP中Session的概念
2006/10/09 PHP
PHP以指定字段为索引返回数据库所取的数据数组
2013/06/30 PHP
国外十大最流行的PHP框架排名
2013/07/04 PHP
Linux下创建nginx脚本-start、stop、reload…
2014/08/03 PHP
JS注册/移除事件处理程序(ExtJS应用程序设计实战)
2013/05/07 Javascript
JS 实现导航栏悬停效果
2013/09/23 Javascript
javascript得到当前页的来路即前一页地址的方法
2014/02/18 Javascript
使用jQuery判断IE浏览器版本的代码
2014/06/14 Javascript
JavaScript实现点击单选按钮改变输入框中文本域内容的方法
2015/08/12 Javascript
JS实现灵巧的下拉导航效果代码
2015/08/25 Javascript
Clipboard.js 无需Flash的JavaScript复制粘贴库
2015/10/02 Javascript
基于jquery二维码生成插件qrcode
2017/01/07 Javascript
详解React Native网络请求fetch简单封装
2017/08/10 Javascript
vue 项目中使用Loading组件的示例代码
2018/08/31 Javascript
PM2自动部署代码步骤流程总结
2018/12/10 Javascript
JS实现头条新闻的经典轮播图效果示例
2019/01/30 Javascript
Vue form表单动态添加组件实战案例
2019/09/02 Javascript
详细分析Node.js 多进程
2020/06/22 Javascript
vue修改Element的el-table样式的4种方法
2020/09/17 Javascript
解决VUE项目使用Element-ui 下拉组件的验证失效问题
2020/11/07 Javascript
基于Python socket的端口扫描程序实例代码
2018/02/09 Python
PyCharm设置每行最大长度限制的方法
2019/01/16 Python
Python面向对象封装操作案例详解
2019/12/31 Python
Python模拟登录requests.Session应用详解
2020/11/17 Python
Python常用断言函数实例汇总
2020/11/30 Python
python 基于selenium实现鼠标拖拽功能
2020/12/24 Python
纯CSS3实现的阴影效果
2014/12/24 HTML / CSS
新奇的小玩意:IWOOT
2016/07/21 全球购物
美国宠物美容和宠物用品购物网站:Cherrybrook
2018/12/07 全球购物
HelloFresh奥地利:立即订购烹饪盒
2019/02/22 全球购物
adidas泰国官网:adidas TH
2020/07/11 全球购物
材料物理专业大学毕业生求职信
2013/10/15 职场文书
毕业生找工作自荐书
2014/06/30 职场文书
病人家属写给医院的感谢信
2015/01/23 职场文书
MySQL分库分表详情
2021/09/25 MySQL