在Ubuntu 14.04的生产环境上部署一个Symfony应用
提供:ZStack云计算 前言Symfony是一个使用PHP编写的开源Web框架,它的结构设计精良,组件可复用,适用于大大小小的各类PHP项目开发。本文将在Ubuntu 14.04服务器上部署一个简单的Symfony应用,其中涵盖了服务器的配置以及安全和性能的考虑,以使其适合在生产环境中使用。如果你对Symfony还不熟悉,可以参阅这篇介绍文章。准备工作正式开始之前,你需要准备如下事宜:一个新建的
提供:ZStack云计算
前言
Symfony是一个使用PHP编写的开源Web框架,它的结构设计精良,组件可复用,适用于大大小小的各类PHP项目开发。
本文将在Ubuntu 14.04服务器上部署一个简单的Symfony应用,其中涵盖了服务器的配置以及安全和性能的考虑,以使其适合在生产环境中使用。
如果你对Symfony还不熟悉,可以参阅这篇介绍文章。
准备工作
正式开始之前,你需要准备如下事宜:
应用的部署涉及很多方面,很多地方取决于应用本身的需求。本文使用的应用是Symfony的一个实例todo应用,其源代码可以在Github获取。
步骤1:安装服务器依赖项
先更新一下系统软件管理器缓存:
sudo apt-get update
我们需要使用git
拉取应用代码,需要acl
设置应用路径权限,以及两个PHP扩展,php5-cli
用于在命令行运行PHP,php5-curl
用于运行Symfony。输入如下命令安装软件包:
sudo apt-get install git php5-cli php5-curl acl
最后,我们还需要安装composer
以下载应用依赖项:
sudo curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
步骤2:配置MySQL
现在需要设置MySQL为生产环境做好准备。你需要MySQL root账号的密码,并已经为MySQL做好安全加固(详见LAMP安装教程和LEMP安装教程的步骤2)。
如果你使用一键安装的方式安装LAMP/LEMP,你的MySQL root密码应该出现在服务器登陆信息中(message of the day),该信息内容也可在/etc/motd.tail
文件中查看。
设置默认字符集
Symfony建议将数据库的字符集设置为utf8
。大部分数据库默认使用拉丁类字符集,这可能导致之前存储在数据库中的数据变成乱码。该设置无法在应用层面启用,必须要到MySQL配置中更改。
使用编辑器打开/etc/mysql/my.cnf
文件:
sudo nano /etc/mysql/my.cnf
找到[mysqld]条目,在Basic Settings添加两个选项collation-server
和character-set-server
:
[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
为应用创建一个用户和数据库
首先以root账号登陆MySQL客户端:
mysql -u root -p
输入你之前在运行mysql_secure_installation
做安全加固时输入的密码。
登陆成功后,创建应用数据库todo
:
CREATE DATABASE todo;
Output
Query OK, 1 row affected (0.00 sec)
数据库建立完毕。再创建一个专门用于访问此数据库的MySQL用户:
CREATE USER 'todo-user'@'localhost' IDENTIFIED BY 'todo-password';
Output
Query OK, 0 rows affected (0.00 sec)
如上,新建用户名“todo-user”,登录密码“todo-password”。生产环境中应该使用更不容易猜到的密码。
然后,给该用户设置权限:
GRANT ALL PRIVILEGES ON todo.* TO 'todo-user'@'localhost';
Output
Query OK, 0 rows affected (0.00 sec)
运行如下命令使变更生效:
FLUSH PRIVILEGES;
Output
Query OK, 0 rows affected (0.00 sec)
退出MySQL,准备测试:
quit;
现在使用“todo-user”登陆数据库:
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应用也相当复杂,有些部署需要特定的操作——如数据库迁移或者额外的设置命令,因此我无法描述一种通用的部署方式。
本文部署的应用是一个简单的demo,部署过程相对简单。你在部署自己的应用的时候,可能需要进行更多其他的操作。
本demo是一个简单的todo列表,你可以在里面添加、移除项目并编辑其中的内容。todo项目保存在MySQL数据库中。该项目代码可在GitHub上下载。
接下来我们使用Git来获取该应用的代码。我们将使用/var/www/todo-symfony
这个目录,所以第一步先要创建这个目录:
sudo mkdir -p /var/www/todo-symfony
更改目录的所有者,以在普通用户权限下运行该应用。本教程中的用户名和用户组名均为“sammy”,你需要修改成自己的用户名:
sudo chown sammy:sammy /var/www/todo-symfony
现在,将应用代码通过git clone下载到该目录下:
cd /var/www
git clone https://github.com/php-demos/todo-symfony.git todo-symfony
Output
Cloning 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”所拥有。不过,Web服务器用户(通常是“www-data”)也需要能够访问这些文件,否则Web服务器将无法以该目录下的文件提供服务。此外,还有两个目录app/cache
和app/logs
需要更改权限以开放给系统用户和Web服务器用户。
我们将用ACL(Access Control Lists)进行上述位置的权限配置。使用ACL进行权限管理具有更好的细粒度,精确的控制权限可以避免将多余的权限开放出去。
首先,给“www-data”用户开放代码目录的读权限+执行权限(rX):
sudo setfacl -R -m u:www-data:rX todo-symfony
然后,给“www-data”用户开放cache
和log
目录的读+写+执行权限(rwX):
sudo setfacl -R -m u:www-data:rwX todo-symfony/app/cache todo-symfony/app/logs
最后,将app/cache
和app/logs
目录下所有以后要新建的文件设置相同的权限。这同样使用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”的一些额外权限。default部分代表此目录下新建文件将具有的权限。
步骤5:应用的设置
我们现在已经获取了应用代码,但相关依赖还需要安装,而且还需要配置一些应用参数。
Symfony可以在多种环境下运行。其默认设置是开发环境,该环境会生成更加详细的日志,使用较少的缓存,并且暴露更多的错误信息以方便debug。而这些不是生产环境所需要的。
将运行环境更改为生产环境,可以执行如下命令:
export SYMFONY_ENV=prod
接下来我们安装依赖项。进入项目目录,运行composer install
:
cd todo-symfony
composer install --no-dev --optimize-autoloader
安装完毕之后,composer会要求你提供一些信息以生成parameters.yml
。该文件包含了一些重要配置信息,如数据库连接的参数。大部分参数都可以直接回车接受默认值,但数据库名称(database name)、用户名(username)、password(密码)必须要正确填写(即你在步骤2中输入的内容):
Output
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
. . .
完成后,可以使用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,这是预期之内的,因为我们还没有建立数据库结构(schema)。下面我们来创建schema:
php app/console doctrine:schema:create
Output
ATTENTION: 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
Output
Clearing the cache for the prod environment with debug false
最后,生成应用的资源文件(assets):
php app/console assetic:dump --env=prod --no-debug
Output
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
步骤6:设置Web服务器
The only thing left to do is to configure the web server. This will involve 2 steps: setting thedate.timezone
directive in php.ini
, and updating the default website config file (either on Apache or Nginx) for serving our application.
Web服务器的设置包含两个步骤:设置php.ini
中的date.timezone
条目,以及更新默认的网站配置文件(Apache或Nginx)。
We’ll see how to accomplish these steps on both LEMP and LAMP environments.
Nginx + PHP-FPM 的配置
首先编辑/etc/php5/fpm/php.ini
文件,设置服务器的时区。服务器时区在默认的配置文件中是注解掉的,而Symfony需要这个设置。
sudo nano /etc/php5/fpm/php.ini
找到date.timezone
条目,将其内容前面的分号删除,然后将时区修改为你所在地的时区(本文使用Europe/Amsterdam
时区,你可以从这个页面查找你的所在地时区):
[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:
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的配置
首先还是在/etc/php5/apache2/php.ini
文件中更改时区:
sudo nano /etc/php5/apache2/php.ini
找到date.timezone
条目,将前面的分号删除,并将你自己的时区写入:
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = Europe/Amsterdam
保存退出。现在需要替换Apache的默认网站配置文件。先把原来的文件做一个备份:
cd /etc/apache2/sites-available
sudo mv 000-default.conf default-bkp.conf
创建一个新文件替换老的:
sudo nano /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
,如下:
<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:访问应用
在浏览器里访问服务器的IP或域名,应该可以看到这个页面:
现在可以创建一些todo任务来测试应用的功能。
总结
在生产环境部署应用有很多细节需要注意,比如数据库的用户权限、应用目录的访问权限等,这些安全步骤都是必要的。通过阅读本文,你应该已经了解了在Ubuntu 14.04服务器上部署一个简单的Symfony应用的各个步骤。
本文来源自DigitalOcean Community。英文原文:How To Deploy a Symfony Application to Production on Ubuntu 14.04 by Erika Heidi
翻译:lazycai
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)