Running WordPress locally should be easy. But once you add MySQL, DNS routing, and port mappings, your docker-compose.yml
turns into a patchwork of scripts, hardcoded secrets, and lots of other pieces that could increase developer’s cognitive load. This isn’t just painful to maintain — it becomes a liability when onboarding new developers or scaling across environments.
As platform engineers, we aim to reduce this friction. One way is by using Score, a workload spec that abstracts application configuration from infrastructure. With Score and score-compose
, developers can define what the app needs, and platform engineers define how those needs are fulfilled — no YAML files or hand-edited Compose files required.
In this guide, we’ll walk through deploying WordPress with MySQL, using Score and Docker Compose. The result becomes a portable, declarative local dev setup that just works and is easily reproducible across other runtimes and environments.
You’ll need the following tools installed:
score-compose
We’ll use an existing example repo for this tutorial. Clone it:
git clone https://github.com/victor-ikeme/awesome-score-spec-examples
cd awesome-score-spec-examples/wordpress-mysql
You can test the full deployment immediately using the provided Makefile:
$ make compose-test
Once deployed, your WordPress instance should display an output on your terminal.
To tear down:
$ make compose-down
We begin by writing a Score spec (score.yaml
) that describes the application’s intent: which container to run, what ports it uses, and what dependencies it needs.
apiVersion: score.dev/v1b1
metadata:
name: wordpress
containers:
wordpress:
image: wordpress:latest
variables:
WORDPRESS_DB_HOST: ${resources.db.host}
WORDPRESS_DB_USER: ${resources.db.username}
WORDPRESS_DB_PASSWORD: ${resources.db.password}
WORDPRESS_DB_NAME: ${resources.db.name}
service:
ports:
tcp:
port: 80
targetPort: 80
resources:
db:
type: mysql
This tells Score:
wordpress-abc.localhost
).At this point, we introduce Score provisioners which are small configuration units that helps in translating developer intent into real infrastructure like MySQL containers, DNS routes, and more.
The real power of this system lies in its clear separation of responsibilities between developers and platform engineers.
Your job is to declare what your application needs, not how it’s deployed.
In the score.yaml
file, you request a mysql
resource using:
resources:
db:
type: mysql
Then, you reference the outputs from this resource (like host
, username
, password
, and name
) directly in your container’s environment variables:
variables:
WORDPRESS_DB_HOST: ${resources.db.host}
WORDPRESS_DB_USER: ${resources.db.username}
WORDPRESS_DB_PASSWORD: ${resources.db.password}
WORDPRESS_DB_NAME: ${resources.db.name}
You don’t care whether MySQL is:
You just say: “I need a MySQL database, and I’ll plug in its outputs when you give them to me.”
That’s it. Easy Peasy with score. You move on with your life. 🙌
You’re responsible for fulfilling that developer request — reliably, consistently, and in a way that scales across environments.
You do that by using (or authoring) Score provisioners.
Provisioners are implementation-specific blueprints that tell score-compose
or score-k8s
how to wire up a resource like type: mysql
. You can use:
For example, you could define one provisioner that spins up a Docker container for MySQL locally, and another that connects to an RDS instance in production.
Provisioners can vary across environments — but the developer’s score.yaml
never has to change.
We use the default MySQL default provisioner from the Score community to satisfy our resource needs during local development.
To register them in your project, initialize your local workspace like this:
score-compose init \
--no-sample
This registers:
Now, when you run score-compose generate
, these provisioners kick in — provisioning MySQL behind the scenes and wiring everything together into a Compose-ready docker-compose.yaml
.
With provisioners in place, we generate the Compose configuration from our Score file:
$ score-compose generate score/score.yaml \
--publish 80:wordpress:80
This creates a docker-compose.yaml
with:
To see what resources have been provisioned, we run:
$ score-compose resources list
Sample Output:
Now let’s start everything:
$ docker compose up -d
This boots all the required workloads and dependencies:
wordpress-wordpress-1
— the WordPress container.mysql-mysql-1
— the MySQL database.To confirm:
docker ps
Or view real-time logs:
$ docker compose logs -f
Let’s confirm the app on browser.
Head to:
http://localhost:80
🎉 You should see the WordPress setup screen!
We’ve just deployed WordPress with MySQL using Score and Docker Compose — with no hand-written Compose files or hardcoded secrets.
Key wins:
This is a composable, scalable way to manage local dev environments and move toward platform engineering maturity.
This walkthrough is part of the Awesome Score Spec Examples repo.
⭐️ Star it on GitHub to follow updates and explore more platform-ready workload examples.
Next up Part 2: deploy this same score.yaml
to Kubernetes using score-k8s
.
Join me as I talk shop about internal developer platforms, products, tools, tips and everything in between—new episodes every week!