如何在Ubuntu 14.04上将Symfony应用程序部署到生产环境中

介绍

Symfony是一个用PHP编写的开源Web框架,适用于构建任何规模的项目。它提供了一个基于可重用组件的精心设计的结构,您可以在其上构建自己的PHP应用程序。

本教程将介绍在Ubuntu 14.04服务器上手动部署基本Symfony应用程序所需的步骤。我们将了解如何正确配置服务器,考虑安全性和性能指标,以便完成准备生产的设置。

准备

在本教程中,您将需要:

  • 运行LAMP或LEMP的全新Ubuntu 14.04 CVM,没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。
  • 一个sudo非root用户。

重要的是要记住,部署是一个非常广泛的主题,因为每个应用程序都有自己的特定需求。为了简单起见,我们将使用使用Symfony构建的示例待办事项应用程序。您可以在GitHub上找到它的源代码。

第一步 - 安装服务器依赖项

在此步骤中,我们将安装服务器依赖项。

首先更新包管理器缓存。

代码语言:javascript
复制
sudo apt-get update

我们需要git检查应用程序文件,在安装应用程序时用acl设置正确的目录权限,以及两个PHP扩展(在命令行输入php5-cli运行PHP和php5-curl运行Symfony )。安装所需的包。

代码语言:javascript
复制
sudo apt-get install git php5-cli php5-curl acl

最后,我们需要composer来下载应用程序依赖项。要在系统范围内安装composer,请运行:

代码语言:javascript
复制
sudo curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer

你现在应该准备好了。

第二步 - 配置MySQL

让我们首先让您的MySQL设置准备好进行生产。对于下一步,您将需要MySQL root 帐户的密码。确保您已安全地设置MySQL。

如果您使用我们的一键单击(LAMP / LEMP),您将在登录到服务器时打印的日期文本消息中找到MySQL root密码。当天的消息内容也可以在/etc/motd.tail文件中找到。

设置默认排序规则和字符集

Symfony建议将数据库的charset和collation设置为utf8。默认情况下,大多数数据库将使用拉丁类型排序规则,这将在检索先前存储在数据库中的数据时产生意外结果,如奇怪的字符和不可读的文本。没有办法在应用程序级别配置它,因此我们需要编辑MySQL配置文件以包含几个定义。

使用您最喜欢的命令行编辑器打开文件/etc/mysql/my.cnf

代码语言:javascript
复制
sudo nano /etc/mysql/my.cnf

现在,找到[mysqld]块。在“ 基本设置”下添加collation-servercharacter-set-server选项。

代码语言:javascript
复制
[mysqld]
#
# * Basic Settings
#
collation-server     = utf8mb4_general_ci # Replaces utf8_general_ci
character-set-server = utf8mb4            # Replaces utf8
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
​
. . .

保存并退出。重启MySQL以使更改生效。

代码语言:javascript
复制
sudo service mysql restart

为应用程序创建用户和数据库

现在我们需要为我们的应用程序创建一个MySQL数据库和用户。

首先,使用MySQL root帐户访问MySQL客户端。

代码语言:javascript
复制
mysql -u root -p

系统会要求您输入密码。这应该与您在运行mysql_secure_installation时使用的密码相同。

现在,创建应用程序数据库。

代码语言:javascript
复制
CREATE DATABASE todo;

输出应如下所示:

代码语言:javascript
复制
Query OK, 1 row affected (0.00 sec)

现在已创建数据库。下一步是创建一个MySQL用户并为他们提供对我们新创建的数据库的访问权限。

代码语言:javascript
复制
CREATE USER 'todo-user'@'localhost' IDENTIFIED BY 'todo-password';

输出应如下所示:

代码语言:javascript
复制
Query OK, 0 rows affected (0.00 sec)

这将创建一个名为todo-user的用户,密码为todo-password。重要的是要注意这些是应该更改的简单示例值,并且您应该为MySQL用户使用更复杂的密码以提高安全性。

我们仍然需要授予此用户对应用程序数据库的正确权限。这可以通过以下方式完成:

代码语言:javascript
复制
GRANT ALL PRIVILEGES ON todo.* TO 'todo-user'@'localhost';

输出应如下所示:

代码语言:javascript
复制
Query OK, 0 rows affected (0.00 sec)

这将授予todo-user用户对todo数据库内所有表的所有权限。要应用此更改,请运行:

