最近自己做了个小项目,试着使用docker来进行发布,而其中用到了node做跨越代理,就是为了解决这个问题至少多花费了我一天时间,不说了直接进入主题吧

一、系统环境配置

二、安装node

直接运行 docker pull node


	[root@dex ~]# docker pull node
	Using default tag: latest
	latest: Pulling from library/node
	844c33c7e6ea: Pull complete 
	ada5d61ae65d: Pull complete 
	f8427fdf4292: Pull complete 
	f025bafc4ab8: Pull complete 
	7a9577c07934: Pull complete 
	9b4289f800f5: Pull complete 
	c74d80ccdeab: Pull complete 
	b418965736e5: Pull complete 
	fb4cff8b8d55: Pull complete 
	Digest: sha256:a4ee833346b09f24095868f6a9d2c7781b6ac319821f912df05f71c6f5a4259c
	Status: Downloaded newer image for node:latest
	docker.io/library/node:latest
	[root@dex ~]# docker images
	REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
	node                latest              2af77b226ea7        9 days ago          934MB
	[root@dex ~]# 
	

三、 Configure node entry

在项目根目录添加prod.server.js文件

  • 目录机构如下
    添加server.js进行后端接口代理
    prod.server.js 内容如下

	var express = require('express');
	var config = require('./config/index');
	
	var port = process.env.PORT || config.build.port;
	
	var app = express();
	
	var router = express.Router();
	const axios = require('axios')
	
	axios.interceptors.request.use((config) => {
	  return config;
	}, (error) => {
	  return Promise.reject(error);
	});
	
	axios.interceptors.response.use((response) => {
	  return response;
	}, (error) => {
	  return Promise.reject(error);
	});
	
	router.get('/', function (req, res, next) {
	  req.url = '/index.html';
	  next();
	});
	
	app.use(router);
	
	var apiRoutes = express.Router();
	app.use('/api', apiRoutes);
	
	app.get('/api/getDiscList', (req, res) => {
	  var url = 'https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg'
	  axios.get(url, {
	    headers: {
	      referer: 'https://c.y.qq.com/',
	      host: 'c.y.qq.com'
	    },
	    params: req.query
	  }).then((response) => {
	    res.json(response.data)
	  }).catch((e) => {
	    console.log('错误日志')
	    console.log(e)
	  })
	}),
	  app.get('/api/getMusic', (req, res) => {
	    var url = 'https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg'
	    axios.get(url, {
	      headers: {
	        referer: 'https://c.y.qq.com/',
	        host: 'c.y.qq.com'
	      },
	      params: req.query
	    }).then((response) => {
	      res.json(response.data)
	    }).catch((e) => {
	      console.log('错误日志')
	      console.log(e)
	    })
	  }),
	  app.get('/api/getplaysongvkey', function (req, res) { // 获取vkey
	    var url = 'https://u.y.qq.com/cgi-bin/musicu.fcg'
	    axios.get(url, {
	      headers: {
	        origin: 'https://y.qq.com',
	        referer: 'https://y.qq.com/portal/player.html'
	      },
	      params: req.query
	    }).then((response) => {
	      res.json(response.data)
	    }).catch((e)=>{
	      console.log(e)
	    })
	  }),
	  app.get('/api/lyric', (req, res) => {
	    var url = 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg'
	    axios.get(url, {
	      headers: {
	        referer: 'https://c.y.qq.com/',
	        host: 'c.y.qq.com'
	      },
	      params: req.query
	    }).then((response) => {
	      res.json(response.data)
	    }).catch((e) => {
	      console.log('错误日志')
	      console.log(e)
	    })
	  }),
	  app.get('/api/getSongList', (req, res) => {
	    var url = 'https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg'
	    axios.get(url, {
	      headers: {
	        referer: 'https://c.y.qq.com/',
	        host: 'c.y.qq.com'
	      },
	      params: req.query
	    }).then((response) => {
	      var ret = response.data
	      res.json(ret)
	    }).catch((e) => {
	      console.log('错误日志')
	      console.log(e)
	    })
	  }),
	  app.get('/api/suggestSearch', (req, res) => {
	    var url = 'https://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp'
	    axios.get(url, {
	      headers: {
	        referer: 'https://c.y.qq.com/',
	        host: 'c.y.qq.com'
	      },
	      params: req.query
	    }).then((response) => {
	      var ret = response.data
	      res.json(ret)
	    }).catch((e) => {
	      console.log('错误日志')
	      console.log(e)
	    })
	  })
	
	app.use(express.static('./dist'));
	
	module.exports = app.listen(port, function (err) {
	  if (err) {
	    console.log(err);
	    return
	  }
	  console.log('Listening at http://localhost:' + port + '\n')
	});

