In an effort to improve my DevOps skills, I’m working to understand how to develop and deploy WordPress sites as a ’12 Factor Application.’
Additionally the Roots team wrote their own notes on ‘The Twelve Factor App’ as it applies to WordPress.
‘The Twelve Factor App’ is a set of principles that a modern project must adhere to.
It establishes rules and guidelines as a set of best practices in an effort to prevent bad things from happening.
- An ‘app’ has one and only one codebase
- Apps with shared code should have them stored as dependent libraries
- A codebase can be deployed many times, in different environment instances (production, staging, development)
- There may be several versions of the same app codebase in different environments.
- There should be a naming convention to differentiate versions within the Codebase repo
- I’ll be using Git Flow for this.
- External dependencies must be explicitly declared and managed by the app
- The app has a dependency declaration manifest
- The app has a dependency isolation tool to execute the dependencies
- No other external libraries should ‘leak’ in.
- Every app environment should be ‘Exact and Exhaustive’ to say the least.
- Don’t rely on implicit existence
- For example, don’t assume a bash script or GNU/Linux binary (curl) will be present on the operating system
- Everything required for the app to run must be explicitly declared.
- Use a packaging system for linking external libraries
- The third party code is not included in your repository
- Ruby has the ‘gem’ system bundler as the isolation tool
- For Ruby the dependency isolation command is ‘> bundle exec‘
- New developers should be able to quickly use the build command to rebuilt the system locally.
- For example on Ruby that build command is ‘> bundle install‘
- Composer is the packaging system for PHP.
- Packagist is the defacto package repository for PHP
- WordPress: This is a new idea to WordPress. Plugins are external dependencies, but not explicitly declared in a manifest.
- WordPress: The WordPress core directory should be a dependency to the entire app.
- WordPress: WPackagist is the current de facto for WordPress packages
- Not supported by WordPress project
- It just mirrors the WordPress.org repos
- WordPress: WordPress needs a lot of help and customization to set up the directory structure correctly.
- (What are the things WordPress needs?) It’s covered in the link below, but what is the TLDR
- WordPress: More reading on Composer
- WordPress: Video on WordPress and Composer
- Different deployment environments will probably have different configurations
- Especially for external 3rd party services
- Configurations are things that are likely to change
- Configurations are NOT things that are needed to configure the app, like the Rails ‘config/routes.rb’ file
- Configurations should not be hardcoded in the code, they should be separate.
- If the codebase could be open-sourced at any moment, without fear of critical keys being exposed to the public, then there is a correct separation of code and configuration.
- Configs should be stored in environmental variables. These are Bash variables on Linux
- WordPress: Some configs should stay in the wp-config.php file, but others should be set in the environment
- WordPress: In the Bedrock set up, config variables are set up in the root .env file.
4. Backing Services
- Databases and other stores are used as ‘attached resources’
- No distinction between local and remote resources
- Simply attached by URL
- Loosely Coupled
- Should be able to swap these resources with only config changes
- Resources should not be hardcoded in the database
- Application code should abstract their connections
- Attach and Detach resources at will
- WordPress: Mostly just concerns MySQL attachment
- WordPress: Very easy, already set up with environmental variables
5. Build, Release, Run
- A codebase is transformed into a deployment in three distinct stages:
- Build: Fetch dependencies and compile binaries and assets
- Release: Combine the build with the env config to create new instance in /releases subdirectory
- Releases have a unique identifier, like a timestamp or version number
- Releases can be stored in a /releases subdirectory, symlinked to the current runtime
- The runtime can then be ‘rolledback’ to a previous release
- WordPress: Build with ‘composer install’ and then compile assets
- WordPress: Can use Capistrano easily for one button deploys
- Apps are stateless processes, they should not share resources with other processes
- Can’t assume that resources will be there
- (I’m a bit lost on all this)
- WordPress: Uploads and Sessions
- More Reading: Shared Nothing Architecture
7. Port Binding
- An app’s service should run standalone and be tied to a port
- Something Something Horizontal Scaling Something
- App processes should be able to be started and stopped at a moments notice
- Processes should end gracefully when given SIGTERM
- WordPress: Seems well managed by nginx and PHP-FPM
10. Dev/Prod Parity
- Gaps appear between codebase versions; keep it as similar as possible
- Time Gap
- Personnel Gap
- Tool Gap
- The goal is Continuous Deployment
- WordPress: User Vagrant
- Logs are event streams
- WordPress: WordPress doesn’t offer great logs
- WordPress: nginx and php logs are not the same thing
12. Admin Processes
- Run code admin processes as a one time process
- For example, when upgrading the database using rake db:migrate
- Admin code should ship with codebase
- WordPress: Use wp-cli