Build Platforms Daily

Part 1: Deploy WordPress with MySQL via Score and Docker Compose

By Victor Ikeme on Jun 10, 2025
Deploying WordPress with Score and Docker Compose

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.

What You Will Learn

  • How to define a WordPress workload using Score.
  • How to request MySQL resources declaratively.
  • How platform engineers fulfill these resources via provisioners.
  • How to generate a full Compose setup from Score.

Table of Contents

Prerequisites

You’ll need the following tools installed:

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

Quick Start

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

1. Define the WordPress Workload with Score

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:

  • The app uses the WordPress container.
  • It needs a MySQL database.
  • It wants to be reachable via a DNS-backed route (e.g. wordpress-abc.localhost).
  • No runtime details are hardcoded — just the app’s intent.

2. Initiliaze Project and Register Score Provisioners for MySQL and DNS

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.

2.1 As a Developer

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:

  • Deployed via Docker Compose, Kubernetes, or some managed cloud service
  • Using custom volume mounts or secrets
  • Version 5.7 or 8.0

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. 🙌

2.2 As a Platform Engineer

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.

2.3 In This Guide

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:

  • A MySQL provisioner that launches a ready-to-use MySQL container with autogenerated credentials.

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.

3. Generate Docker Compose Files from Score

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:

  • A WordPress container.
  • A MySQL container.
  • Volumes for persistence.

To see what resources have been provisioned, we run:

$ score-compose resources list

Sample Output:

4. Launch WordPress with Docker Compose

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

5. Confirm our WordPress Deployment

Let’s confirm the app on browser.

Head to:

http://localhost:80

🎉 You should see the WordPress setup screen!

Summary

We’ve just deployed WordPress with MySQL using Score and Docker Compose — with no hand-written Compose files or hardcoded secrets.

Key wins:

  • Developers focus on what the app needs (MySQL, port 80).
  • Platform engineers define how to fulfill those needs (via provisioners).
  • The same spec can run on Docker Compose, Kubernetes, or Humanitec — without rewriting.

This is a composable, scalable way to manage local dev environments and move toward platform engineering maturity.

Contribute to the Awesome Score Spec

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.

Listen to my Podcasts

Join me as I talk shop about internal developer platforms, products, tools, tips and everything in between—new episodes every week!

© Copyright 2025 by Build Platforms Daily. Built with ♥ by Victor Ikeme.