GVKun编程网logo

使用 PM2 在 Docker 上部署 Node.js Web 应用(pm2-docker)

2

如果您想了解使用PM2在Docker上部署Node.jsWeb应用和pm2-docker的知识,那么本篇文章将是您的不二之选。我们将深入剖析使用PM2在Docker上部署Node.jsWeb应用的各个

如果您想了解使用 PM2 在 Docker 上部署 Node.js Web 应用pm2-docker的知识,那么本篇文章将是您的不二之选。我们将深入剖析使用 PM2 在 Docker 上部署 Node.js Web 应用的各个方面,并为您解答pm2-docker的疑在这篇文章中,我们将为您介绍使用 PM2 在 Docker 上部署 Node.js Web 应用的相关知识,同时也会详细的解释pm2-docker的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

使用 PM2 在 Docker 上部署 Node.js Web 应用(pm2-docker)

使用 PM2 在 Docker 上部署 Node.js Web 应用(pm2-docker)

背景

本文介绍 PM2 在 Docker 上部署 Node.js Web 应用。

  • PM2 是守护进程管理器,它将帮助您管理和保持 Nodejs 应用程序 24/7 在线。
  • Docker 是一个开放源代码软件,是一个开放平台,用于开发应用、交付(shipping)应用、运行应用。 Docker 允许用户将基础设施(Infrastructure)中的应用单独分割出来,形成更小的颗粒(容器),从而提高交付软件的速度。

一,项目初始化

新建项目 docker-nodejs-pm2-demo,目录结构说明如下:

.
|-- Dockerfile # Docker 构建配置
|-- README.md 
|-- app.js # Nodejs 应用入口
|-- ecosystem.config.js # pm2 配置文件
复制

二,Nodejs 应用

Nodejs Web 应用入口 app.js 文件内容。点击查看

const http = require(''http'');

http.createServer((request, response) => {
    response.writeHead(200, {''Content-Type'': ''text/plain''});
    response.end(''Docker-nodejs-pm2-demo, Hello World!'');
}).listen(8080);
复制

三,PM2 配置

PM2 配置文件 ecosystem.config.js 内容。点击查看

module.exports = {
    apps : [{
        name: "docker-nodejs-pm2-demo",
        script: "./app.js",
        instances: 1,
        env: {
            NODE_ENV: "development",
        },
        env_production: {
            NODE_ENV: "production",
        },
        exec_mode: ''cluster'',
        combine_logs: true,
        out_file: ''/dev/null''
    }]
}
复制

四,Dockerfile

Docker 配置文件 Dockerfile 内容。点击查看

FROM keymetrics/pm2 

# 暴露端口
EXPOSE 8080

WORKDIR /data/release/docker-nodejs-pm2-demo

# 创建目录
RUN mkdir -p /data/release/docker-nodejs-pm2-demo

# 复制源码
COPY . /data/release/docker-nodejs-pm2-demo

# 容器启动时,启动应用服务
CMD ["pm2-runtime", "ecosystem.config.js", "--only", "docker-nodejs-pm2-demo"]
复制

五,Docker 部署应用

5.1. 获取源代码

文章中的示列源码托管到 Github,可直接克隆使用。点击查看

# clone 项目
$ git clone https://github.com/yorkiyu/docker-nodejs-pm2-demo.git

# 进入项目目录
$ cd docker-nodejs-pm2-demo 

# 构建镜像
$ docker build -t docker-nodejs-pm2-demo:2 .

# 查看镜像
$ docker images
复制

5.2. 启动容器

# 启动容器,指定容器中的端口 8080 与宿主机的端口 8080 绑定
$ docker run -d -p 8080:8080 docker-nodejs-pm2-demo:2

# 查看容器
$ docker ps
复制

5.3. 进入容器

# 进入容器
$ docker exec -it 61288ea7784f sh 

# 在容器中查看 pm2 进程
$ pm2 ls
复制

5.4. 访问应用

使用 curl 访问 Nodejs Web 应用。点击查看 curl 教程

$ curl -v http://127.0.0.1:8080
复制

参考

  • [1] Docker部署nodejs应用并使用PM2作为守护进程
  • [2] PM2 Documentation
  • [3] Docker Documentation

Docker - 入门(二),docker&nodeJs制作镜像与本地部署

Docker - 入门(二),docker&nodeJs制作镜像与本地部署

在熟悉docker基本命令与运作逻辑后,尝试实战。

目标:制作一个nodejs服务镜像,并使用nginx反向代理,在本地跑通。