代码语言:javascript
复制
FLUSH PRIVILEGES;

输出应如下所示:

代码语言:javascript
复制
Query OK, 0 rows affected (0.00 sec)

要测试一切是否按预期工作,请退出MySQL客户端。

代码语言:javascript
复制
quit;

现在再次登录,这次使用您刚刚创建的新MySQL用户和密码。在此示例中,我们使用用户名todo-user,密码为todo-password

代码语言:javascript
复制
mysql -u todo-user -p

您可以检查此用户有权访问的数据库:

代码语言:javascript
复制
SHOW DATABASES;

输出应如下所示:

代码语言:javascript
复制
Output+--------------------+
| Database           |
+--------------------+
| information_schema |
| todo               |
+--------------------+
2 rows in set (0.00 sec)

这意味着使用正确的权限成功创建了新用户。您应该只看到两个数据库:information_schematodo

您现在可以退出MySQL客户端。

代码语言:javascript
复制
quit;

第三步 - 签出应用程序代码

由于大多数应用程序的独特性,部署是一个广泛的主题,即使我们只考虑Symfony项目。很难概括,因为每个用例都需要非常具体的部署步骤,例如迁移数据库或运行额外的设置命令。

为了简化教程流程,我们将使用Symfony构建基本的演示应用程序。您也可以使用自己的Symfony应用程序,但请记住,您可能必须根据应用程序的需要执行额外的步骤。

我们的应用程序是一个简单的待办事项列表,允许您添加和删除项目,并更改每个项目的状态。待办事项存储在MySQL数据库中。源代码可在GitHub上获得。

我们将使用Git检查应用程序代码。下一步是选择将用作应用程序根目录的位置。稍后,我们将相应地配置Web服务器。对于本教程,我们将使用/var/www/todo-symfony,所以现在创建该目录。

代码语言:javascript
复制
sudo mkdir -p /var/www/todo-symfony

在克隆存储库之前,让我们更改文件夹所有者和组,以便我们能够使用常规用户帐户处理项目文件。用你的sudo非root用户名替换sammy

代码语言:javascript
复制
sudo chown sammy:sammy /var/www/todo-symfony

现在,移动到父目录并克隆应用程序。

代码语言:javascript
复制
cd /var/www
git clone https://github.com/php-demos/todo-symfony.git todo-symfony
OutputCloning into 'todo-symfony'...
remote: Counting objects: 76, done.
remote: Compressing objects: 100% (61/61), done.
remote: Total 76 (delta 6), reused 76 (delta 6), pack-reused 0
Unpacking objects: 100% (76/76), done.
Checking connectivity... done.

第四步 - 修复文件夹权限

应用程序文件现在位于/var/www/todo-symfony ,我们的系统用户所拥有的目录中(在本教程中,我们以sammy为例)。但是,Web服务器用户(通常是www-data)也需要访问这些文件。否则,Web服务器将无法为该应用程序提供服务。除此之外,有两个目录需要特殊的权限安排:app/cacheapp/logs。这些目录应该是系统用户和Web服务器用户都可写的。

我们将使用ACL(访问控制列表)来配置这些特殊权限。ACL为文件和目录提供了更细粒度的访问权限,这是我们设置正确权限同时避免过于宽松的安排所需要的。

首先,我们需要允许用户使用www-data访问应用程序文件夹中的文件。在整个目录中为此用户授予读取+执行权限(rX)。

代码语言:javascript
复制
sudo setfacl -R -m u:www-data:rX todo-symfony

接下来,我们需要为cachelogs文件夹设置特殊权限。将读取+写入+执行权限(rwX)提供给用户www-data,以使Web服务器只能在这些目录中写入。

代码语言:javascript
复制
sudo setfacl -R -m u:www-data:rwX todo-symfony/app/cache todo-symfony/app/logs

最后,我们将定义在app/cacheapp/logs文件夹内创建的所有新文件都遵循我们刚刚定义的相同权限模式,并具有对Web服务器用户的读取,写入和执行权限。这是通过重复我们刚刚运行的setfacl命令来完成的,但这次添加了该-d选项。

代码语言:javascript
复制
sudo setfacl -dR -m u:www-data:rwX todo-symfony/app/cache todo-symfony/app/logs

如果要检查给定目录中当前具有哪些权限,可以使用getfacl

代码语言:javascript
复制
getfacl todo-symfony/app/cache

