文章标签 ‘node.js’
2016六月13

Docker:部署Node.js项目

 

Dockerfile:

FROM node:6.2
# Author
MAINTAINER wizzer "wizzer@qq.com"
ENV PORT 1337
RUN apt-get update && apt-get install -y \
		imagemagick \
	--no-install-recommends && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /node/nodeshop
WORKDIR /node/nodeshop

RUN npm config set registry https://registry.npm.taobao.org
RUN npm i node-gyp -g
RUN npm i pm2 -g
ADD api /node/nodeshop/api
ADD assets /node/nodeshop/assets
ADD config /node/nodeshop/config
ADD tasks /node/nodeshop/tasks
ADD views /node/nodeshop/views
ADD app.js /node/nodeshop
ADD Gruntfile.js /node/nodeshop
ADD package.json /node/nodeshop
RUN npm i
EXPOSE ${PORT}
ENV LANG C.UTF-8
ENV TZ "Asia/Shanghai"
VOLUME ["/node/nodeshop/cert", "/node/nodeshop/upload", "/node/nodeshop/backup"]
CMD [ "pm2", "start", "--no-daemon", "app.js" ]

docker-compose.yml:

redis:
  image: redis
db:
  image: mariadb:5.5
  environment:
    "MYSQL_ROOT_PASSWORD": "xxxxxx"
    "MYSQL_DATABASE": "db123"
  command: "mysqld --character-set-server=utf8"
  ports:
    - "127.0.0.1:3306:3306"
  volumes:
    - "/node/nodeshop/db:/var/lib/mysql"
web:
  image: wizzer/nodeshop
  links:
    - redis
    - db
  environment:
    "MYSQL_HOST": "db"
    "MYSQL_USER": "root"
    "MYSQL_PASSWORD": "xxxxxx"
    "MYSQL_DATABASE": "db123"
    "MYSQL_LIMIT": 150
    "REDIS_HOST": "redis"
    "REDIS_PASS": ""
    "LOG_LEVEL": "verbose"
    "PORT": 1337
    "NODE_ENV": "development"
  command: "pm2 start /node/nodeshop/app.js --no-daemon"
  ports:
    - "1337:1337"
  volumes:
    - "/node/nodeshop/cert:/node/nodeshop/cert"
    - "/node/nodeshop/upload:/node/nodeshop/upload"
    - "/node/nodeshop/backup:/node/nodeshop/backup"

说明:
1、把数据库端口3306映射到127.0.0.1:3306 是为了还原数据库,web映射端口不绑定IP这样外网可以访问,通过nginx代理出去.
2、volumes将数据文件、数据库文件使用容器外文件夹,这样重启后不丢失数据.

1、打包最新image
docker build -t wizzer/nodeshop .

. 为当前文件夹,通过Dockerfile打包
wizzer/nodeshop:v1.0 用户名/项目:版本号

docker images 列出所有镜像
docker rmi ID 删除某个镜像
docker ps -a 列出所有容器
docker rm ID 删除某个容器
2、Centos安装Docker-engine 1.7.1版本(windows安装docker-toolbox即可)

vi /etc/yum.repos.d/docker.repo