与此同时修改package.json 中 node的启动脚本,如下


  "private": true,
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "node prod.server.js",
    "lint": "eslint --ext .js,.vue src",
    "build": "node build/build.js"
  },
  

"start": "npm run dev" 改为 "start": "node prod.server.js"
因为直接使用 npm run dev 将无法完成node的代理
会出现调用api接口报错

四、打包项目

执行npm run build编译项目,再将dist目录上传到centos 系统


# 执行 ll 查看已上传的文件

	[root@VM_0_5_centos vuedev]# ll
	total 20
	drwxr-xr-x 2 root root 4096 Jul 28 09:01 config
	drwxr-xr-x 3 root root 4096 Jul 28 09:01 dist
	-rw-r--r-- 1 root root  404 Jul 28 09:02 Dockerfile
	-rw-r--r-- 1 root root 2612 Jul 28 09:01 package.json
	-rw-r--r-- 1 root root 3253 Jul 28 09:01 prod.server.js

同时在该目录创建一个Dockerfile用于镜像制作

  • 文件内容如下

	FROM docker.io/node:8.0-alpine
	
	# Create app directory
	WORKDIR /usr/src/vueappdev
	
	# Install app dependencies
	# A wildcard is used to ensure both package.json AND package-lock.json are copied
	# where available (npm@5+)
	COPY package*.json ./
	
	RUN npm install
	
	# If you are building your code for production
	# RUN npm ci --only=production
	
	# Bundle app source
	COPY . .
	
	EXPOSE 9009
	CMD [ "npm", "start" ]

Dockerfile文件就很多中配置,还有待研究…

五、 制作镜像


#cd 到项目目录下

	[root@VM_0_5_centos ~]# cd /opt/web_proj/vuedev
	
	# 执行镜像创建 (注意最后的 . 标识使用当前目录下的Dockerfile)
	[root@VM_0_5_centos vuedev]# docker build -t vuedev:v1 .
	
	# 执行完上面步骤,现在可以看见你创建的images了
	[root@VM_0_5_centos vuedev]# docker images
	REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
	vuedev              v1                  ac171f1d6b87        21 hours ago        239 MB

六、 创建容器


	# 创建并运行容器
	[root@VM_0_5_centos vuedev]# docker run -p 8191:8009 --name vuedev2 -d vuedev:v1
	
	# 查看容器运行日志
	[root@VM_0_5_centos vuedev]# docker logs -f -t --tail 200 vuedev2
	2019-07-26T02:59:30.093574000Z npm info it worked if it ends with ok
	2019-07-26T02:59:30.094162000Z npm info using npm@5.0.0
	2019-07-26T02:59:30.094450000Z npm info using node@v8.0.0
	2019-07-26T02:59:30.137340000Z npm info lifecycle vue-music@1.0.0~prestart: vue-music@1.0.0
	2019-07-26T02:59:30.143459000Z npm info lifecycle vue-music@1.0.0~start: vue-music@1.0.0
	2019-07-26T02:59:30.147283000Z > vue-music@1.0.0 start /usr/src/vueappdev
	2019-07-26T02:59:30.147534000Z > node prod.server.js
	2019-07-26T02:59:30.404213000Z Listening at http://localhost:8009
	
	# 查看容器运行情况 【运行后见 STATUS 处于 Up 标识正在运行】
	[root@VM_0_5_centos vuedev]# docker ps 
	CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
	6141d4fda6c9        vuedev:v1           "npm start"              21 hours ago        Up 21 hours         9009/tcp, 0.0.0.0:8191->8009/tcp    vuedev2
	
	# 使用wget进行端口检测【运行后见 response... 200 ok 信息标识端口测试成功】
	[root@VM_0_5_centos vuedev]# wget localhost:8191
	--2019-07-27 08:44:10--  http://localhost:8191/
	Resolving localhost (localhost)... 127.0.0.1, ::1
	Connecting to localhost (localhost)|127.0.0.1|:8191... connected.
	HTTP request sent, awaiting response... 200 OK
	Length: 514 [text/html]
	Saving to: ‘index.html.4’
	
	100%[=================================================================================================================================================>] 514         --.-K/s   in 0s      
	
	2019-07-27 08:44:10 (61.4 MB/s) - ‘index.html.4’ saved [514/514]
	
	# 假如我们检测了一个不存在的端口【结果会是如下】
	[root@VM_0_5_centos vuedev]# wget localhost:8190
	--2019-07-27 08:45:14--  http://localhost:8190/
	Resolving localhost (localhost)... 127.0.0.1, ::1
	Connecting to localhost (localhost)|127.0.0.1|:8190... failed: Connection refused.
	Connecting to localhost (localhost)|::1|:8190... failed: No route to host.

【注意】在执行docker run -p 8191:8009 --name vuedev2 -d vuedev:v1
运行容器的时候,端口的指定要小心,不然会被坑;
其中的8191指的是容器向外暴露的端口,而8009这个就要注意了(我当时就没弄明白)
这个并不是Dockerfile中的 EXPOSE 9009
而是 vue中config>index.js 文件里
build:{ port:8009, }
中的 8009

如果你不需要node进行api代理(就是没有修改package.json的script) 如

  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0",
    "start": "npm run dev",
    "build": "node build/build.js"
  },

那么端口就应该是
dev: { port: 18080, }
中的 18080


七、配置nginx反向代理

1、配置项目代理地址

     location /vueapp/ {
  		 proxy_pass http://127.0.0.1:8191/;
     }
     
2、数据接口代理

这里使用的QQ音乐数据,所以需要使用nginx 进行数据服务代理

完整配置如下:



    location /vueapp/ {
   		proxy_pass http://127.0.0.1:8191/;
     }
    
      location ^~ /api/getDiscList {
       proxy_pass https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg;
      }
    location ^~ /api/getMusic {
       proxy_pass https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg;
      }
    location ^~ /api/getplaysongvkey {
       proxy_pass https://u.y.qq.com/cgi-bin/musicu.fcg;
      }
     location ^~ /api/lyric {
       proxy_pass https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg;
      }
     location ^~ /api/getSongList {
       proxy_pass https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg;
      }
     location ^~ /api/suggestSearch {
       proxy_pass https://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp;
      }
     location ^~ /api/musichall {
       proxy_pass https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg;
      }
     location ^~ /api/splcloud {
       proxy_pass https://c.y.qq.com/splcloud/fcgi-bin/gethotkey.fcg;
      }
     location ^~ /api/topList {
       proxy_pass https://c.y.qq.com/v8/fcg-bin/fcg_myqq_toplist.fcg;
      }
      location ^~ /api/getMusicListTopId {
       proxy_pass https://c.y.qq.com/v8/fcg-bin/fcg_v8_toplist_cp.fcg;
      }

3、重新nginx配置

 # 检测配置
[root@dex ~]#  /usr/local/nginx/sbin/nginx -t 

 # 重新加载配置
[root@dex ~]#  /usr/local/nginx/sbin/nginx -s reload

到此项目部署圆满完成 ;在手机浏览器中输入 https://www.benpaodehenji.com/vueapp/即可访问页面,如果使用PC请F12转到手机模式预览,因为这是一个移动版app
该项目源码访问地址:https://github.com/dengxiaoning/vue-music


Logo

前往低代码交流专区

更多推荐