您应该获得类似于此的输出:

代码语言:javascript
复制
# file: todo-symfony/app/cache
# owner: sammy
# group: sammy
user::rwx
user:www-data:rwx
group::rwx
mask::rwx
other::r-x
default:user::rwx
default:user:www-data:rwx
default:group::rwx
default:mask::rwx
default:other::r-x

从此输出中,您可以看到即使目录app/cache由用户sammy拥有,也有一组用户www-data的权限。默认指令显示在此目录中创建的新文件的权限。

第五步 - 设置应用程序

我们现在已经有了应用程序文件,但是我们仍然需要安装项目依赖项并配置应用程序参数。

Symfony适用于不同环境。默认情况下,它将使用开发设置,这会影响它处理缓存和错误的方式。开发环境具有更广泛和详细的日志,更少的缓存内容,并且以显着的方式展示错误以简化调试。这对于开发应用程序很有用,但对于生产环境来说这不是一个好习惯。

为了调整生产应用程序,我们需要定义一个环境变量,告诉Symfony我们在生产环境中运行应用程序。

代码语言:javascript
复制
export SYMFONY_ENV=prod

接下来,我们需要安装项目依赖项。访问应用程序文件夹并运行composer install

代码语言:javascript
复制
cd todo-symfony
composer install --no-dev --optimize-autoloader

在安装过程结束时,系统会提示您提供一些填充parameters.yml文件的信息。此文件包含应用程序的重要信息,如数据库连接设置。您可以按ENTER以接受所有这些的默认值,但数据库名称,用户名和密码除外。对于那些,请使用您在第二步中创建的值。

代码语言:javascript
复制
Creating the "app/config/parameters.yml" file
Some parameters are missing. Please provide them.
database_host (127.0.0.1): 
database_port (null): 
database_name (symfony): todo
database_user (root): todo-user
database_password (null): todo-password
. . .

安装完成后,我们可以使用console命令doctrine:schema:validate检查数据库连接。

代码语言:javascript
复制
php app/console doctrine:schema:validate

输出应如下所示:

代码语言:javascript
复制
[Mapping]  OK - The mapping files are correct.
[Database] FAIL - The database schema is not in sync with the current mapping file.

OK行表示数据库连接正在运行。FAIL行是预期的,因为我们尚未创建数据库模式,所以让我们接下来这样做:

代码语言:javascript
复制
php app/console doctrine:schema:create

输出应如下所示:

代码语言:javascript
复制
ATTENTION: This operation should not be executed in a production environment.

Creating database schema...
Database schema created successfully!

根据从应用程序实体获得的元数据信息,这将在配置的数据库中创建所有应用程序表。

迁移现有应用程序时,应避免直接使用doctrine:schema:createdoctrine:schema:update命令,而是执行数据库迁移。在我们的示例中,不需要迁移,因为应用程序应该安装一个干净的空数据库。

现在你应该清除缓存。

代码语言:javascript
复制
php app/console cache:clear --env=prod --no-debug

输出应如下所示:

代码语言:javascript
复制
Clearing the cache for the prod environment with debug false

最后,生成应用程序资产。

代码语言:javascript
复制
php app/console assetic:dump --env=prod --no-debug

输出应如下所示:

代码语言:javascript
复制
Dumping all prod assets.
Debug mode is off.

14:02:39 [file+] /var/www/todo-symfony/app/../web/css/app.css
14:02:39 [dir+] /var/www/todo-symfony/app/../web/js
14:02:39 [file+] /var/www/todo-symfony/app/../web/js/app.js

第六步 - 设置Web服务器

剩下要做的唯一事情就是配置Web服务器。这将涉及两个步骤:设置php.ini中的date.timezone指令,并更新默认网站配置文件(在Apache或Nginx上)以便为我们的应用程序提供服务。

我们将看到如何在LEMP和LAMP环境中完成这些步骤。

Nginx + PHP-FPM的配置步骤

让我们从编辑默认文件php.ini开始,定义服务器的时区。这是运行Symfony应用程序的要求,它通常在新服务器安装上被注释掉。

打开文件/etc/php5/fpm/php.ini

代码语言:javascript
复制
sudo nano /etc/php5/fpm/php.ini 

搜索包含的行date.timezone。通过删除;行开头的符号取消注释该指令,并为您的应用程序添加适当的时区。在这个例子中我们将使用Europe/Amsterdam,但您可以选择任何支持的时区。

