一步步教你利用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 URL锚点取值方法
Feb 25 Javascript
input 高级限制级用法
Mar 26 Javascript
jquery事件机制扩展插件 jquery鼠标右键事件
Dec 21 Javascript
setTimeout的延时为0时多个浏览器的区别
May 23 Javascript
JavaScript代码简单实现求杨辉三角给定行的最大值
Oct 29 Javascript
document.compatMode的CSS1compat使用介绍
Apr 03 Javascript
无限树Jquery插件zTree的常用功能特性总结
Sep 11 Javascript
jquery 构造函数在表单提交过程中修改数据
May 25 Javascript
jQuery弹出层插件popShow用法示例
Jan 23 Javascript
JS/jQuery实现超简单的Table表格添加,删除行功能示例
Jul 31 jQuery
jquery实现的分页显示功能示例
Aug 23 jQuery
vue+Element-ui实现分页效果
Nov 15 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
php方法调用模式与函数调用模式简例
2011/09/20 PHP
PHP处理excel cvs表格的方法实例介绍
2013/05/13 PHP
浅析十款PHP开发框架的对比
2013/07/05 PHP
一个完整的PHP类包含的七种语法说明
2015/06/04 PHP
通过PHP简单实例介绍文件上传
2015/12/16 PHP
ThinkPHP路由机制简介
2016/03/23 PHP
php图片上传类 附调用方法
2016/05/15 PHP
PHP实现的最大正向匹配算法示例
2017/12/19 PHP
javascript 写类方式之六
2009/07/05 Javascript
JQuery加载图片自适应固定大小的DIV
2013/09/12 Javascript
基于JQuery实现的图片自动进行缩放和裁剪处理
2014/01/31 Javascript
jQuery on方法传递参数示例
2014/12/09 Javascript
js实现浏览本地文件并显示扩展名的方法
2015/08/17 Javascript
JS实现快速的导航下拉菜单动画效果附源码下载
2016/11/01 Javascript
Vue一个案例引发的递归组件的使用详解
2018/11/15 Javascript
jQuery模拟html下拉多选框的原生实现方法示例
2019/05/30 jQuery
Node.js 的 GC 机制详解
2019/06/03 Javascript
vue实现codemirror代码编辑器中的SQL代码格式化功能
2019/08/27 Javascript
微信小程序云函数添加数据到数据库的方法
2020/03/04 Javascript
老生常谈Python进阶之装饰器
2017/05/11 Python
Python实现将照片变成卡通图片的方法【基于opencv】
2018/01/17 Python
Python中py文件引用另一个py文件变量的方法
2018/04/29 Python
ubuntu上安装python的实例方法
2019/09/30 Python
python实现企业微信定时发送文本消息的实例代码
2020/11/25 Python
HTML5 HTMLCollection和NodeList的区别详解
2020/04/29 HTML / CSS
高尔夫球鞋、服装、手套和装备:FootJoy
2018/12/15 全球购物
国际商务专业学生个人的自我评价
2013/09/28 职场文书
乡镇消防工作实施方案
2014/03/27 职场文书
社区优秀志愿者先进事迹
2014/05/09 职场文书
中学生社会实践活动总结
2014/07/03 职场文书
教师自我剖析材料范文
2014/09/30 职场文书
2014乡镇领导班子四风对照检查材料思想汇报
2014/10/05 职场文书
刑事附带民事上诉状
2015/05/23 职场文书
师德师风培训感言
2015/08/03 职场文书
2016年百日安全生产活动总结
2016/04/06 职场文书
php 获取音视频时长,PHP 利用getid3 获取音频文件时长等数据
2021/04/01 PHP