# 使用一键脚本部署

GitHub: https://github.com/summerblue/laravel-ubun...

适用于 Ubuntu 16.04 的 LNMP 安装脚本,并设置了国内镜像加速。

请确保所有命令都以 root 账户执行,如果登录账户不是 root,则需要执行 sudo -H -s 切换为 root 账户后再下载安装。

Welcome to Alibaba Cloud Elastic Compute Service !

Last login: Tue Aug 13 13:17:16 2019 from 221.218.153.139
root@iZwn1owkika3a8Z:~# wget -qO- https://raw.githubusercontent.com/summerblue/laravel-ubuntu-init/master/download.sh - | bash
===> 开始下载...
===> 下载完毕

安装脚本位于: /root/laravel-ubuntu-init
===> 正在初始化系统...    [DONE]
===> 正在初始化软件源...    [DONE]
===> 正在安装基础软件...    [DONE]
===> 正在安装 PHP...    [DONE]
===> 正在安装 Mysql / Nginx / Redis / Memcached / Beanstalkd / Sqlite3...    [DONE]
===> 正在安装 Nodejs / Yarn...    [DONE]
===> 正在安装 Composer...    [DONE]
安装完毕
Mysql root 密码:ORAdqR7QwG1aHNk3jaGCpOWBu7owgVvf
请手动执行 source ~/.bash_aliases 使 alias 指令生效。
root@iZwn1owkika3a8Z:~# 

出现以上输出,说明安装成功。注意保存密码,切勿丢失。随后请执行:

$ source ~/.bash_aliases

# 配置运行环境

首先,我们需要增加 Nginx 站点:

$ ~/laravel-ubuntu-init/16.04/nginx_add_site.sh

根据提示,输入一些信息并回车:

请输入项目名:deployment
请输入站点域名(多个域名用空格隔开):laravel-deployment.wi1dcard.cn

请注意,站点名称(项目名)仅允许英文、数字、-_ 组合。另外,与上文宝塔面板类似,站点域名也可以使用公网 IP 代替。

请注意以下输出:

域名列表:laravel-deployment.wi1dcard.cn
项目名:deployment
项目目录:/var/www/deployment
是否确认? [y/N]

记住此处的项目目录,后续将会使用。检查无误后,输入 y 并回车。

没什么问题的话,将会看到成功提示:

配置文件创建成功
Nginx 重启成功

# 修改linux的配置文件

/etc/nginx/sites-available/<站点名>.conf

# 手动部署

# 初始化系统

全新的 Ubuntu Bionic 18.04 LTS 服务器

# 切换root用户

$ sudo -i

# 更新软件源

登录到服务器,我们首先要做的就是更新软件源:

$ apt update

注意:这里所说的「更新软件源」并非升级软件,在中文内更加准确的描述应当是 刷新软件源。在这个过程中,包管理器(也就是 APT,可以理解为「软件管家」之类)将会从 软件源 服务器上获取一份最新的包列表并建立本地缓存,包括软件名称、描述、最新版本、下载地址等等。

你将会看到类似这样的输出:

Get:1 http://mirrors.cloud.aliyuncs.com/ubuntu xenial InRelease [247 kB]
Get:2 http://mirrors.cloud.aliyuncs.com/ubuntu xenial-updates InRelease [109 kB]
Get:3 http://mirrors.cloud.aliyuncs.com/ubuntu xenial-security InRelease [109 kB]
...

稍等片刻即可刷新完毕,最后有可能提示:

186 packages can be upgraded. Run 'apt list --upgradable' to see them.

意为有 186 个软件包可升级,执行 apt list --upgradable 命令来查看它们。

我们暂且忽略,直接升级:

$ apt upgrade

注意:生产环境下,更新任何软件包前都需要仔细检查,确保更新日志内没有影响现有环境的改动。另外,你也可以先不升级,对后续部署基本没有影响。