代码语言:javascript
复制
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = Europe/Amsterdam

保存文件并退出。要应用更改,请重新启动PHP。

代码语言:javascript
复制
sudo service php5-fpm restart

接下来,我们需要将默认网站配置文件替换为为Symfony应用程序提供服务而定制的文件。首先创建当前默认网站配置的备份。

代码语言:javascript
复制
cd /etc/nginx/sites-available
sudo mv default default-bkp

创建一个新文件来替换旧文件。

代码语言:javascript
复制
sudo nano /etc/nginx/sites-available/default

将以下内容粘贴到文件中。不要忘记替换server_name值以反映您的服务器域名或IP地址。

代码语言:javascript
复制
server {
server_name example.com www.example.com your_server_ip;
root /var/www/todo-symfony/web;

location / {
    # try to serve file directly, fallback to app.php
    try_files $uri /app.php$is_args$args;
}

location ~ ^/app\.php(/|$) {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    # Prevents URIs that include the front controller. This will 404:
    # http://domain.tld/app.php/some-path
    # Remove the internal directive to allow URIs like this
    internal;
}

error_log /var/log/nginx/symfony_error.log;
access_log /var/log/nginx/symfony_access.log;

}

保存文件并退出。要应用更改,请重新启动Nginx。

代码语言:javascript
复制
sudo service nginx restart

Apache + PHP5 Web服务器的配置步骤

让我们从编辑默认文件php.ini开始,定义服务器的时区。这是运行Symfony应用程序的要求,它通常在新服务器安装上被注释掉。

打开文件/etc/php5/apache2/php.ini

代码语言:javascript
复制
sudo nano /etc/php5/apache2/php.ini 

搜索包含的行date.timezone。通过删除;行开头的符号取消注释该指令,并为您的应用程序添加适当的时区。在这个例子中我们将使用Europe/Amsterdam,但您可以选择任何支持的时区。

代码语言:javascript
复制
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = Europe/Amsterdam

保存文件并退出。现在我们需要使用自定义的网站配置文件替换默认网站配置文件,以便为Symfony应用程序提供服务。创建当前默认网站配置的备份。

代码语言:javascript
复制
cd /etc/apache2/sites-available
sudo mv 000-default.conf default-bkp.conf

创建一个新文件来替换旧文件。

代码语言:javascript
复制
sudo nano /etc/apache2/sites-available/000-default.conf

将以下内容粘贴到文件中。

代码语言:javascript
复制
<VirtualHost :80>

DocumentRoot /var/www/todo-symfony/web
<Directory /var/www/todo-symfony/web>
AllowOverride None
Order Allow,Deny
Allow from All

<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.
)$ app.php [QSA,L]
</IfModule>
</Directory>

# uncomment the following lines if you install assets as symlinks
# or run into problems when compiling LESS/Sass/CoffeScript assets
# <Directory /var/www/project>
# Options FollowSymlinks
# </Directory>

ErrorLog /var/log/apache2/symfony_error.log
CustomLog /var/log/apache2/symfony_access.log combined
</VirtualHost>

如果您使用域名访问服务器而不仅仅是IP地址,则可以选择定义ServerNameServerAlias值,如下所示。如果没有,您可以省略。

代码语言:javascript
复制
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com

DocumentRoot /var/www/todo-symfony/web
. . .

保存文件并退出。我们还需要为Apache 启用mod_rewrite

代码语言:javascript
复制
sudo a2enmod rewrite

要应用所有更改,请重新启动Apache。

代码语言:javascript
复制
sudo service apache2 restart

第七步 - 访问应用程序

您的服务器应该准备好为演示Symfony应用程序提供服务。在您的浏览器访问http://your_server_ip,您应该看到如下页面:

您可以使用该表单创建新任务并测试应用程序的功能。

结论

将任何应用程序部署到生产环境需要特别注意细节,例如创建具有有限访问权限的专用数据库用户以及在应用程序文件夹上设置正确的目录权限。这些步骤对于提高生产环境中的服务器和应用程序安全性是必需的。在本教程中,我们看到了在Ubuntu 14.04服务器上手动部署基本Symfony应用程序到生产时应采取的具体步骤。

想要了解更多关于Linux的开源信息教程,请前往腾讯云+社区学习更多知识。

参考文献:《How To Deploy a Symfony Application to Production on Ubuntu 14.04》