如何在Ubuntu14.04上将Symfony应用程序部署到生产环境
介绍
Symfony 是一个用 PHP 编写的开源 Web 框架,适用于构建任何规模的项目。 它提供了一个基于可重用组件的精心设计的结构,您可以在此基础上构建自己的 PHP 应用程序。
本教程将介绍在 Ubuntu 14.04 服务器上手动部署基本 Symfony 应用程序所需的步骤。 我们将了解如何正确配置服务器,同时考虑安全性和性能措施,以完成可用于生产的设置。
如果您正在寻找有关 Symfony 的介绍性教程,您可以阅读 如何在 Ubuntu 14.04 上安装和开始使用 Symfony。
先决条件
对于本教程,您将需要:
- 运行 LAMP 或 LEMP 的全新 Ubuntu 14.04 Droplet
- 一个sudo非root用户,可以按照Initial Server Setup教程进行设置
重要的是要记住,部署是一个非常广泛的主题,因为每个应用程序都有自己的特定需求。 为了简单起见,我们将使用一个使用 Symfony 构建的示例待办事项应用程序。 你可以在 GitHub 上找到它的源代码。
第 1 步 — 安装服务器依赖项
在这一步中,我们将安装服务器依赖项。
首先更新包管理器缓存。
sudo apt-get update
我们需要 git
来检查应用程序文件,acl
来在安装应用程序时设置正确的目录权限,以及两个 PHP 扩展(php5-cli
来运行 PHP Symfony 的命令行和 php5-curl
)。 安装所需的软件包。
sudo apt-get install git php5-cli php5-curl acl
最后,我们需要 composer
来下载应用程序依赖项。 要在系统范围内安装 composer
,请运行:
sudo curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
你现在应该准备好了。
第 2 步 — 配置 MySQL
让我们首先让您的 MySQL 设置为生产做好准备。 对于下一步,您将需要 root MySQL 帐户的密码。 确保您已安全地设置 MySQL(如 LAMP 和 LEMP 教程的第 2 步中所述)。
如果您使用我们的一键式(LAMP / LEMP),您将在登录服务器时打印的当天文本消息中找到 MySQL root 密码。 当天消息的内容也可以在文件 /etc/motd.tail
中找到。
设置默认排序规则和字符集
Symfony 建议将数据库的字符集和排序规则设置为 utf8
。 大多数数据库默认会使用拉丁类型排序规则,这会在检索之前存储在数据库中的数据时导致意外结果,例如奇怪的字符和不可读的文本。 无法在应用程序级别进行配置,因此我们需要编辑 MySQL 配置文件以包含几个定义。
使用您喜欢的命令行编辑器打开文件 /etc/mysql/my.cnf
。
sudo nano /etc/mysql/my.cnf
现在,找到 [mysqld] 块。 在基本设置下添加collation-server
和character-set-server
选项。
/etc/mysql/my.cnf
[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 以使更改生效。
sudo service mysql restart
为应用程序创建用户和数据库
现在我们需要为我们的应用程序创建一个 MySQL 数据库和一个用户。
首先,使用 MySQL root 帐户访问 MySQL 客户端。
mysql -u root -p
您将被要求输入密码。 这应该与您在运行 mysql_secure_installation
时使用的密码相同。
现在,创建应用程序数据库。
CREATE DATABASE todo;
OutputQuery OK, 1 row affected (0.00 sec)
数据库现已创建。 下一步是创建一个 MySQL 用户并为他们提供对我们新创建的数据库的访问权限。
CREATE USER 'todo-user'@'localhost' IDENTIFIED BY 'todo-password';
OutputQuery OK, 0 rows affected (0.00 sec)
这将创建一个名为 todo-user 的用户,密码为 todo-password。 重要的是要注意这些是应该更改的简单示例值,您应该为 MySQL 用户使用更复杂的密码以提高安全性。
我们仍然需要授予该用户对我们的应用程序数据库的正确权限。 这可以通过以下方式完成:
GRANT ALL PRIVILEGES ON todo.* TO 'todo-user'@'localhost';
OutputQuery OK, 0 rows affected (0.00 sec)
这将授予 todo-user 用户对 todo
数据库内所有表的所有权限。 要应用更改,请运行:
FLUSH PRIVILEGES;
OutputQuery OK, 0 rows affected (0.00 sec)
要测试一切是否按预期工作,请退出 MySQL 客户端。
quit;
现在再次登录,这次使用您刚刚创建的新 MySQL 用户和密码。 在此示例中,我们使用用户名 todo-user,密码为 todo-password。
mysql -u todo-user -p
您可以检查此用户可以访问哪些数据库:
SHOW DATABASES;
输出应如下所示:
Output+--------------------+ | Database | +--------------------+ | information_schema | | todo | +--------------------+ 2 rows in set (0.00 sec)
这意味着新用户已成功创建并具有正确的权限。 您应该只会看到两个数据库:information_schema
和 todo
。
您现在可以退出 MySQL 客户端。
quit;
第 3 步 — 检查应用程序代码
由于大多数应用程序的独特性,部署是一个广泛的主题,即使我们只考虑 Symfony 项目。 很难一概而论,因为每个用例都可能需要非常具体的部署步骤,例如迁移数据库或运行额外的设置命令。
为了简化教程流程,我们将使用一个用 Symfony 构建的基本演示应用程序。 您也可以使用自己的 Symfony 应用程序,但请记住,根据您的应用程序需要,您可能需要执行额外的步骤。
我们的应用程序是一个简单的待办事项列表,允许您添加和删除项目,并更改每个项目的状态。 待办事项存储在 MySQL 数据库中。 源代码可在 GitHub 上获得。
我们将使用 Git 来检查应用程序代码。 下一步是选择一个位置作为我们的应用程序根目录。 稍后,我们将相应地配置 Web 服务器。 对于本教程,我们将使用 /var/www/todo-symfony
,因此现在创建该目录。
sudo mkdir -p /var/www/todo-symfony
在克隆存储库之前,让我们更改文件夹所有者和组,以便我们能够使用我们的常规用户帐户处理项目文件。 将 sammy 替换为您的 sudo 非 root 用户名。
sudo chown sammy:sammy /var/www/todo-symfony
现在,移动到父目录并克隆应用程序。
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.
第 4 步 — 修复文件夹权限
应用程序文件现在位于 /var/www/todo-symfony
,这是我们的 系统用户 拥有的目录(在本教程中,我们使用 sammy 作为示例)。 但是, 网络服务器用户(通常是 www-data)也需要访问这些文件。 否则,Web 服务器将无法为应用程序提供服务。 除此之外,还有两个目录需要特殊的权限安排:app/cache
和 app/logs
。 这些目录应该可由系统用户和 Web 服务器用户写入。
我们将使用 ACL(访问控制列表)来配置这些特殊权限。 ACL 为文件和目录启用了更细粒度的访问权限,这是我们在设置正确权限的同时避免过于宽松的安排所需要的。
首先,我们需要允许用户 www-data 访问应用程序文件夹中的文件。 在整个目录中授予该用户 读取 + 执行 权限 (rX)。
sudo setfacl -R -m u:www-data:rX todo-symfony
接下来,我们需要为 cache
和 logs
文件夹设置特殊权限。 为用户 www-data 授予 read + write + execute 权限 (rwX),以使 Web 服务器只能在这些目录中写入。
sudo setfacl -R -m u:www-data:rwX todo-symfony/app/cache todo-symfony/app/logs
最后,我们将定义在 app/cache
和 app/logs
文件夹中创建的所有新文件都遵循我们刚刚定义的相同权限架构,对 Web 服务器用户具有读取、写入和执行权限。 这是通过重复我们刚刚运行的 setfacl
命令来完成的,但这次添加了 -d
选项。
sudo setfacl -dR -m u:www-data:rwX todo-symfony/app/cache todo-symfony/app/logs
如果要检查给定目录中当前存在哪些权限,可以使用 getfacl
。
getfacl todo-symfony/app/cache
你应该得到类似这样的输出:
Output# 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 还拥有一组额外的权限。 默认指令显示在此目录中创建的新文件将具有哪些权限。
第 5 步 — 设置应用程序
我们现在已经有了应用程序文件,但我们仍然需要安装项目依赖项并配置应用程序参数。
Symfony 可以在不同的环境中正常工作。 默认情况下,它将使用开发设置,这会影响它处理缓存和错误的方式。 开发环境有更广泛和详细的日志,更少的缓存内容,并且错误以突出的方式展示以简化调试。 这对于开发应用程序很有用,但对于生产环境来说并不是一个好的做法。
要为生产环境调整应用程序,我们需要定义一个环境变量,告诉 Symfony 我们正在生产环境中运行应用程序。
export SYMFONY_ENV=prod
接下来,我们需要安装项目依赖项。 访问应用程序文件夹并运行 composer install
。
cd todo-symfony composer install --no-dev --optimize-autoloader
在安装过程结束时,系统会提示您提供一些将填充 parameters.yml
文件的信息。 此文件包含应用程序的重要信息,例如数据库连接设置。 您可以按 ENTER
接受所有这些的默认值,但数据库名称、用户名和密码除外。 对于这些,请使用您在 步骤 2 中创建的值。
OutputCreating 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 . . .
安装完成后,我们可以使用 doctrine:schema:validate
控制台命令检查数据库连接。
php app/console doctrine:schema:validate
Output[Mapping] OK - The mapping files are correct. [Database] FAIL - The database schema is not in sync with the current mapping file.
OK 线表示数据库连接正常。 FAIL 行是预期的,因为我们还没有创建数据库模式,所以接下来让我们这样做:
php app/console doctrine:schema:create
OutputATTENTION: This operation should not be executed in a production environment. Creating database schema... Database schema created successfully!
这将根据从应用程序实体获得的元数据信息,在配置的数据库中创建所有应用程序表。
迁移现有应用程序时,应避免直接使用 doctrine:schema:create
和 doctrine:schema:update
命令,而是执行 数据库迁移。 在我们的例子中,不需要迁移,因为应用程序应该安装一个干净的空数据库。
现在您应该清除缓存。
php app/console cache:clear --env=prod --no-debug
OutputClearing the cache for the prod environment with debug false
最后,生成应用程序资产。
php app/console assetic:dump --env=prod --no-debug
OutputDumping 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
第 6 步 — 设置 Web 服务器
剩下要做的就是配置 Web 服务器。 这将涉及 2 个步骤:在 php.ini
中设置 date.timezone
指令,并更新默认网站配置文件(在 Apache 或 Nginx 上)以服务于我们的应用程序。
我们将看到如何在 LEMP 和 LAMP 环境中完成这些步骤。
Nginx + PHP-FPM的配置步骤
让我们首先编辑默认的 php.ini
文件来定义服务器的时区。 这是运行 Symfony 应用程序的要求,通常在全新服务器安装时被注释掉。
打开文件 /etc/php5/fpm/php.ini
。
sudo nano /etc/php5/fpm/php.ini
搜索包含 date.timezone
的行。 通过删除行首的 ;
符号来取消注释指令,并为您的应用程序添加适当的时区。 在此示例中,我们将使用 Europe/Amsterdam
,但您可以选择任何 支持的时区 。
修改/etc/php5/fpm/php.ini
[Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone date.timezone = Europe/Amsterdam
保存文件并退出。 要应用更改,请重新启动 PHP。
sudo service php5-fpm restart
接下来,我们需要将默认的网站配置文件替换为为 Symfony 应用程序服务而定制的配置文件。 首先创建当前默认网站配置的备份。
cd /etc/nginx/sites-available sudo mv default default-bkp
创建一个新文件来替换旧文件。
sudo nano /etc/nginx/sites-available/default
将以下内容粘贴到文件中。 不要忘记替换 server_name
值以反映您的服务器域名或 IP 地址。
/etc/nginx/sites-available/default
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。
sudo service nginx restart
Apache + PHP5 Web 服务器的配置步骤
让我们首先编辑默认的 php.ini
文件来定义服务器的时区。 这是运行 Symfony 应用程序的要求,通常在全新服务器安装时被注释掉。
打开文件/etc/php5/apache2/php.ini
:
sudo nano /etc/php5/apache2/php.ini
搜索包含 date.timezone
的行。 通过删除行首的 ;
符号来取消注释指令,并为您的应用程序添加适当的时区。 在此示例中,我们将使用 Europe/Amsterdam
,但您可以选择任何 支持的时区 。
修改/etc/php5/fpm/php.ini
[Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone date.timezone = Europe/Amsterdam
保存文件并退出。 现在我们需要用自定义的替换默认的网站配置文件,为 Symfony 应用程序提供服务。 创建当前默认网站配置的备份。
cd /etc/apache2/sites-available sudo mv 000-default.conf default-bkp.conf
创建一个新文件来替换旧文件。
sudo nano /etc/apache2/sites-available/000-default.conf
将以下内容粘贴到文件中。
/etc/apache2/sites-available/000-default.conf
<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 地址来访问您的服务器,您可以选择定义 ServerName
和 ServerAlias
值,如下所示。 如果没有,您可以省略它们。
/etc/apache2/sites-available/000-default.conf
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com DocumentRoot /var/www/todo-symfony/web . . .
保存文件并退出。 我们还需要为 Apache 启用 mod_rewrite
。
sudo a2enmod rewrite
要应用所有更改,请重新启动 Apache。
sudo service apache2 restart
第 7 步 — 访问应用程序
您的服务器应该准备好为演示 Symfony 应用程序提供服务。 在浏览器中访问 http://your_server_ip
,您应该会看到如下页面:
您可以使用该表单来创建新任务并测试应用程序的功能。
结论
将任何应用程序部署到生产环境需要特别注意细节,例如创建具有有限访问权限的专用数据库用户以及在应用程序文件夹上设置正确的目录权限。 这些步骤对于提高生产环境中的服务器和应用程序安全性是必要的。 在本教程中,我们看到了在 Ubuntu 14.04 服务器上手动将基本 Symfony 应用程序部署到生产环境中应采取的具体步骤。