[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/6/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg

yum search docker
yum install docker-engine.x86_64
service docker start 启动docker服务
chkconfig docker on 设置为开启启动

3、Centos安装docker-compose 1.1.0版本(windows安装docker-toolbox即可)

curl -L https://github.com/docker/compose/releases/download/1.7.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

ps:第一行命令复制会少符号,到 https://github.com/docker/compose/releases/ 复制命令。

4、迁移镜像
docker ps -a 列出容器快照
docker export ID > nodeshop.tar 将容器快照导出
cat /node/nodeshop.tar | docker import – wizzer/nodeshop 加载容器快照

5、创建运行目录
分别创建4个文件夹【必须】
/node/nodeshop/cert 将证书文件拷贝进去
/node/nodeshop/upload 附件上传文件夹
/node/nodeshop/backup 数据库备份文件夹
/node/nodeshop/db 数据库文件夹
将Dockfile 、 docker-compose.yml 拷贝到 /node/nodeshop 目录

6、启动项目

cd /node/nodeshop
docker-compose up -d

docker-compose ps 列出正在运行的服务
docker-compose stop 停止服务
docker ps -a 列出所有容器状态
docker rm ID 删除容器

若要修改环境变量,可以修改 /node/nodeshop/docker-compose.yml 文件内容

7、安装mariadb客户端(用于连接数据库)

cd /etc/yum.repos.d/
vi MariaDB.repo

[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/5.5/centos6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

yum install MariaDB-client

MariaDB-server 不需要安装

8、还原数据

mysql -h 127.0.0.1 -u root -p
密码
show databases;
use nodeshop;
source /node/nodeshop/db.sql;
show tables;
exit;

9、重启docker容器

docker-compose stop
docker-compose start

10、进入容器执行命令,比如测试网络情况

docker ps -a
docler exec -it ID /bin/bash
ping 192.168.1.11
exit

如果网络不通,可能需要关闭防火墙,然后重启docker服务:

service docker restart

11、容器开机自启动

vi /etc/rc.d/rc.local
/usr/local/bin/docker-compose -f /node/sunshop/docker-compose.yml up -d

注意:如果是centos7 则需要执行 chmod +x /etc/rc.d/rc.local 添加执行权限.

 


本教程适用于Centos6.x版本,7或有不同。

2016五月24

Node.js:集成apidoc

本文基于Sails.js MVC框架
一、安装

npm i apidoc -save
npm i grunt-apidoc -save

二、配置

package.json

增加配置项

"apidoc": {
  "title": "Sunshop"
},

tasks/config/apidoc.js

/**
 * Created by wizzer on 2016/5/24.
 */
module.exports = function (grunt) {
  grunt.config.set('apidoc', {
    myapp: {
      src: "api/controllers/api",
      dest: "apidoc/",
      options: {
        includeFilters: [ ".*\\.json$" ]
      }
    }
  });
  grunt.loadNpmTasks('grunt-apidoc');
};

tasks/register/compileAssets.js

module.exports = function (grunt) {
	grunt.registerTask('compileAssets', [
		'clean:dev',
		'jst:dev',
		'less:dev',
		'copy:dev',
		'coffee:dev',
    'apidoc:myapp' // <-- apidoc
	]);
};

 

api/controllers/api/oauth.json  一个API文档示例,详细参数见apidoc官网。

/**
 * @api {POST} /api/oauth/token Token
 * @apiName Token
 * @apiGroup Oauth
 * @apiVersion 1.0.0
 * @apiDescription 获取Token
 * @apiPermission anyone
 *
 * @apiParam {string} client_id client_id
 * @apiParam {string} client_secret client_secret
 *
 * @apiParamExample {json} 示例
 *   POST /api/oauth/token
 *   {
 *      "client_id": "client_id",
 *      "client_secret": "client_secret"
 *   }
 *
 * @apiSuccess (成功) {number} code 0
 * @apiSuccess (成功) {string} msg success
 * @apiSuccess (成功) {Object} data Token对象
 * @apiSuccess (成功) {string} data.token Token
 * @apiSuccess (成功) {number} data.expires 失效时间(24小时)请保存若失效重新获取
 * @apiSuccess (成功) {number} data.appid AppId
 * @apiSuccessExample {json} 示例
 *   HTTP/1.1 200 OK
 *   {
 *     "code": 0,
 *     "msg": "success",
 *     "data": {
 *       "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOjIsImV4cCI6MTQ2NDE1NjA2OTg3Nn0.4i_o7gCjCKvOImSi4peCMgCUrzpdgbtmvMECKf5wkqE",
 *       "expires": 1464156069876,
 *       "appid": 2
 *     }
 *   }
 *
 * @apiError (失败) {number} code 1:client_id不存在 2:client_id禁用 3:client_secret错误 4:参数错误
 * @apiError (失败) {string} msg 错误文字描述
 * @apiErrorExample {json} 示例
 *   HTTP/1.1 200 OK
 *   {
 *     "code": 1
 *     "msg": "client_id has error"
 *   }
 */

框架配置静态目录,让其可访问:
config/http.js

customMiddleware: function (app) {
    app.use('/apidoc', require('express')['static'](require('path').normalize(__dirname + '/../apidoc')));
},