Customizing Symfony API Platform for simpler deployments

by Sebastian Kurfürst on 06.04.2020

I've recently tried out API Platform - a REST and GraphQL Framework based on Symfony and React - and I am extremely happy with using it so far. There are some details, which I like to change from the default API Platform configuration, so that's what I'll blog here about.

What is API Platform?

API Platform is two things:

a symfony based library for creating powerful REST and GraphQL APIs based on simple model annotations

an Application Template which contains:

the PHP server for the APIs

a placeholder client based on create-react-app, which can already talk to the APIs

a server-push mechanism so that updates can be pushed from the server to the clients based on Server-Sent Events: All is based on mercure.rocks

a performance optimizer for eagerly pushing related API data to clients based on HTTP/2: This is called vulcain.

an optional Varnish cache.

A docker-compose setup for all of the above.

All of the above parts can be easily enabled and disabled.

Additionally, API Platform has great documentation to get up and running, and for many common use cases.

For our scenarios, we customized the API platform deployment a bit - and we released a set of patches on GitHub which can be simply applied to the default API-Platform template which do the necessary adjustments.

A more coarse-grained deployment approach

By default, an API Platform production deployment consists of 4-6 different containers, which need to be connected together. For big deployments, that's definitely a great setup. However, for us, we often have low-traffic APIs, where we want to develop and deploy as easily as possible. Thus, we are a big fan of reducing the number of parts to-be-deployed, using fewer, but bigger, docker containers.

The following sections explain what needs to be changed for a good experience with deploying the application as a "monolith".

Making the API available in a nested server path

By default, the HTTP API is available in the root of the server. For API-first projects, this is fine; however, in our case we often want to show a UI at the server root; and move the API a bit further down.

I've experimented a lot on how to move the nested server path, trying all sorts of Nginx configuration to make this work. Ultimately, I could not make it reliably work just with Nginx configuration; thus our approach now is to re-configure the Symfony routes a bit, and tweaking the entrypoint URLs for Admin and the Client.

Towards a single container in production

For production, we want to deploy only a single container with the full application. For making Development and Production as similar as possible, we need to bundle the Nginx and PHP containers together, optionally with including Vulcain as well.