介绍
在将 Web 应用部署到 Droplet 时,可能会诱人地简单地使用与开发中相同的设置,即在终端中运行“ruby app.rb”或“node server.js”来启动服务器。这样做简单易行,同时提供可见的日志。甚至可以使用“screen”、“tmux”或“nohup”来使其在 SSH 会话断开时保持运行。但这是危险的:如果服务器崩溃而没有人在附近重新启动它会怎么样呢?
可以使用 forever 和 crontab 来解决这个问题。本教程提供了一个更健壮但更复杂的解决方案。使用 systemd(在 Arch 和 Fedora 上可用,在将来的 CentOS 上也可用),可以全面管理 Web 应用程序:日志、正常运行时间、通过 cgroups 进行资源和安全性控制,以及高级守护程序启动,所有这些都可以以统一的方式访问、控制和微调。
本教程使用一个简单的 Node.js 应用程序,但同样适用于大多数其他应用程序(无论是 Ruby、Python 等)。对于 PHP Web 应用程序,建议使用更专业的 LAMP 或 LEMP 堆栈。
将为 Fedora 和 Arch 提供命令,请注意区分以避免配置错误和/或混淆。如果没有指示,命令对两个系统都是相同的。还建议在逐步尝试之前阅读整个教程,以便了解其内容并确定它是否适合您的情况。
系统准备工作
- 一个带有 systemd 的服务器。默认情况下,Arch Linux 和 Fedora droplets 已配置好。
- Nginx,用作反向代理 HTTP 和 WebSocket 服务器。
- Git,用于安装 nvm,并在使用 git 时拉取您的应用程序。
- Root 访问权限。也可以以普通用户身份登录并对所有命令使用 sudo,或者切换到 root 提示符的 su - 或 sudo su -。
安装软件包
Arch:
# pacman -Sy # pacman -S nginx git
Fedora:
# yum install nginx git
应用程序准备工作
这些是您可以根据自己的喜好进行自定义的设置,但它们必须在开始之前决定并设置好。
用户
应用程序将在其自己的独立用户帐户中运行。选择一个名称,它应该与应用程序相关,以便易于记忆和维护。在这里,使用了 srv-node-sample
。
# useradd -mrU srv-node-sample
端口
为了避免冲突,选择一个高端口。在这里,使用了“15301”。
应用程序设置
首先安装应用程序运行所需的内容。对于 Node.js(以及 Ruby、Python 等),有两种选择:要么使用系统的运行时,要么使用特定于用户的安装(例如使用 nvm、rbenv、RVM、virtualenv 等)。
使用系统的 node
Arch:
# pacman -S nodejs
Fedora:
# yum install nodejs
使用特定于用户的安装
这必须安装在应用程序的主目录中,即 /home/srv-node-sample
,最简单的方法是以该用户身份登录:
# su srv-node-sample
$ cd $ curl https://raw.github.com/creationix/nvm/master/install.sh | sh $ source ~/.nvm/nvm.sh $ nvm install 0.10 $ nvm alias default 0.10
然后注意 node 二进制文件安装的位置:
$ which node /home/srv-node-sample/.nvm/v0.10.22/bin/node
部署您的应用程序
在 srv-node-sample
用户登录后,部署您的代码。这只是一个示例,您的过程会有所不同。
$ git clone git@server.company.tld:user/repo.git . $ npm install $ grunt deploy
对于本教程,使用了以下示例应用程序:
js var http = require('http'); http.createServer(function(req, res) { res.end('<h1>Hello, world.</h1>'); }).listen(15301);
然后返回到 root:
$ exit
Nginx 设置
本教程仅简要介绍了所需的配置,有关配置 Nginx 的更详细教程,请参阅“如何配置 Nginx Web 服务器”或 nginx 手册。
将以下内容放入您的服务器块中:
location / { proxy_pass http://localhost:15301/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
然后设置其守护程序:
systemctl enable nginx
systemctl restart nginx
## Systemd 设置 在 `/etc/systemd/system/node-sample.service` 中创建应用程序的服务文件。 有一些需要填写的变量: - [node binary] 这是作为 srv-node-sample 用户输出的“which node”的结果。可以是 `/usr/bin/node` 或上面提到的 `~/.nvm/...` 路径。 - [main file] 这是你的应用程序的主文件。在这里是 `index.js`。 不要忘记替换 `srv-node-sample`!
[Service]
ExecStart=[node binary] /home/srv-node-sample/[main file]
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=node-sample
User=srv-node-sample
Group=srv-node-sample
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
现在启动服务:
systemctl enable node-sample
systemctl start node-sample
## 用法 ### 状态
systemctl status node-sample
node-sample.service
Loaded: loaded (/etc/systemd/system/node-sample.service; enabled)
Active: active (running) since Fri 2013-11-22 01:12:15 UTC; 35s ago
Main PID: 7213 (node)
CGroup: name=systemd:/system/node-sample.service
└─7213 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod…
Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service.
### 日志
journalctl -u node-sample
– Logs begin at Thu 2013-11-21 19:05:17 UTC, end at Fri 2013-11-22 01:12:15 UTC. –
Nov 22 01:12:15 d02 systemd[1]: Starting node-sample.service…
Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service.
Nov 22 01:12:30 d02 node-sample[7213]: Sample message from application
### 重启、停止等 强制重启:
systemctl restart node-sample
停止应用程序:
systemctl stop node-sample
如果应用程序死掉或被杀死,它将自动重新启动:
systemctl status node-sample
node-sample.service
Loaded: loaded (/etc/systemd/system/node-sample.service; enabled)
Active: active (running) since Fri 2013-11-22 01:12:15 UTC; 35s ago
Main PID: 7213 (node)
CGroup: name=systemd:/system/node-sample.service
└─7213 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod…
Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service.
kill 7213
systemctl status node-sample
node-sample.service
Loaded: loaded (/etc/systemd/system/node-sample.service; enabled)
Active: active (running) since Fri 2013-11-22 01:54:37 UTC; 6s ago
Main PID: 7236 (node)
CGroup: name=systemd:/system/node-sample.service
└─7236 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod…
Nov 22 01:54:37 d02 systemd[1]: node-sample.service holdoff time over, sch…t.
Nov 22 01:54:37 d02 systemd[1]: Stopping node-sample.service…
Nov 22 01:54:37 d02 systemd[1]: Starting node-sample.service…
Nov 22 01:54:37 d02 systemd[1]: Started node-sample.service.
PID 已经改变,显示应用程序确实已被杀死并重新启动。 ### Websockets 如果应用程序使用 Websockets,则必须将以下行添加到 Nginx 配置中:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
proxy_http_version 1.1;
然后重新加载 Nginx:
systemctl reload nginx