We removed our free Sandbox April 25th.
You can read more on our blog.

PHP & PHP Worker

Note

CLI Command examples on this page are always provided without the --application (shorthand -A) argument, assuming you’re running these commands in a connected folder (at creation or using the dotcloud connect command). For more details on connected folders, see Migrating to the CLI 0.9.

The PHP service can host any kind of PHP5 based website: - Frameworks like Symfony or CakePHP, - Content Management Systems like Drupal or Joomla, WordPress or PHPBB, - and of course custom-tailored applications.

Basic Use

Let’s assume that you are building a dotCloud application called “ramen”. For the sake of simplicity, we will also assume that everything related to this application is located in a directory called “ramen-on-dotcloud”.

Let’s setup our environment:

mkdir ramen-on-dotcloud
cd ramen-on-dotcloud
dotcloud create ramen

A dotCloud application is described by a Build File (dotcloud.yml), which is a simple YAML file named “dotcloud.yml” located in our “ramen-on-dotcloud” directory. To add a new service to our app, we just add the following lines to “ramen-on-dotcloud/dotcloud.yml”:

www:
  type: php
  approot: hellophp

Our PHP code should be in the “hellophp” directory:

mkdir ramen-on-dotcloud/hellophp

Let’s create a very minimal (but informative!) “index.php” file here:

<?php phpinfo(); ?>

We can now push our application to dotCloud:

dotcloud push

URLs will be generated for each web service in our application. Open your browser to see your new service in action!

If you want to attach a better URL to your application, read the Custom Domains documentation.

The PHP Stack

You may have already heard about the “LAMP stack”. LAMP is an acronym that stands for Linux, Apache, MySQL, PHP. This software stack is the “engine” that runs the vast majority of PHP-based websites.

dotCloud uses a slightly different stack:

  • we use Nginx instead of Apache;
  • you can use MySQL, but also other SQL engines like PostgreSQL, and “NoSQL” databases like Redis or MongoDB.

Nginx

dotCloud relies on Nginx and Fast-CGI to forward PHP requests to PHP-FPM:

                   ╭───────╮                      ╭─────────╮
                   │       │                      │         │ ┌ - PHP Worker
   HTTP Requests ⇒ │ Nginx ╞══════ Fast-CGI ══════╡ PHP─FPM ├─┼ - PHP Worker
                   │       │                      │         │ └ - …
                   ╰───────╯                      ╰─────────╯

This setup has several advantages:

  • the HTTP server and the PHP interpreter are decoupled: that means that the web server does not have to load the PHP interpreter to serve static assets (images, JS, CSS...), thus saving great amounts of memory;
  • Nginx is well-known to be very fast at serving static files;
  • instead of using .htaccess files, Nginx loads its whole configuration at startup time; this is much more efficient, because the .htaccess mechanism incurs configuration file lookups and parsings for each HTTP request and for each directory leading to the requested file;
  • if you are an Apache expert, you might be confused at first by Nginx configuration syntax; however, after testing both, a lot of people find that Nginx is more flexible, and that complex Apache RewriteRule directives will often be expressed in a simpler way with Nginx syntax.

You will find ready to use Nginx rewrite and access rules for most common use cases (https, basic authentication...) and frameworks in the Nginx guide and in the tutorials.

Any Database

dotCloud let you choose the kind of database you want to use: it can be MySQL, MySQL, PostgreSQL and PostGIS or the document oriented database MongoDB. You can also use the advanced key-value store Redis.

Databases are not shared. If you use a MySQL service, you will have your own MySQL server, with access to the MySQL root account and all its privileges.

Databases instances are always separated from the PHP instances. This means that your database server will never be “localhost”. This separation is mandatory to allow application scaling, since it allows us to place databases and PHP instances on different physical machines.

Layout of a PHP Instance

The following tree view will give you a clear overview of the file layout of your code, after you push it to the dotCloud PHP service:

home/
└── dotcloud/
    ├── current/
    │   ├── dotcloud.yml     # Your code lives here: /home/dotcloud/current/
    │   ├── fastcgi.conf     # Optional FastCGI parameters
    │   ├── index.php        # Your application code
    │   ├── nginx.conf       # Optional Nginx configuration (e.g: rewrite rules)
    │   ├── php.ini          # Optional configuration directive for PHP
    │   ├── postinstall*     # Optional post installation script
    │   └── supervisord.conf # Optional background processes configuration
    ├── environment.json     # Hold informations on your stack and your environment variables
    └── environment.yaml     # Same thing but in YAML

