Symfony on Giant Swarm

Paul Seiffert
5 min readDec 8, 2014

I’ve been playing around with Docker for some while now and what I’ve always missed was a comfortable way of running my containers somewhere in the cloud. “Comfortable” means in this context that I don’t have to care about the machine hosting Docker, the distribution of containers to machines, or connecting containers that run on different machines.

A couple of weeks ago, I got access to the alpha program of a startup that promises to solve these issues for you: Giant Swarm.
Giant Swarm provides a managed cloud you can use via a CLI tool to run your containers on the Swarm. After installing the CLI client, you create a configuration file (`swarm.json`) for your project that describes its services which can be composed from multiple components. A component is basically a set of one or more instances of the same Docker image. With this configuration you can then start these services on the Swarm’s clusters and it will handle all the low-level issues for you.

The Swarm

The Swarm configuration is pretty similar to the one you provide to fig. It describes the components’ Docker images, dependencies between components, ports that should be exposed, and URIs that will be accessible from the internet.

{
“app_name”: “my-app”,
“services”: [{
“service_name”: “webapp”,
“components”: [{
“component_name”: “nginx”,
“image”: “registry.giantswarm.io/seiffert/symfony-nginx”,
“ports”: [ “80/tcp” ],
“domains”: { “myapp.alpha.giantswarm.io”: “80" }
}]
}]
}

This example defines a very simple application that consists of a single service with only one component — a web server.

Once you have created such a description of your application’s components and saved it in a swarm.json file, you can start the application on Giant Swarm:

swarm up

This will register your application at the Swarm and start it up (you can perform these steps separately by executing swarm create swarm.json and swarm start my-app.
You can always check the status of an application using by executing

swarm status my-app

Once the Swarm pulled all images and started the container, you can access it in your browser at myapp.alpha.giantswarm.io.

For more realistic scenarios, you will probably need to run more than one container at once and connect them somehow with each other. This is done by defining the dependencies between components.

{
“app_name”: “my-app”,
“services”: [{
“service_name”: “webapp”,
“components”: [{
“component_name”: “nginx”,
“image”: “registry.giantswarm.io/seiffert/symfony-nginx”,
“ports”: [ “80/tcp” ],
“domains”: { “myapp.alpha.giantswarm.io”: “80" },
“dependencies”: [
{ “name”: “fpm”, “port”: 9000 }
]
},{
“component_name”: “fpm”,
“image”: “registry.giantswarm.io/seiffert/symfony-fpm”,
“ports”: [ “9000/tcp” ]
}]
}]
}

The Swarm will make sure that the containers are started in the correct order and connect them by linking the Docker containers (even across physical machines).

Giant Swarm has a whole bunch of other cool features you should have a look at. This Article however will now focus on explaining a set-up for running Symfony applications on Docker and the Swarm.

Dockerizing Symfony

Running Symfony on Docker isn’t very different from running any other PHP application on Docker. To host a PHP application, you always need to run a web server that passes requests to PHP. Most PHP application’s I have seen in the last years are being hosted on a combination of Nginx and PHP-FPM which is why I chose this set-up for this article, too.

Having identified those two components, we can translate this set-up directly to Docker containers: One running Nginx, the other one running PHP-FPM. Both containers should be configured in a way that runs the respective service in foreground, writing all access and error logs to stdout. The container running PHP needs file system access to the Symfony project’s PHP source code, the one running Nginx to your project’s static assets.

Make

Since typing in Docker commands can result in severe health problems, I like to use make for this. Don’t worry if you’re not familiar with make so far, it’s very intuitive! The make targets I usually define in projects using Docker are for building, pushing, and running Docker containers. Working with Symfony, we can add targets for installing composer dependencies and copying static assets over to the Nginx container’s sources.

For a better understanding you should have a quick look at my demo’s Makefile: https://github.com/seiffert/symfony-swarm/blob/master/Makefile

File System

For the production environment, your container images should contain all the files they need to serve the application. In development however, it is handy if the project files are mounted into the containers as volumes (this way, you don’t have to rebuild your PHP container after every change).

With Docker, you can accomplish this by adding the project files to the image in your Dockerfile and mounting a volume over this directory when running the container on your local machine:

FROM ubuntu:14.04

ADD symfony /opt/symfony
$ docker run -d -v $(pwd)/symfony:/opt/symfony symfony-fpm

Configuring Nginx

Running Nginx in a Docker container is pretty easy. The only things required are the Nginx installation, a configuration file (nginx.conf), and a small script that starts Nginx.

To be able to pass requests to PHP-FPM, Nginx needs to know the other container’s IP which is available as environment variable after linking the two containers. The start script just has to write this IP to the Nginx configuration file.

Configuring PHP-FPM

Creating a container for PHP-FPM also isn’t very hard. Take a standard Ubuntu image, install FPM, configure it, add your source code, and start it up!

When running Symfony, you’ll have to configure file system permissions on the cache and log directories. Also, you need to configure FPM to listen on a TCP port instead of a Unix Socket. (You should always avoid relying on a file system shared between containers!)

Running the Containers

Once you’ve created configurations for the two Docker containers, you can start them (in the demo project this is done by running make run-dev) and work on your application.
Whenever you have reached a point that you want to publish, you should build new Docker images and push them to your registry. Once published, you can use Giant Swarm to run them in the cloud.

This whole set-up is available on GitHub (including the Giant Swarm configuration file swarm.json). If you experience any issues with it, please drop me a line and I’ll have a look at it.

http://symfony.alpha.giantswarm.io/app_dev.php

--

--