你将会看到一大坨(是的,一坨)输出,它们是将被升级的软件列表;注意关注最后几行:

186 upgraded, 8 newly installed, 0 to remove and 0 not upgraded.
Need to get 249 MB of archives.
After this operation, 331 MB of additional disk space will be used.
Do you want to continue? [Y/n]

意为此操作将占用 331 MB 磁盘空间。此时输入 Y(注意关闭中文输入法),或直接回车即可开始升级。主流云服务厂商均有缓存软件源,数据流量是通过内网传输,所以该过程不会太慢。

# 本地化配置

所谓「本地化配置」,可理解为系统时区、单位、地址、语言等配置的统称。使其能够符合某一地区的习惯。虽然我们的母语是中文,但还是建议将服务器配置为英语,尽可能避免奇葩乱码等问题带来的影响。

首先,执行以下命令生成美国本地化数据:

$ locale-gen en_US.UTF-8

随后将本地化配置修改为 en_US.UTF-8 即可:

$ update-locale LC_ALL=en_US.UTF-8

如果服务器在国外,则服务商可能不会将其配置为东八区;我们还需手动修改时区为 Asia/Shanghai

timedatectl set-timezone Asia/Shanghai

若你是在国内云服务商租用的服务器,那么极有可能时区已经配置好了。

至此,系统初始化阶段完成。

# 安装 Nginx

由于我们执行 apt update 更新软件源不久,所以直接安装 Nginx 即可:

$ apt install nginx

再次收到确认提示:

0 upgraded, 10 newly installed, 0 to remove and 0 not upgraded.
Need to get 2,715 kB of archives.
After this operation, 8,752 kB of additional disk space will be used.
Do you want to continue? [Y/n]

上节为大家介绍过输入 Y 或直接回车均可继续,也就是说此处的询问默认结果为 Y。有个普遍共识是,在提供选项供用户选择时,以大写项为默认值。例如此处的 [Y/n] 那么 Y 即为默认值;同理,若是 [a/b/c/D/e],那么 D 即为默认值。

另外,上节介绍了更新软件源即为包管理器从软件源服务器拉取软件包列表并建立本地缓存。其实,当我们执行 apt install 操作时,包管理器便会从本地缓存中找到该软件包的指定版本,并进行下载、安装。

稍等几秒钟即可安装成功:

img

# 管理 Nginx 服务

我们可使用 service 命令管理服务状态,常用操作如下:

$ service nginx start # 启动 Nginx
$ service nginx stop # 停止 Nginx
$ service nginx restart # 重启 Nginx

同时,可使用 systemctl 命令开关服务的开机自启:

$ systemctl enable nginx # 启用 Nginx 开机启动
$ systemctl disable nginx # 禁用 Nginx 开机启动

注意:通常情况下,在 APT 安装后已默认启用 Nginx 开机启动。

# 确认 Nginx 正常运行

与一键脚本类似,在浏览器内输入服务器公网 IP(或域名)并打开,出现默认欢迎页面说明 Nginx 已经正常运行:

img

恭喜,Nginx 安装成功。

# 安装 PHP

# 配置第三方软件源

由于 Ubuntu 的官方软件源通常不包含最新版本的 PHP,因此需要添加一个包含最新 PHP 的第三方软件源。

在添加之前,我们首先安装名为 software-properties-common 的软件包,它提供了快速管理软件源的实用脚本:

$ apt install -y software-properties-common

相比之前执行的 apt install 命令,这次我添加了 -y 选项,表示当 APT 遇到询问时默认确认,避免再次输入 Y 并回车。

随后,执行以下脚本添加第三方 PHP 软件源:

$ add-apt-repository -y ppa:ondrej/php

成功后别忘记刷新:

$ apt-get update

# 安装 PHP

PHP 的安装实际上分为三个软件包:

  • PHP - PHP 自身。
  • PHP-CLI - PHP 的命令行接口,通俗地说,在命令行内执行 php 便依赖于此包。
  • PHP-FPM - 全称为 PHP FastCGI Process Manager,用于管理 PHP 进程,并提供 FastCGI 接口与 Nginx 交互;浏览网页时的请求便是由 Nginx 交由 PHP-FPM 处理的。

apt install 支持多参数,所以我们不必执行多次安装,只需在单条命令内写明多个软件包即可:

$ apt install -y php7.2 php7.2-cli php7.2-fpm

按照 Laravel 5.8 安装文档 的说明,接着安装几个必备的 PHP 扩展:

$ apt install -y php7.2-mbstring php7.2-xml php7.2-bcmath

注意:由于 PDO 等扩展已经内置在 PHP 中,故无需额外安装。

对于不同项目的不同依赖,可能有必要安装以下扩展,根据实际情况选择即可:

$ apt install php7.2-curl php7.2-gd php7.2-mysql php7.2-opcache php7.2-zip php7.2-sqlite3

有个小技巧是,你可以通过 apt-cache 命令来搜索当前软件源内的包:

$ apt-cache search php7.2

例如以上命令,将会得到所有名称、描述等信息内包含 php7.2 字样的软件包:

php-amqp - AMQP extension for PHP
php-apcu - APC User Cache for PHP
php-geoip - GeoIP module for PHP
...

# 管理 PHP-FPM 服务

与管理 Nginx 服务类似,你同样可以通过 servicesystemctl 命令管理 PHP-FPM 服务:

$ service php7.2-fpm restart# 重启 PHP-FPM
$ service php7.2-fpm start # 启动 PHP-FPM
$ service php7.2-fpm stop # 停止 PHP-FPM
$ systemctl enable php7.2-fpm # 启用 PHP-FPM 开机启动
$ systemctl disable php7.2-fpm # 禁用 PHP-FPM 开机启动

注意:不同版本的 PHP-FPM 服务名是不一致的。例如 7.2 为 php7.2-fpm,7.3 为 php7.3-fpm,以此类推……

# 确认 PHP-FPM 正常运行

通过以下命令可确认 PHP-FPM 进程正在运行:

$ ps aux | grep php

其中:

  • ps aux 用于列出系统当前正在运行的所有进程的所有信息。
  • | 名为管道操作符,将前一条命令的标准输出连接到下一条命令的标准输入。
  • grep 是一款文本搜索工具,常用来过滤命令行输出;php 是搜索的关键词。

ps 将进程信息输出到 grep 进行过滤,后者筛选出包含 php 字样的行,再将它们输出。于是,它们相结合,产生的效果便是这样:

root      6546  0.0  3.8 315484 19340 ?        Ss   14:13   0:00 php-fpm: master process (/etc/php/7.2/fpm/php-fpm.conf)
www-data  6550  0.0  1.0 315484  5260 ?        S    14:13   0:00 php-fpm: pool www
www-data  6551  0.0  1.0 315484  5260 ?        S    14:13   0:00 php-fpm: pool www
root      6566  0.0  0.1  15964   920 pts/0    S+   14:13   0:00 grep --color=auto php

忽略最后一行(这是我们正在执行的 grep 命令),可观察到有 php-fpm 进程正在运行中。

若 PHP-FPM 进程不存在,那么输出将只有孤零零的 grep

root      6722  0.0  0.1  15964   920 pts/0    S+   14:24   0:00 grep --color=auto php

提示:你可以结合上文提到的 service 命令,将服务进程手动停止试试看;测试完毕不要忘记再次启动。

# 安装 Git 和 Composer

Git 和 Composer 是部署 PHP 项目时必不可少的两款工具。用它们代替原有 SCP 方案有许多好处:

  • 安全
  • 快速
  • 可回滚
  • 易管理
  • ...

好处非常非常多。实际上,正如之前提到的「在生产环境中这样做很危险」,直接使用 SCP 或压缩包传输代码是万万不可取的,具体原因请见文末。

# 安装 Git

依然使用 APT 安装:

$ apt install -y git

# 安装 Composer

Composer 比较特殊,不能通过 APT 安装。虽然网络上流传着一大堆从第三方服务器直接下载 composer.phar 文件的安装方式,但根据 Composer 的官方文档,正确的安装姿势应当为:

$ wget https://raw.githubusercontent.com/composer/getcomposer.org/master/web/installer -O - -q | php -- --filename=composer --install-dir=/usr/local/bin

以上修改自 https://getcomposer.org/doc/faqs/how-to-in...,另一种比较复杂的安装方式可参考 https://getcomposer.org/download/。你可以不必关心该脚本的具体意义,通常它只需执行一次。

注意:通过第三方服务器、直接下载 composer.phar 不进行任何检查,均无法保证 Composer 正常运行,且存在安全风险!请务必遵循官方文档内的说明。

稍等片刻,将会出现以下输出:

All settings correct for using Composer
Downloading...

提示当前环境检查通过,可正常使用 Composer;随后开始下载。

鉴于众所周知的原因,大陆访问国际网络速度奇慢无比,请耐心等待。当出现以下提示时,表示已经安装成功:

Composer (version 1.8.4) successfully installed to: /usr/local/bin/composer
Use it: php /usr/local/bin/composer

按照提示,我们可以使用 /usr/local/bin/composer 运行 Composer,当然,还有个更简单的方法:

$ composer

你可能会收到这样一条警告:

Do not run Composer as root/super user! See https://getcomposer.org/root for details

意为请勿使用根用户运行 Composer;暂时不必关心它,我将在后续课程中详细说明。

# 配置 Packagist 中国镜像

这一步是可选的。如果你的服务器位于大陆,强烈建议使用可信赖的代理,或是国内 Packagist 镜像。

推荐使用 Laravel-China 提供的 Packagist 中国镜像,执行以下命令即可切换服务器内 Composer 的默认 Packagist 源:

$ composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

# 拓展:为什么生产环境中万万不可使用 SCP 传输代码?

更准确地说,这个问题应该是:为什么不可使用 SCP 将整个 Laravel 应用传输到服务器的 Nginx 站点目录?

SCP 传输文件 这一操作本身不存在任何问题;不过,本地开发时 APP_DEBUG(调试模式)通常为打开状态,并且 APP_KEY(应用密钥)已经生成为一个固定值,若是利用 SCP 将整个目录传输到服务器并直接公开,那么 .env文件内的值也会照搬到服务器内。

调试模式时展示的详细错误信息虽然有利于排查问题,但在生产环境开启极易引发安全漏洞;至于应用密钥,Laravel 将使用它加密 Cookie 等信息,在本地和线上绝对不应当使用相同值,更严格地说,线上的 APP_KEY 必须完全随机并确保不被任何人获得。

虽然你可以上传后再修改它们的值,或是使用类似 Rsync 等支持忽略特定文件的方式。但其一,不方便、易受人为失误影响;其二,无法享受 Git + Composer 的大量优势。

综上所述,在实际部署过程中,绝对不推荐使用 SCP 传输代码

# 安装 MySQL

# 安装 MySQL 5.7

$ sudo apt update # 更新源
$ sudo apt-get install -y mysql-server mysql-client # 安装 MySQL 服务端及客户端
$ sudo mysql_secure_installation # 设置。在这里可以设置 root 密码、删除测试数据库、禁止远程访问(即只能本地访问或者 via SSH:通过 SSH 访问)等等。

# 安装 MySQL 8.0

$ wget  -c  https://repo.mysql.com/mysql-apt-config_0.8.13-1_all.deb # 下载 MySQL 8.0 的 deb 包
$ sudo dpkg  -i  mysql-apt-config_0.8.10-1_all.deb # 安装 deb 包
$ sudo apt update
$ sudo apt-get install -y mysql-server mysql-client
$ sudo mysql_secure_installation

# 进行数据库设置

root@VM-0-3-ubuntu:~# mysql_secure_installation

Securing the MySQL server deployment.

Connecting to MySQL using a blank password.

VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No: 

是否使用VALIDATE PASSWORD插件,来检查用户设置的密码强度?我们输入 y

There are three levels of password validation policy:

LOW    Length >= 8    //弱强度
MEDIUM Length >= 8, numeric, mixed case, and special characters //
STRONG Length >= 8, numeric, mixed case, special characters and dictionary     //高强度             file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 

系统为我们提供了三个密码验证策略供我们选择,我们这里选择高强度 2

Please set the password for root here.

New password: 

输入 大小写字母 + 数字 + 字符的密码,输入完毕回车即可

Estimated strength of the password: 100 
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : 

密码强度: 100 ,询问我们是否使用密码,继续设置。 我们输入y

By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : 

默认情况下,MySQL安装有一个匿名用户,允许任何人登录MySQL而不必拥有为他们创建的用户帐户。 这仅适用于 测试,并使安装更顺畅。您应该在进入生产之前将其删除环境。 输入y

Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : 

通常,只允许root连接'localhost' 的。 这可以确保有人无法猜测来自网络的root密码。禁止远程登录 输入y

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : 

默认情况下,MySQL附带一个名为'test'的数据库,任何人都可以访问 这也仅用于测试,并且应该在进入生产之前将其删除 环境。访问它并删除测试数据库。输入y

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : 

至此,我们对数据库的配置设置完毕,输入y,立即生效。

安装完数据库后,mysql默认是不允许远程连接。m

mysql默认是只允许本地连接的。所以我们需要修改一个配置文件。然而最新版本的mysql跟以前目录结构不太一样,最新版本的允许远程连接放在/etc/mysql/mysql.conf.d/mysqld.cnf 这个配置文件下,搜索bind-address = 127.0.0.1 这行,把它注释掉,然后是用命令service mysql restart重启mysql服务就可以了。

# 部署应用代码

# 使用 Git 拉取项目(HTTPS 协议)

登录到服务器,执行:

$ cd /var/www/

cd 命令用于切换当前工作目录,/var/www 是 Nginx 默认的站点存放目录。

随后便可以将仓库克隆到本地了:

$ git clone https://github.com/wi1dcard/hello-deployment.git deployment

提示:若仓库包含大量提交历史,以上命令可能耗时较久;你可以尝试使用 --depth 选项来优化,详情请搜索 Git 浅克隆 等关键字。

请将命令中的 URL 替换为刚刚从 GitHub 或其它仓库托管平台内复制的链接。末尾的 deployment 参数表示将此仓库克隆至当前工作目录下的 deployment 子目录内。

稍等将会出现以下输出:

Cloning into 'hello-deployment'...
remote: Enumerating objects: 130, done.
remote: Counting objects: 100% (130/130), done.
remote: Compressing objects: 100% (95/95), done.
remote: Total 130 (delta 50), reused 105 (delta 32), pack-reused 0
Receiving objects: 100% (130/130), 2.73 MiB | 850.00 KiB/s, done.
Resolving deltas: 100% (50/50), done.
Checking connectivity... done.

如果你的项目是「私有」的,那么可能需要输入用户名和密码:

Cloning into 'hello-deployment'...
Username for 'https://github.com': <输入你的用户名>
Password for 'https://wi1dcard@github.com': <请输入你的密码>

提示:还记得之前提到的吗?密码输入是不可见的。

# 使用 Composer 安装依赖

首先,请切换至 deployment 目录内:

$ cd deployment

接着执行:

$ composer install

稍等片刻,你可能会看到这样的警告:

Failed to download foo/bar from dist: The zip extension and unzip command are both missing, skipping.
Now trying to download from source

意为 PHP Zip 扩展和 unzip 命令均找不到,此时 Composer 会尝试从依赖的 Git 仓库内直接克隆源码,这是不推荐的;因此我们使用 Ctrl + C(macOS 为 Cmd + C)中止正在运行的命令。

针对该警告信息,可以想到两种解决思路:

  • 使用之前小节提到的 apt-cache search 搜索 php zip 关键字,查找 Zip 扩展并安装。
  • 安装 unzip 命令。

第一种方法本节不再赘述,我们来尝试第二种方法。首先,尝试手动执行 unzip,确认它的确未安装:

$ unzip
The program 'unzip' is currently not installed. You can install it by typing:
apt install unzip

看样子在当前系统中确实找不到 unzip。不过,贴心的 APT 帮我们找到了包含 unzip 的软件包,并直接提供了安装命令:

$ apt install unzip

稍等片刻便安装好了。此时再次执行:

$ unzip
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.
...

完美。

实际上,不仅是 Composer,其它多数命令都支持使用 Ctrl + C 中止运行;如果 Ctrl + C 无效,你也可以试试 Ctrl + D;另外,结合 APT 的提示和 apt-cache search,可以帮助我们很快地解决绝大多数命令缺失的错误,而无需遵从百度来的手动而又复杂的源码编译步骤。

我们回到主题,再次运行 composer install

Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 72 installs, 0 updates, 0 removals
  - Installing dragonmantank/cron-expression (v2.2.0): Downloading (100%)
  - Installing erusev/parsedown (1.7.1): Downloading (100%)
  - Installing symfony/var-dumper (v4.2.3): Downloading (connecting...)

恭喜,等待安装完毕即可。

# 配置环境变量

依赖安装完成后,我们还需要将 .env.example 文件复制为 .env 文件,并生成 APP_KEY 密钥:

$ cd /var/www/deployment
$ php -r "file_exists('.env') || copy('.env.example', '.env');"
$ php artisan key:generate --ansi

提示:实际上,以上两条命令都是从部署应用的 composer.json - scripts 小节内摘抄出来的,这也解释了为何使用 laravel new 创建项目后 .env 文件就已经存在。有兴趣可深入了解 Composer Scripts

# 配置文件所有者

最后,别忘记修改文件所有者:

$ chown -R www-data:www-data .

由于目前所在的工作目录为 /var/www/deployment,所以可用表示当前工作目录的 . 代替之前的 /var/www/deployment,它们是等效的。

至此,本小节目标完成。你可以通过 ll 命令来列出当前目录:

$ ll
total 440
drwxr-xr-x 13 www-data www-data   4096 Mar  9 01:26 ./
drwxr-xr-x  5 root     root       4096 Mar  9 00:49 ../
drwxr-xr-x  6 www-data www-data   4096 Mar  9 00:45 app/
-rw-r--r--  1 www-data www-data   1686 Mar  9 00:45 artisan
...

# 配置 Nginx 站点信息

# Nginx 站点配置

根据 Laravel 5.8 部署文档 的说明,我们可直接拿到一份现成的 Nginx 配置文件,稍作调整即可:

server {
    listen 80;
    server_name laravel-deployment.wi1dcard.cn; # 此为必修改项,请替换为服务器公网 IP 或域名
    root /var/www/deployment/public; # 此为必修改项,请注意指向站点根目录的 public 子目录

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; # 请注意核对 PHP 版本
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

提示:关于以上 Nginx 配置项的解析,可参见 这篇博客

通常我们仅需修改 server_namerootfastcgi_pass;请注意阅读 # 后的注释。

我们将以上内容保存到本地文件(例如 deployment.conf)内,使用 SCP 即可上传至服务器:

$ scp ~/deployment.conf root@laravel-deployment.wi1dcard.cn:/etc/nginx/sites-enabled/

提示:如果你熟悉 vi 等文本编辑器,也可以直接在服务器上操作,此处不再展开。

其中:

  • ~/deployment.conf 请替换为配置文件的实际保存路径,该路径位于本地。
  • /etc/nginx/sites-enabled/ 为存放 Nginx 站点配置的目录,该目录位于服务器。

# 重载 Nginx

配置完成后,请务必重启(Restart)或重载(Reload)Nginx。

什么是 重载?实际上,直接重启 Nginx 是不安全的。原因有二:

  • 在 Nginx 进程结束再重新运行的过程中,将造成极短时间的闪断。虽然这一时间通常很短(一般来说在秒级别),但倘若面对大量并发,还是极易造成一部分请求无法访问,即服务中断。
  • 在重启的过程中,若此时 Nginx 恰好正在处理请求,与客户端的 TCP 连接将会断开,客户端无法收到正确响应,造成前后端信息不一致。

在之前的小节中,已经提到重启 Nginx 的方法;

$ service nginx restart

同样地,亦可使用 service 命令重载 Nginx:

$ service nginx reload

另一种等效的方法是:

$ nginx -s reload

# 最终效果

在浏览器内输入服务器公网 IP 或域名并访问,你将会看到 Laravel 应用的默认主页:

img

恭喜你,部署成功。

# 生产环境的必要优化

# Nginx 配置

对于 Laravel 应用来说,优化 Nginx 配置所带来的性能提升可谓微不足道。因此不建议在中小型项目中花费较多精力调优 Nginx。

不过,有一点值得注意:

server {
    # ...
    location ~* \.(js|css)$ {
        expires 24h;
    }
    #...
}

通过以上配置,可使 Nginx 匹配请求 URI,若以 jscss 结尾,则将响应头 Expires 的值设置为 24h返回。客户端浏览器将根据该值建立资源缓存,并在指定时间后过期,因此可节省部分服务器静态资源流量。24h 可根据需要调整,若使用 CDN 服务分发静态资源,则不必配置此项。

# Laravel 的配置缓存与路由缓存

开启 配置缓存路由缓存 能够在一定程度上提升 Laravel 的性能。

$ php artisan config:cache # 生成配置缓存

注意:当开启配置缓存后,env() 函数将会失效;它将会永远返回 null;因此务必确保在非配置文件内,未直接调用该函数。

$ php artisan route:cache # 生成路由缓存

注意:路由缓存仅支持控制器风格;若路由注册时存在闭包(Closures),则无法使用该功能。

注意:生成缓存后,对配置和路由的修改将不会生效,需再次执行缓存命令,或使用 php artisan cache:clear 命令清除它们。

# Composer

在安装依赖时,建议使用以下命令:

$ composer install --optimize-autoloader --no-dev

其中,--optimize-autoloader 表示生成优化后的自动加载器,虽然生成过程可能较慢,但换来的是提高运行时的效率。--no-dev 表示不安装 composer.json 中 require-dev 声明的扩展包,在生产环境中我们不需要这些开发依赖。

# 再谈文件权限

文件权限直接关系到服务器安全与否。通常情况下,我们应当遵循「最小权限原则」,即权限越小越好。对于 Laravel 来说,我个人比较倾向的权限配置为 750

$ chmod -R 750 /var/www/deployment

你可以通过在线工具 Chmod Calculator 来解析八进制权限数字:

以上是 750 所代表的权限,即文件所有者可 读、写、执行,文件所有组可 读、执行,其余用户 均不可

也就是说,运行 Nginx 和 PHP-FPM 的 www-data 用户,可读、写、执行;www-data 用户组内的用户可读、执行。

更加严格安全的另一个权限推荐是 640,不过务必确保 www-data 用户具备 bootstrap/cachestorage 目录的 读、写 权限,在 Laravel 应用运行过程中是需要读写它们的。

# 杂项

根据应用本身的逻辑不同,涉及的 Laravel 功能也不一样。针对部分项目,你有可能还需要执行以下 Artisan 命令:

$ php artisan storage:link # 软链接 app/storage 到 public 目录,以便公开访问
$ php artisan migrate # 执行迁移
$ php artisan db:seed # 执行数据填充