Deploy a container image
Worked example — deploy an off-the-shelf application (WordPress) as a Coderunner service, with CPU/memory limits and autoscaling replicas.
This walks through deploying WordPress — an application you didn't write, with no Groundfloor-specific code in it — as a Coderunner service. The point isn't WordPress specifically; it's that any application that ships as a container and listens on a port can run the same way. Swap the Dockerfile and env vars for your own image and the rest of this walkthrough still applies.
If you're deploying your own code (not a pre-built image), see Coderunner for the function/job/schedule types instead — those are a better fit for request/response handlers and batch jobs than service.
What you get
- A long-running container, always reachable at a Deployment URL, running behind the Front Door edge proxy
- CPU and memory limits you set
- A min/max replica band the platform autoscales within (this is what "autoscaling" means here — see Resources you control)
- Automatic redeploy-on-failure detection: if your container never becomes ready on its port, the deployment is marked Failed and traffic isn't routed to it
What you don't get (yet)
- No customer-attachable persistent volume. The container's filesystem is ephemeral — anything WordPress writes to local disk (uploads, etc.) is lost on redeploy or a pod restart. Point file storage at Files or an S3-compatible bucket if your image supports it; this walkthrough accepts the limitation for simplicity.
- No managed MySQL/MariaDB. Groundfloor's Managed Databases catalog today is Postgres, Redis, ClickHouse, and Qdrant — no MySQL-family engine. WordPress needs MySQL-compatible storage, so this example points at an external MySQL instance (RDS, Cloud SQL, or one you already run) rather than a Groundfloor-managed one. If your application can use Postgres instead, use a Groundfloor Managed Database and skip this caveat entirely.
Prerequisites
gf login --stage # or --dev / production
gf workspaces use <uuid>An external MySQL-compatible database reachable from your cluster's egress, with a database and user already created for WordPress.
1. Write the Dockerfile
Zip root must contain the Dockerfile — Kaniko builds with --dockerfile=Dockerfile, and language bootstrap does not apply to service workloads.
FROM wordpress:latest
EXPOSE 8080
ENV PORT=8080
# The official image listens on 80 by default; Coderunner requires 8080 (or $PORT).
RUN sed -i 's/Listen 80/Listen 8080/' /etc/apache2/ports.conf \
&& sed -i 's/:80>/:8080>/' /etc/apache2/sites-available/000-default.conf2. Put credentials in Secrets, not the image
Never bake WORDPRESS_DB_PASSWORD into the Dockerfile or the ZIP.
gf secrets set WORDPRESS_DB_PASSWORD3. Deploy
gf deploy --workload-type service \
--runtime node \
--cpu 500m --memory 512Mi \
-e WORDPRESS_DB_HOST=your-mysql-host:3306 \
-e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_NAME=wordpress \
--secret WORDPRESS_DB_PASSWORD--runtimemust still be one of Code Runner's existing language slugs (node,python,go,dotnet,dotnet-script) even though it has no effect on aservicebuild — the build always uses yourDockerfile. Pick any valid slug;nodeis a reasonable default. There's nodockeror generic "container" runtime slug today.gf deployfails fast if the ZIP has no rootDockerfilefor aserviceworkload.
gf deploy does not set replicas. The CLI has --cpu and --memory, but no --min-replicas/--max-replicas flag — the autoscaling band is set from the Customer Portal's deploy dialog (Databases → your coderunner → Deploy), or by calling POST /v1/workspaces/{workspace_id}/coderunners/{id}/deploy directly with minReplicas/maxReplicas in the body (see Coderunners API). After gf deploy finishes the first deploy, set minReplicas: 1 there so the site doesn't cold-start on first load — a fresh coderunner otherwise deploys with the platform default replica count.
4. Verify
gf coderunner status -c <slug>Open the printed Deployment URL — first load runs the WordPress installer. If the deployment shows Failed (status 4), check that your container is actually listening on 8080/PORT and bound to 0.0.0.0, not 127.0.0.1:
gf coderunner logs -c <slug>5. Scale or update later
CPU/memory changes: redeploy with new --cpu/--memory values (CLI), or from the Portal deploy dialog. Replica/autoscaling-band changes: Portal deploy dialog or the deploy API only (see the callout above) — you don't need a new coderunner for either, only for a workload-type change (e.g. service → function).
Related
- Coderunner — the full resource-control surface
- Coderunner overview — architecture
- Managed Databases — for applications that can use Postgres/Redis/ClickHouse/Qdrant instead of an external database
- Front Door — how the Deployment URL is routed
- Secrets — inject-by-reference, never plaintext in the ZIP