简介

目前能够方便地部署Meteor app的方法还不多,一般都是用官网的Galaxy或者meteor up或者按照部署Nodejs服务器的方式。而如果我们想要使用Nginx作为Web服务器,其中配置的步骤又很繁琐,那有没有好的开源项目或者平台能够帮助我们减轻痛苦呢?答案是必须的。下面就隆重请出今天的主角——PhusionPassenger

Passenger简介

passenger
passenger

Passenger 想必对于Rails开发者都很熟悉了,使用Passenger+Apache/Nginx配置Rails Web程序也是主流之一。

没想到如今竟然也支持Meteor(其实不止Meteor,还支持Nodejs和Python)。从他的官网介绍中可以看到——A web server and application server for your web apps,其实就是整合了web服务器和后端语言所需要的各种依赖包。而且他的官网有非常详细的教程,本文就是按照此教程一步步走下来的,其中也记录了我部署过程中遇到的一些问题和解决方法。话不多说,首先奉上地址:

步骤一 选择一台云服务器

国外一般用亚马逊或Digital Ocean的云服务器,这里我们就选择通用的运行Linux的服务器,配置差不多都一样。我使用的是阿里云运行Ubuntu14.04的服务器,当然CentOS也支持。

步骤二 选择Passenger集成包

官网总共提供了三种模式:与Nginx集成,与Apache集成,Standalone。三种模式的介绍与区别大家看官网,这里我选择了Nginx集成模式。

步骤三 选择Passenger版本

有开源版和企业版,企业版要收费的,所以我选择了open source

步骤四 安装Nodejs环境

说明 以下都是在你买的服务器上操作的

1
2
3
4
5
$ sudo apt-get update
$ sudo apt-get install -y curl apt-transport-https ca-certificates &&
curl --fail -ssL -o setup-nodejs https://deb.nodesource.com/setup_0.12 &&
sudo bash setup-nodejs &&
sudo apt-get install -y nodejs build-essential

经过此过程,安装的Nodejs版本是0.12.10,大家也可以从NodeSource安装其他的版本如v4.3.1,或者使用nvm版本管理脚本。不过一开始在我尝试使用更高的版本时,老是出问题,后来发现Meteor不支持更高的Nodejs版本,所以大家尽量使用v0.12或者以下的版本吧!

另外,使用nvm版本管理安装的Nodejs,其实安装到了你的用户目录下,以后使用不需要sudo命令,方便。而上面的步骤会全局安装Nodejs,以后安装包时,会出现权限问题,大家自行选择。

步骤五 安装Passenger

还是先选择你的服务器安装的系统类型和版本,这里我选择的是Ubuntu14.04.开始安装:

1
2
3
4
5
6
7
8
# 添加钥匙和apt包
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt-get install -y apt-transport-https ca-certificates
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update

# 安装Passenger和Nginx
sudo apt-get install -y nginx-extras passenger

安装完成后,打开vim /etc/nginx/nginx.conf,并取消下面两行的注释:

1
2
# passenger_root /some-filename/locations.ini;
# passenger_ruby /usr/bin/passenger_free_ruby;

然后重启Nginx服务器:

1
sudo service nginx restart

查看是否安装成功:

1
sudo /usr/bin/passenger-config validate-install

查看Passenger运行情况(不是必须):

1
sudo /usr/sbin/passenger-memory-stats

最后重新执行一下:

1
2
sudo apt-get update
sudo apt-get upgrade

目前都还是准备工作,下面开始上正餐了。

步骤六 部署Meteor App

说明 以下操作是在你的本地机器上

首先打包你的Meteor程序包meteor bundle package.tar.gz,此处使用的是bundle命令,会出现提示说这个命令已经被build命令取代了,不过这里因为build命令会把iOS and Android移动平台的包一起打包进去,而我们并不需要。package.tar.gz是你取的压缩包的名字和格式。执行结束后,会在当前目录下生成。
然后传到服务器上:

1
2
3
scp package.tar.gz  adminuser@yourserver.com:
# 例如(最好使用IP地址,注意最后的冒号)
scp package.tar.gz root@120.24.72.4:

登陆到服务器:ssh root@120.24.72.4(需要先下载ssh)

说明 以下操作是在你的远程服务器上

