美文网首页
部署_nginx_pm2_docker

部署_nginx_pm2_docker

作者: LM林慕 | 来源:发表于2019-11-18 19:36 被阅读0次

    此文项目代码:https://github.com/bei-yang/I-want-to-be-an-architect
    码字不易,辛苦点个star,感谢!

    引言


    此篇文章主要涉及以下内容:

    1. Nginx
      • 静态资源location
      • 动态数据请求proxy
      • 负载均衡
    2. cluster原理
    3. pm2部署NodeJS服务

    参考文档


    使用pm2+nginx部署koa2(https)https://www.zhaofinger.com/detail/5

    如何构建一个高可用的node环境(cluster模块)


    主要解决问题

    文件上传服务器


    • scp(最原始)
    scp docker-compose.yml root@47.98.252.43:/root/source/ #⽂件
    scp -r mini-01 root@47.98.252.43:/root/source/ #⽂件夹
    
    • git(实际工作中)
    • deploy插件(debug)

    PM2的应用


    • 内建负载均衡(使用Node cluster集群模块、子进程,可以参考朴灵的《深入浅出node.js》一书第九章)
    • 线程守护,keep alive
    • 0秒停机重载,维护升级的时候不需要停机
    • 现在Linux(stable)&MacOSx(stable)&Windows(stable)多平台支持
    • 停止不稳定的进程(避免无限循环)
    • 控制台检测https://id.keymetrics.io/api/oauth/login#/register
    • 提供HTTP API
      配置
    npm install -g pm2
    pm2 start app.js --watch -i 2
    // watch 监听⽂件变化
    // -i 启动多少个实例
    pm2 stop all
    pm2 list
    pm2 start app.js -i max # 根据机器CPU核数,开启对应数⽬的进程
    

    配置process.yml

    apps:
     - script : app.js
     instances: 2
     watch : true
     env :
     NODE_ENV: production
    
    • Keymetrics在线监控

    https://id.keymetrics.io

    pm2 link 8hxvp4bfrftvwxn uis7ndy58fvuf7l TARO-SAMPLE
    

    pm2设置为开机启动

    pm2 startup
    

    Nginx反向代理+前端打包Dist


    安装

    yum install nginx
    -----
    apt update
    apt install nginx
    

    添加静态路由

    # /etc/nginx/sites-enable/taro
    server {
     listen 80;
     server_name taro.josephxia.com;
     location / {
     root /root/source/taro-node/dist;
     index index.html index.htm;
     }
    }
    
    # 验证Nginx配置
    nginx -t
    # 重新启动Nginx
    service restart nginx
    nginx -s reload
    
    # /etc/nginx/sites-enable
    # taro
    server {
     listen 80;
     server_name taro.josephxia.com;
     location / {
     root /root/source/taro-node/dist;
     index index.html index.htm;
     }
     location ~ \.(gif|jpg|png)$ {
     root /root/source/taro-node/server/static;
     }
     location /api {
     proxy_pass http://127.0.0.1:3000;
     proxy_redirect off;
     proxy_set_header Host $host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For
    $proxy_add_x_forwarded_for;
     }
    }
    
    # 查看配置⽂件位置
    nginx -t
    # nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    # nginx: configuration file /etc/nginx/nginx.conf test is successful
    #重启
    service nginx restart
    

    Docker概念


    • 操作系统层面的虚拟化技术
    • 隔离的进程独立于宿主和其它的隔离的进程-容器
    • GO语言开发

    特点

    • 高效的利用系统资源
    • 快速的启动时间
    • 一致的运行环境
    • 持续交付和部署
    • 更轻松的迁移

    对比传统虚拟机总结

    三个核心改名

    • 镜像
    • 容器
    • 仓库

    Docker基本使用


    构建一个Nginx服务器

    1. 拉取官方镜像
    # 拉取官⽅镜像
    docker pull nginx
    # 查看
    docker images nginx
    # 启动镜像
    mkdir www
    echo 'hello docker!!' >> www/index.html
    # 启动
    # www⽬录⾥⾯放⼀个index.html
    docker run -p 80:80 -v $PWD/www:/usr/share/nginx/html -d nginx
    # 查看进程
    docker ps
    docker ps -a // 查看全部
    # 伪终端 ff6容器的uuid
    # -t 选项让Docker分配⼀个伪终端(pseudo-tty)并绑定到容器的标准输⼊上,
    # -i 则让容器的标准输⼊保持打开
    docker exec -it ff6 /bin/bash
    # 停⽌
    docker stop ff6
    # 删除镜像
    docker rm ff6
    

    Dockerfile定制镜像


    #Dockerfile
    FROM nginx:latest
    RUN echo '<h1>Hello, Kaikeba!</h1>' > /usr/share/nginx/html/index.html
    
    # 定制镜像
    docker build -t mynginx .
    # 运⾏
    # -d 守护态运⾏
    docker run -p 80:80 -d mynginx
    

    定制一个程序NodeJS镜像

    npm init -y
    npm i koa -s
    
    // package.json
    {
     "name": "myappp",
     "version": "1.0.0",
     "main": "app.js",
     "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
     },
     "keywords": [],
     "author": "",
     "license": "ISC",
     "description": "myappp",
     "dependencies": {
     "koa": "^2.7.0"
     }
    }
    
    // app.js
    const Koa = require('koa')
    const app = new Koa()
    app.use(ctx => {
     Math.random() > 0.8 ? abc() : ''
     ctx.body = 'Hello Docker'
    })
    app.listen(3000, () => {
     console.log('app started at http://localhost:3000/')
    })
    
    #Dockerfile
    #制定node镜像的版本
    FROM node:10-alpine
    #移动当前⽬录下⾯的⽂件到app⽬录下
    ADD . /app/
    #进⼊到app⽬录下⾯,类似cd
    WORKDIR /app
    #安装依赖
    RUN npm install
    #对外暴露的端⼝
    EXPOSE 3000
    #程序启动脚本
    CMD ["node", "app.js"]
    
    # 定制镜像
    docker build -t mynode .
    # 运⾏
    docker run -p 3000:3000 -d mynode
    

    Pm2-利用多核资源

    # .dockerignore
    node_modules
    
    // process.yml
    {
     "apps": [{
     "name": "app-name",
     "script": "app.js",
     "instances": 2,
     "env": {
     "production": true
     }
     }]
    }
    
    # Dockerfile
    FROM keymetrics/pm2:latest-alpine
    WORKDIR /usr/src/app
    ADD . /usr/src/app
    RUN npm config set registry https://registry.npm.taobao.org/ && \
     npm i
    EXPOSE 3000
    #pm2在docker中使⽤命令为pm2-docker
    CMD ["pm2-runtime", "start", "process.yml"]
    
    # 定制镜像
    docker build -t mypm2 .
    # 运⾏
    docker run -p 3000:3000 -d mypm2
    

    Docker-Compose


    #docker-compose.yml
    app-pm2:
     container_name: app-pm2
     #构建容器
     build: .
     # volumes:
     # - .:/usr/src/app
     ports:
     - "3000:3000"
    
    // 强制重新构建并启
    # --force-recreate 强制重建容器
    # --build 强制编译
    docker-compose up -d --force-recreate --build
    
    #docker-compose.yml
    version: '3.1'
    services:
     nginx:
     image: nginx:kaikeba
     ports:
     - 80:80
    
    # 运⾏
    docker-compose up
    # 后台运⾏
    docker-compose up -d
    

    部署Mongo+MongoExpress

    #docker-compose.yml
    version: '3.1'
    services:
     mongo:
     image: mongo
     restart: always
     ports:
     - 27017:27017
     mongo-express:
     image: mongo-express
     restart: always
     ports:
     - 8081:8081
    

    代码中添加Mongoose调用

    // mongoose.js
    const mongoose = require("mongoose");
    // 1.连接
    mongoose.connect("mongodb://mongo:27017/test", { useNewUrlParser: true });
    const conn = mongoose.connection;
    conn.on("error", () => console.error("连接数据库失败"));
    
    // app.js
    const mongoose = require('mongoose');
    mongoose.connect('mongodb://mongo:27017/test', {useNewUrlParser: true});
    const Cat = mongoose.model('Cat', { name: String });
    Cat.deleteMany({})
    const kitty = new Cat({ name: 'Zildjian' });
    kitty.save().then(() => console.log('meow'));
    app.use(async ctx => {
    
     ctx.body = await Cat.find()
    
    })
    

    Github WebHook实现CI持续集成


    启动NodeJS监听

    var http = require('http')
    var createHandler = require('github-webhook-handler')
    var handler = createHandler({
      path: '/webhooks',
      secret: 'myHashSecret'
    })
    // 上⾯的 secret 保持和 GitHub 后台设置的⼀致
    function run_cmd(cmd, args, callback) {
      var spawn = require('child_process').spawn;
      var child = spawn(cmd, args);
      var resp = "";
      child.stdout.on('data', function (buffer) {
        resp += buffer.toString();
      });
      child.stdout.on('end', function () {
        callback(resp)
      });
    }
    http.createServer(function (req, res) {
      handler(req, res, function (err) {
        res.statusCode = 404
        res.end('no such location')
      })
    }).listen(3000)
    handler.on('error', function (err) {
      console.error('Error:', err.message)
    })
    handler.on('*', function (event) {
    console.log('Received *', event.payload.action);
    // run_cmd('sh', ['./deploy-dev.sh'], function(text){
    console.log(text)
    });
    })
    handler.on('push', function (event) {
    console.log('Received a push event for %s to %s',
      event.payload.repository.name,
      event.payload.ref);
    // 分⽀判断
    if (event.payload.ref === 'refs/heads/master') {
      console.log('deploy master..')
    }
    // run_cmd('sh', ['./deploy-dev.sh'], function(text){
    console.log(text)
    });
    })
    handler.on('issues', function (event) {
      console.log('Received an issue event for % action=%s: #%d %s',
        event.payload.repository.name,
        event.payload.action,
        event.payload.issue.number,
        event.payload.issue.title)
    })
    

    你的赞是我前进的动力

    求赞,求评论,求转发...

    相关文章

      网友评论

          本文标题:部署_nginx_pm2_docker

          本文链接:https://www.haomeiwen.com/subject/wakuictx.html