Customizing Symfony API Platform for simpler deployments
I am extremely happy with using it so far and there are some details, which I like to improve 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
- an admin interface based on react-admin (and create-react-app)
- 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.
- This is done with this patch (02_api_subdirectory).
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.
- Patch: combine nginx and PHP.
- Patch: disable vulcain, mercure and varnish as extra containers
- Patch: add one-container production build for combining frontend and API
- (optional) Patch: re-add mercure hub to single container
- (optional) Patch: re-add vulcain to single container
What are your experiences with API Platform? Reach out on Twitter to tell us!