If you use an approot, then the ~/current directory will actually point to a subdirectory of your application and the whole application tree will be under ~/code. This way, relative includes in your application (e.g: ../libs/mylib.php) will remain valid.

Running Background Processes and Periodic Tasks

Our PHP services can run background processes (using Supervisor) and periodic tasks (using cron). This is covered extensively in two guides:

You can run background processes on the same service as your web pages (i.e. on the php service), but you are strongly encouraged to run them on a dedicated php-worker service, as shown in the following Build File:

www:
  type: php

daemons:
  type: php-worker

This will avoid any inconvenient interaction between your web processes and your background processes. It will allow to scale both services separately, and make sure that one service resource usage (CPU/RAM) will not impair the other one.

Connect to the Services in your Stack

To connect to your database, mail server or any service in your stack you will need to know where it lives, on which port, you will also certainly need to know the right username and password.

All this information can be found in the Environment File: environment.json (or environment.yaml, if you prefer the YAML format).

Installing Additional PHP Packages

If the PHP library or extension you want is not installed by default, you can install it using PEAR or PECL with a requirements list in your dotcloud.yml:

www:
  type: php
  requirements:
    - mongo-1.2.2
    - oauth
    - channel://pear.amazonwebservices.com/sdk

You can also use this mechanism to get newer versions of the pre-installed extensions (e.g: apc).

If for some reason, you want to check installed (or installable) packages with pear or pecl, feel free to do it using the SSH access to your service:

dotcloud run www
pear list -a

Configuring PHP

If you need to set PHP options, you can create a file named php.ini in your application’s top-level directory. This file is included after all other PHP directives, so you can override anything you need.

For example, if you want to display all errors (very convenient during development to make sure that you spot even the slightest warnings and notices):

[PHP]
error_reporting = E_ALL
display_errors = On

By default, dotCloud enables APC (an extension which caches PHP opcodes for your pages; it reduces CPU and execution time, at the expense of some RAM). Some applications (notably, installation wizards like the one of Drupal, which generate PHP files containing the application configuration) can be incompatible with APC. If you want to install such an application, or if you want to disable APC for any reason, you can do it with the following php.ini file:

[apc]
apc.enabled = 0

Note that you can generally re-enable APC once you have gone through the installation wizard.

Configuring Nginx

You can include your own Nginx configuration (e.g rewrite rules, access, control, authentication...) in a file called nginx.conf at the root of your application. For those of you used to Apache, you can think of nginx.conf as a global .htaccess.

Nginx is covered in detail in the Nginx guide. Below are small sections that covers some PHP specifics details.

Note

Your Nginx configuration is included almost on the top of the server block. That means that you can override most of our default Nginx configuration including the location block that handles PHP requests.

Denying Access to Files

It is a best practice to deny direct access to your PHP libraries or framework. That will prevent any side effect triggered by their unexpected execution. Here is a sample nginx.conf file to achieve this:

location ~ /system/.* {
    deny all;
}

location ~ /application/.* {
    deny all;
}

This will completely deny access to the /system and /application directories in your application.

MVC Frameworks

A lot of PHP frameworks and applications require a custom Apache .htaccess configuration file to enable “pretty URLs” (that’s the name used by WordPress to designate this feature).

Without “pretty URLs”, you will access your content with URLs like http://myapp/index.php/blogpost/2011/06/23/what-pretty-urls or http://myapp/index.php?node=451 instead of http://myapp/what-pretty-url.

To enable them, it is generally sufficient to create a nginx.conf file at the root of your PHP code, containing the following line:

try_files $uri $uri/ /index.php?$args;

As surprising as it might seem, this single line will replace multiple RewriteCond and RewriteRule directives. It has been verified to work with WordPress, Drupal, CakePHP, and others. If your favorite application or framework does not work with it, contact our support about it!

Configuring FastCGI

You can define additional FastCGI parameters in a file called fastcgi.conf at the root of your application.

One common use-case is to define an extra variable that will be available in $_SERVER from your PHP code; e.g.:

fastcgi_param ENVIRONMENT production;

Check out the FastCGI Nginx wiki page for a list of more advanced configuration options.

Caveats

For improved performance, the PHP service uses APC, which caches pre-compiled version of your PHP files. However, that means that if you modify the PHP files while the service is running, or if you do things like PHP code generation, you will see strange results. This is notably the case with a few “setup wizards”, which will ask you a few questions about your setup (database setup, login, and so on) and generate a config.php file for you on the server. If at the end of such a wizard, you are taken back to the beginning and it asks you all the questions over again, you probably need to disable APC, at least during the setup.

See Also

You might want to read our tutorials related to PHP:

Or third-party documentations: