一步步教你利用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 相关文章推荐
JS小功能(offsetLeft实现图片滚动效果)实例代码
Nov 28 Javascript
用jQuery toggleClass 实现鼠标移上变色
May 14 Javascript
javascript实现dom元素可拖动
Mar 21 Javascript
JS中如何实现Laravel的route函数详解
Feb 12 Javascript
ES6中Class类的静态方法实例小结
Oct 28 Javascript
原生JS写Ajax的请求函数功能
Dec 22 Javascript
6行代码实现微信小程序页面返回顶部效果
Dec 28 Javascript
详解vue项目中使用token的身份验证的简单实践
Mar 08 Javascript
小程序click-scroll组件设计
Jun 18 Javascript
Nuxt.js实战和配置详解
Aug 05 Javascript
JavaScript中变量提升和函数提升的详解
Aug 07 Javascript
vue3.0+vue-router+element-plus初实践
Dec 02 Vue.js
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
gd库图片下载类实现下载网页所有图片的php代码
2012/08/20 PHP
php删除与复制文件夹及其文件夹下所有文件的实现代码
2013/01/23 PHP
PHP截断标题且兼容utf8和gb2312编码
2013/09/22 PHP
php5.5中类级别的常量使用介绍
2013/10/02 PHP
PHP实现仿Google分页效果的分页函数
2015/07/29 PHP
Laravel使用PHPQRCODE实现生成带有LOGO的二维码图片功能示例
2017/07/07 PHP
JavaScript flash复制库类 Zero Clipboard
2011/01/17 Javascript
基于JavaScript实现瀑布流效果(循环渐近)
2016/01/27 Javascript
jQuery Ajax页面局部加载方法汇总
2016/06/02 Javascript
详解微信小程序 页面跳转 传递参数
2016/12/08 Javascript
JS实现京东首页之页面顶部、Logo和搜索框功能
2017/01/12 Javascript
基于VUE选择上传图片并页面显示(图片可删除)
2017/05/25 Javascript
Angular实现的进度条功能示例
2018/02/18 Javascript
js实现带有动画的返回顶部
2020/08/09 Javascript
Vue解决移动端弹窗滚动穿透问题
2020/12/15 Vue.js
[01:35]辉夜杯战队访谈宣传片—LGD
2015/12/25 DOTA
Python 变量类型及命名规则介绍
2013/06/08 Python
python正则分组的应用
2013/11/10 Python
pygame播放音乐的方法
2015/05/19 Python
浅谈Matplotlib简介和pyplot的简单使用——文本标注和箭头
2018/01/09 Python
python rsa实现数据加密和解密、签名加密和验签功能
2019/09/18 Python
Jupyter notebook运行Spark+Scala教程
2020/04/10 Python
Pycharm2020.1安装中文语言插件的详细教程(不需要汉化)
2020/08/07 Python
python中Mako库实例用法
2020/12/31 Python
编写html5时调试发现脚本php等网页js、css等失效
2013/12/31 HTML / CSS
Coltorti Boutique官网:来自意大利的设计师品牌买手店
2018/11/09 全球购物
英国领先的独立时装店:Van Mildert
2019/10/28 全球购物
Java程序员综合测试题
2014/04/25 面试题
金属材料工程毕业生个人的自我评价
2013/11/28 职场文书
个人委托书怎么写
2014/04/04 职场文书
公安局副政委班子个人对照检查材料
2014/10/04 职场文书
小学语文的各类谚语(70首)
2019/08/15 职场文书
二年级作文之动物作文
2019/11/13 职场文书
Java实现二分搜索树的示例代码
2022/03/17 Java/Android
nginx刷新页面出现404解决方案(亲测有效)
2022/03/18 Servers
Java 常见的限流算法详细分析并实现
2022/04/07 Java/Android