提供:ZStack云计算

前言

Symfony是一个使用PHP编写的开源Web框架,它的结构设计精良,组件可复用,适用于大大小小的各类PHP项目开发。

本文将在Ubuntu 14.04服务器上部署一个简单的Symfony应用,其中涵盖了服务器的配置以及安全和性能的考虑,以使其适合在生产环境中使用。

如果你对Symfony还不熟悉,可以参阅这篇介绍文章

准备工作

正式开始之前,你需要准备如下事宜:

  • 一个新建的Ubuntu 14.04云主机,运行LAMPLEMP堆栈
  • 一个具有sudo权限的非root用户(设置方法见这个教程

应用的部署涉及很多方面,很多地方取决于应用本身的需求。本文使用的应用是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-servercharacter-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_schematodo这两个数据库。

现在可以退出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/cacheapp/logs需要更改权限以开放给系统用户和Web服务器用户。

我们将用ACL(Access Control Lists)进行上述位置的权限配置。使用ACL进行权限管理具有更好的细粒度,精确的控制权限可以避免将多余的权限开放出去。

首先,给“www-data”用户开放代码目录的读权限+执行权限(rX):

sudo setfacl -R -m u:www-data:rX todo-symfony

然后,给“www-data”用户开放cachelog目录的读+写+执行权限(rwX):

sudo setfacl -R -m u:www-data:rwX todo-symfony/app/cache todo-symfony/app/logs

最后,将app/cacheapp/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:createdoctrine: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地址访问网站,可以定义ServerNameServerAlias,如下:

<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或域名,应该可以看到这个页面:

Symfony To-Do App Preview

现在可以创建一些todo任务来测试应用的功能。

总结

在生产环境部署应用有很多细节需要注意,比如数据库的用户权限、应用目录的访问权限等,这些安全步骤都是必要的。通过阅读本文,你应该已经了解了在Ubuntu 14.04服务器上部署一个简单的Symfony应用的各个步骤。

本文来源自DigitalOcean Community。英文原文:How To Deploy a Symfony Application to Production on Ubuntu 14.04 by Erika Heidi

翻译:lazycai

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