本次项目配置与工具构成:

  1. node后端:使用阿里的 Egg.js 脚手架
  2. db:mongodb
  3. nginx
  4. NoSqlBooster for MongoDB,一个mongodb可视化工具
  5. postman 一个可以发起网络请求的工具,用于测试

注:本机操作系统为 macOS

本文主讲docker部分,其余知识面仅描述部分

准备工作:

  1. docker镜像:nginx:latest、node:10.15.3、mongo:latest
  2. docker-compose可用
  3. Egg.js脚手架初始化后端项目,命名为 egg-center

项目配置

Egg.js

安装egg-mongoose库,以便连接mongodb。

数据库配置,修改./config/config.default.js

  config.mongoose = {
    clients: {
      center: {
        url: ''mongodb://你本地的内网ip:27017/example'',
        options: {
          dbName: ''center'', // 数据库名,自己取
          user: '''', // 连接数据库的账号,默认为空
          pass: '''', // 连接数据库的账号,默认为空
        }
      }
    }
  }
接下来写一个后台用户管理系统

在 ./app/controller 下新增对应的控制器、在./app/model下新增对应的表结构。

然后写几个简单的接口,修改:./app/router.js,定义路由:

''use strict''

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const { router, controller } = app
  router.get(''/'', controller.home.index)

  /* 新增用户 */
  router.post(''/api/admin/user'', controller.admin.user.create)
  
  /* 用户列表 */
  router.get(''/api/admin/user'', controller.admin.user.index)
  
  ...略
}

本地启动服务测试: npm run dev
本地使用 postman 调通接口,造些测试数据。

修改package.json

"start": "egg-scripts start --deamon --title=egg-server-egg-center",

修改为:

"start": "egg-scripts start --title=egg-server-egg-center",

删除出--deamon,我们是在docker里跑项目,所以需要node服务跑在docker前台。

配置Dockerfile

Egg.js根目录(./)下新增文件:

  1. Dockerfile // Egg.js镜像制作的配置文件
  2. docker-compose.yml // Egg.js和nginx容器的配置
  3. mongodb-compose.yml // mongodb容器的配置
  4. nginx.conf // nginx配置文件

我们本次部署不使用jenkins,采用较为简单的部署方式。

解释下为什么要把mongodb的配置单独写:
1.绝大部分情况,数据库都是不关闭的,而业务服务器和nginx是会随着版本迭代等影响重启,所以将mongodb的配置单独拎出来
2.业务服务会依赖mongodb启动,若写在同一个docker-compose文件里会出现异步问题,即mongodb还未完全启动至ready状态,node服务已经启动连接数据库报错了。

接下来看文件内容。

Dockerfile:

FROM node:10.15.3 # 使用node:10.15.3镜像
RUN mkdir -p /egg-center # 在容器中新建目录文件夹 egg-center
WORKDIR /egg-center # 将 /egg-center 设置为默认工作目录
COPY package.json /egg-center/package.json
RUN yarn --production # 先copy package.json文件至容器,并安装依赖
COPY . /egg-center # 再copy代码至容器。也可以部分先后直接copy整个代码
EXPOSE 7006 # 暴露7006端口

docker-compose.yml:

version: ''3''
services:
  nginx:
    image: nginx:latest # 使用nginx:latest镜像
    ports:
      - 8080:8080 # 宿主机端口:容器端口
    volumes:
      - "/Users/liaoxinyu/JsProject/eggJsProject/server/egg-center/nginx.conf:/etc/nginx/conf.d/nginx.conf" # 挂载nginx配置文件
  egg-center:
    build:
      context: . # 以Dockerfile文件配置 build
    ports:
      - 7006:7006 # 宿主机端口:容器端口,用于nginx转发
    command: ["npm", "start"] # 启动服务

配置mongodb容器,修改mongodb-compose.yml:

version: ''3''
services:
  mongodb:
    image: mongo:latest # 使用mongo:latest镜像
    ports:
      - 27017:27017 # 宿主机端口:容器端口
    volumes:
      - "/Users/liaoxinyu/db/mongodb/data:/data/db/" # 挂载数据库目录至本地,若不挂载,容器关闭后数据丢失。

修改nginx.conf:

upstream api {
    server 10.10.1.31:7006;
} # 后端服务容器 端口:ip