首先创建一个普通用户如blog(如果你以前已经创建过,可以省略这一步),按照提示输入密码(注意:不是你的root账户密码

1
adduser blog

然后确保以后可以不用密码登陆服务器(不是必须)

1
2
3
4
5
6
sudo mkdir -p ~blog/.ssh
touch $HOME/.ssh/authorized_keys
sudo sh -c "cat $HOME/.ssh/authorized_keys >> ~blog/.ssh/authorized_keys"
sudo chown -R blog: ~blog/.ssh
sudo chmod 700 ~blog/.ssh
sudo sh -c "chmod 600 ~blog/.ssh/*"

现在blog用户是没有root权限的,不能使用sudo命令,最好把blog添加到sudoers里,输入visudo,找到:

1
2
# User privilege specification
root ALL=(ALL:ALL) ALL

在下面添加一句:

1
2
3
# User privilege specification
root ALL=(ALL:ALL) ALL
blog ALL=(ALL:ALL) ALL

切换到blog用户(以后直接使用这个用户就行,不用在使用root)

1
sudo -u blog -H bash -l

然后你就能使用sudo命令了,注意,你的root用户密码不要和你的普通用户密码一样,以后需要输入密码时,直接输入普遍用户的
密码就可以了,不需要再使用root用户的密码。

接下来:

1
2
3
4
5
6
# 创建程序使用的目录(名字任意)
sudo mkdir -p /var/www/blog
# 然后进入
cd /var/www/blog/
# 解压到此目录
sudo tar zxf ~/package.tar.gz

安装mongodb

1
sudo apt-get install -y mongodb

此处最好进入到/bundle目录下,创建两个空目录,后面要用到public目录,
tmp目录可以创建restart.txt文件,用于Nginx重启(现在不需要):

1
mkdir tmp public

接着进入到cd /programs/server目录下,执行:

1
sudo npm install --production

安装完成后,创建Nginx配置文件:

1
2
sudo vim /etc/nginx/sites-enabled/blog.conf
# 后面的文件名任意

写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 80;
server_name yourserver.com;
# 写你的域名 或者直接写IP

# 你的程序的public目录,就是刚才创建的空目录
root /var/www/blog/bundle/public;

# 开启Passenger
passenger_enabled on;
# 说明是个meteor app
passenger_app_type node;
passenger_startup_file main.js;

# MongoDB的位置,此处不用改就可以,后面的文件名任意,但不能有'.',如myapp.db
passenger_env_var MONGO_URL mongodb://localhost:27017/blogdb;
# 你的根url,也可以是IP
passenger_env_var ROOT_URL http://yourserver.com;
}

最后重启Nginx

1
sudo service nginx restart

然后你可以访问你的网站了:

  1. 如果能直接访问,那只有恭喜你了
  2. 如果显示500错误,说明Passenger配置过程出错,没有启动,你可以再仔细从头来一遍
  3. 如果出现Passenger提示的错误信息,如We're sorry, but something went wrong.说明Passenger启动了,但是程序内部有误,我就是在第三种情况下困扰了好久,这时就要查看Nginx错误日志了:
1
sudo cat /var/log/nginx/error.log

也可以查看Passenger的输出信息,在/var/log/目录下,有很多html文件,你可以用cat命令查看。然后根据错误信息Google之,可能遇到的问题不一样,下面是我遇到的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/your-app-path/bundle/programs/server/node_modules/fibers/future.js:245
throw(ex);
^
Error: Module did not self-register.
at Error (native)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at bindings (/your-app-path/bundle/programs/server/npm/npm
-bcrypt/node_modules/bcrypt/node_modules/
bindings/bindings.js:74:15)
at Object.<anonymous> (/your-app-path/bundle/programs/server/npm/
npm-bcrypt/node_modules/bcrypt/bcrypt.js:3:35)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)

在网上搜了许多方法,归纳一下就是这两个包fibersbcrypt的依赖关系,需要重新安装,不过我试了N多遍,还是不行,就在我要放弃的时候,
又重新仔细看了一遍错误原因,才发现bcrypt这个包的位置不在bundle/programs/server/node_modules/目录下,而是在/bundle/programs/server/npm/npm-bcrypt/node_modules/目录下,然后瞬间看到一丝希望,赶忙删除/bcrypt这个目录,重新运行npm install bcrypt安装了新的包,最后
重启Nginx,访问我的域名,真的就成功了。此刻,我真的想哭。泪的教训:看错误日志一定要仔细,仔细,再仔细

总结一下:

  1. 运行npm install --production后,fibersbcrypt这两个包应该就在正确的位置了
  2. 但由于依赖问题(我猜)不能工作,安装的fibers的版本是1.0.5bcrypt的版本是0.7.8
  3. 所以我只把/bundle/programs/server/npm/npm-bcrypt/node_modules/目录下的/bcrypt文件夹删除
  4. 然后重新安装npm install bcrypt(注意是在这目录下),就会安装0.8.5版本bcrypt
  5. 然后问题就能解决,最后重启Nginx
  6. 注意我没有重新安装fibers

步骤七 你的程序需要更新时

当我们更新程序后,需要上传新的打包好的文件,并再次部署,也可以编写自动化脚本,帮助你处理。这部分内容请大家直接看官网的步骤,我这里不再赘述了。

接下来

Passenger还能做更多,比如一台服务器可以同时运行多个Meteor app,监控你的内存和CPU,更多的配置项和优化功能,错误处理和调试等。

总结

可以看到,使用Passenger真的很方便,不用再头疼Nginx 的配置了,极大地节省了你的时间,强烈推荐大家使用。

如果你遇到了其他问题,并且不能解决,可以联系我。