server {
    listen         8080; # 监听8080端口,docker-compose里做的映射
    server_name    localhost; # 本地配置就直接用localhost了,线上的话改成域名或公网ip

    location /api {
        # /api前缀的请求,全部转发至Egg.js服务
        proxy_pass http://api;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        # 可写多个location,转发至不同的服务或静态资源路由
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri /index.html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

启动项目:
1.先启动数据库:docker-compose -f mongodb-compose.yml up
2.数据库完全启动后,启动Egg.js服务与nginx:docker-compose up

验证:
1.使用 NoSqlBooster for MongoDB 连接数据库,配置很简单,配置ip:port,查看数据库内容
2.使用 postman 请求 http://localhost:8080/api/admin/user,这里发的请求是直接发到nginx代理的8080上。 由nginx转发至业务服务端口7006。

线上服务器就直接请求域名了,且不对外公开业务服务器的公网ip:端口。

结束

附:使用nginx - docker镜像部署服务器,配置https,附带java后端部署例子

Docker+Jenkins+Nodejs+Git+Webhook自动部署

Docker+Jenkins+Nodejs+Git+Webhook自动部署

1.准备环境

  • 一台有网络的Linux 服务器
  • Docker rpm安装包,依赖包 libcgroup
  • jdk1.7 OR 1.8环境下载
  • Jenkins WAR包下载
  • NodeJs 源码包下载

依赖下载地址:

  • https://pkgs.org/download/
  • https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/

2.安装Docker

rpm -ivh libcgroup-0.40.rc1-23.el6.x86_64.rpm 
rpm -ivh docker-engine-1.7.1-1.el6.x86_64.rpm 

3.编写Dockerfile

FROM ubuntu 

ADD jdk-8u171-linux-x64.tar.gz /usr/local/

RUN mv /usr/local/jdk1.8.0_171 /usr/local/java

ADD apache-tomcat-8.5.30.tar.gz /usr/local/

RUN mv /usr/local/apache-tomcat-8.5.30 /usr/local/tomcat

COPY jenkins.war /usr/local/tomcat/webapps/

ADD node-v8.11.1.tar.gz /root/

RUN apt-get update

RUN apt-get install -y python git ssh gcc g++ make

RUN /root/node-v8.11.1/configure && make -C /root/node-v8.11.1/ && make install -C /root/node-v8.11.1/ && rm -rf /root/node-v8.11.1/

ENV JAVA_HOME /usr/local/java

ENV JRE_HOME $JAVA_HOME/jre

ENV CLASSPATH .:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ENV PATH $JAVA_HOME/bin:$PATH

EXPOSE 8080 3000 22

ENTRYPOINT ["java","-jar","/usr/local/tomcat/webapps/jenkins.war"]

(这里就不对Dockerfile和语法做解释了,可以自行查阅资料)

本来是要用tomcat启动的,但容器启动后tomcat没启动,试了很多种方法都不行,最后只能改成java -jar

将Dockerfile与所有的软件包放在一起然后执行命令

docker build -t jenkins ./
-t jenkins为镜像的TAG,''./''为Dockerfile与软件包的路径,最后看到Successfully说明成功

(Docker基础镜像中有jenkins的镜像,直接执行docker pull jenkins就可以了,我为什么要用WAR包安装,是因为jenkins镜像的登陆用户为jenkins,登陆到容器后没有权限很多事情都做不了)

4.运行镜像

这时候运行docker images应该就会有一个叫jenkins的镜像

执行命令

docker run -d -p 8080:8080 -p 50000:50000 -p 3000:3000 -p 50001:22 -v /var/jenkins_home:/root/.jenkins/ --name jenkins_node jenkins

(3000端口是自己设置的nodejs程序端口)

run 运行docker镜像,-d 以后台守护进程运行 ,-p 将容器端口开放(服务器端口:容器端口) , -v 挂载分区(服务器分区:容器分区) --name 指定容器名称,最后的jenkins为镜像包名

如果出现这种问题,重启docker服务,在尝试启动容器,如问题未能解决就将防火墙端口开放,然后重启docker服务
图片描述

以Centos7为例

firewall-cmd --zone=public --add-port=50001/tcp --permanent
firewall-cmd --reload
systemctl restart docker
docker start jenkins_node

防火墙对docker的影响很大,在防火墙开启的情况下会遇到很多奇怪的错误,而且这些错误基本上查不到决绝办法,能查到的只有与你遇到的问题无关的,但这些问题基本上都是与连接有关的,比如连不上主机或找不到主机,解析不了网址之类的,如果在防火墙开启的情况下遇到这类问题就先检查防火墙,然后重启docker服务和容器

5.jenkins配置

jenkins安装

  1. 打开浏览器并输入:"服务器地址:8080"访问,出现如下页面
    图片描述
  2. 将服务器"/var/jenkins_home/secrets/initialAdminPassword"文件的内容复制到输入框,点击继续

    图片描述

  3. 点击左边的推荐安装,等待安装完成

    图片描述

  4. 设置Admin user

    图片描述

jenkins插件安装配置

  1. 点击 系统管理 --> 插件管理
  2. 选择 “可选插件”
  3. 右上角搜索SSH,--> 选择Publish Over SSH -->点击 直接安装
  4. 等待安装完成
  5. 安装成功后,点击 系统管理 --> 插件管理
  6. 拉到最下面找到 "Publish over SSH" , 设置服务器的SSH信息

    1. 到服务器执行docker exec -it jenkins_node bash登陆到容器
    2. 重置用户密码passwd
    3. 安装一个编辑器apt-get install -y vim
    4. 安装完之后vim /etc/ssh/sshd_config编辑ssh配置文件
    5. 找到PermitRootLogin prohibit-password改为PermitRootLogin yes保存文件
    6. 重新启动sshservice ssh restart
    7. 设置ssh开机自启动update-rc.d ssh defaults
    8. 生成ssh秘钥ssh-keygen -t rsa什么都不要输直接回车直到完成就好
    9. 切换到ssh秘钥目录cd ~/.ssh/会有两个文件''id_rsa''(秘钥)和''id_rs a.pub''(公钥)文件
    10. 将公钥复制cp id_rsa.pub authorized_keys
    11. 复制id_rsa(秘钥)文件中的内容
    12. 到jenkins ‘Publish over SSH’ 设置找到SSH Servers 点击 "增加 --> 高级"

      • Name : ssh server名称随意设置
      • Hostname : 服务器ip地址
      • Username : 容器用户名
      • 选中 Use password authentication, or use a different key
      • Passphrase / Password : 容器用户密码
      • Key : 将刚刚复制的id_rsa(秘钥)内容粘贴到这里
      • Port : 设置成镜像运行命令中将22端口映射为50001的端口
      • 点击Test Configuration出现Success成功
      • 如果出现下图请检查authorized_keys文件名称或内容是否正确,和复制的私钥内容是否正确,docker容器ssh是否运行。
      • 图片描述
      • 如果出现下图就到宿主机开放50001端口
      • ![图片描述
      • 保存

    图片描述

6.jenkins项目配置

  1. 首页,点击左上角”新建”
  2. General: 只填 项目名称即可
  3. 源码管理: 填写Git信息
    Repository URL : 填写项目git地址
    Credentials : 如果有用户名密码,点击add添加用户信息,输入用户名密码

    图片描述

    如果出现图中CAfile错误就到容器中执行git config --global http.sslverify false关闭https证书检测,然后回到页面将Repository URL中的地址剪切并重新粘贴

  4. 构建环境选中‘Send files or execute commands over SSH before the build starts’
    Remote directory : 执行此命令的文件夹位置,一般为"./",意思是在项目目录
    Exec command :所执行的构建命令,例如"npm start"
    图片描述
  5. 保存,返回首页,并构建刚刚创建的项目

7.自动部署

  1. jenkins --> 首页 --> 用户
    图片描述
  2. 设置 --> 点击 "show API Token"
    图片描述
  3. 复制API Token内容
    图片描述
  4. 返回首页 --> (自己的项目) --> 配置 --> 构建触发器 --> 选择 "触发远程构建" -->粘贴"API Token"内容到"身份验证令牌"
    图片描述
  5. 登陆git平台,找到你的项目,选择管理,选择webhook
    图片描述

    • URL 中 node 请替换为你在jenkins上创建的项目名称
    • token为复制的 API Token内容
  6. 此时你git push,会发现jenkins并没有自动构建,是因为jenkins的安全策略导致的,还需要如下设置。
    jenkins首页,选择 系统管理-->Configure Global Security(系统设置下面那个) 进行如下设置
    图片描述

docker-node-pm2-sails.js启动传递环境参数

docker-node-pm2-sails.js启动传递环境参数

docker-node-pm2-sails.js启动传递环境参数

[TOC]

流程:docker run->DockerFile ->docker_start.sh

mark

docker run

 docker run -e NODE_ENV=test -d -p 1337:1337 noncar:0.1

DockerFile

#FROM 设置镜像
FROM node:8-alpine
# 设置镜像作者
MAINTAINER xumy 
# 创建目录
RUN mkdir -p  /app/csp
# 安装npm模块
ADD package.json /app/csp/package.json
# 安装npm模块
WORKDIR /app/csp
# 使用淘宝的npm镜像
RUN npm install --production -d --registry=http://registry.npm.taobao.org
# 再装pm2
RUN npm install -g pm2 --registry=https://registry.npm.taobao.org
# 添加源代码
ADD . /app/csp/
# 设置环境变量
ENV NODE_ENV test
# 用环境变量启动
CMD /bin/sh ./docker_start.sh $NODE_ENV

docker_start.sh

#!/bin/sh
echo $NODE_ENV
pm2-docker start pm2.json --env $NODE_ENV

sails.js 代码

config.connections.js

  mongo: {
    adapter: ''sails-mongo'',
    host: ''10.11.1.161'', // defaults to `localhost` if omitted
    port: 27017, // defaults to 27017 if omitted
    database: ''cs'' // or omit if not relevant
  },
  devmongo: {
    adapter: ''sails-mongo'',
    host: ''10.2.108.59'', // defaults to `localhost` if omitted
    port: 27017, // defaults to 27017 if omitted
    database: ''cs'' // or omit if not relevant
  },
  testmongo: {
    adapter: ''sails-mongo'',
    host: ''10.1.110.74'', // defaults to `localhost` if omitted
    port: 27017, // defaults to 27017 if omitted
    database: ''cs'' // or omit if not relevant
  }

config.models.js

  //默认本机
  connection: ''mongo

config.env

包括dev.js/prod.js/test.js

config.env.test.js

  models: {
    connection: ''testmongo''
  },

启动验证

# 启动
docker run -e NODE_ENV=test -d -p 1337:1337 noncar:0.1
# 日志
docker logs -f cf

Docker: 编写 dockerfile 启动 node.js 应用

Docker: 编写 dockerfile 启动 node.js 应用

编写 Dockerfile

express 自动创建的目录为例,目录结构如下:

├── /bin
│   └── www
├── /node_modules
├── /public
├── /routes
├── /views
├── package-lock.json
├── package.json
├── ecosystem.config.js
├── app.js
└── Dockerfile

在项目目录下新建 Dockerfile 文件

FROM node:10.15
MAINTAINER sunhengzhe@foxmail.com
COPY . /app/
WORKDIR /app
RUN npm install pm2 -g
EXPOSE 8003
CMD ["pm2-runtime", "ecosystem.config.js"]
  • FROM 指定基础镜像为 node 的 10.15 版本(node 官方版本可 在此查看)
  • MAINTAINER 说明镜像的维护者
  • COPY 命令将宿主机的文件拷贝到镜像中,格式为 COPY [--chown=<user>:<group>] <源路径>... <目标路径>,这里将项目目录下的所有文件都拷贝到镜像中的 /app 目录下。如果目标路径不存在,docker 将自动创建。
  • WORKDIR 用来指定工作目录,即是 CMD 执行所在的目录。
  • RUN 命令用来执行 shell 命令,这里用来安装 pm2
  • EXPOSE 命令用来 声明 运行时容器提供服务端口,但要注意运行时并不会开启这个端口的服务。这个命令主要是帮助使用者理解这个镜像服务的守护端口,以方便配置映射;另外在使用随机端口映射时,会自动随机映射 EXPOSE 的端口
  • CMD 是默认的容器主进程的启动命令

构建镜像

在项目目录下执行

docker build -t express-app:v1 .

如果构建成功,查看镜像列表

docker images

应该会输出镜像 express-app:v1

clipboard.png

运行容器

docker run -d -p 8003:3000 --name="express-app" express-app:v1

docker rundocker createdocker start 两个命令的简写。

  • -d--detach,代表让容器后台运行。
  • -p 指定宿主机和容器的端口映射,左边为宿主机的端口,右边为容器的端口,也就是说访问宿主机的 8003 端口,会映射到容器内的 3000 端口。
  • --name 设置容器别名,如果不指定,docker 会随机生成一个名字,比如 tender_swirles 之类的。

执行

docker ps

正常展示如下

clipboard.png

添加 -a 参数可以查看所有已启动容器。

进入容器

如果要进入容器进行操作,执行下面命令

docker exec -it express-app bash

clipboard.png

-i-t 一般结合使用,-i 启动交互模式,-t 指定需要分配终端,可以自行尝试不传其中一个的效果。

exec 类似的还有 attach 命令,命令为 docker attach express-app,但从这个 stdin 中 exit,会导致容器的停止,所以推荐使用 exec 命令。

关闭操作

停止容器

docker stop express-app

删除容器

docker rm express-app

如果删除时容器还在运行,需要加上 -f 参数

删除镜像

docker rmi express-app:v1

今天关于使用 PM2 在 Docker 上部署 Node.js Web 应用pm2-docker的介绍到此结束,谢谢您的阅读,有关Docker - 入门(二),docker&nodeJs制作镜像与本地部署、Docker+Jenkins+Nodejs+Git+Webhook自动部署、docker-node-pm2-sails.js启动传递环境参数、Docker: 编写 dockerfile 启动 node.js 应用等更多相关知识的信息可以在本站进行查询。

本文标签: