Yudhvir Singh
//AUTHENTICATING CLEARANCE...
← BACK TO PROJECTSCLEARANCE: PUBLIC
PROJECT DOSSIER #002

DOCKYARD

Own Your Cloud

READING TIME
DIFFICULTY
Advanced
STATUS
Design — Pre-Implementation
LAST UPDATED
Aug 2026
01

OBJECTIVE

A platform-as-a-service that lets a developer run one command from a project directory and get a live, HTTPS-secured, auto-scaling deployment — with zero manual server work after initial platform setup.

dockyard login → dockyard deploy → public HTTPS URL, with logs, env vars, and rollbacks — no kubectl, Docker, or DNS touched directly.

Why this is hard: Heroku and Vercel make this look trivial precisely because the hard part is hidden — every layer between a Dockerfile and a live HTTPS URL (registry auth, cluster scheduling, TLS issuance, DNS propagation) has its own failure modes, and a PaaS is only as good as its worst-behaved layer. The goal isn't reimplementing Kubernetes; it's hiding it convincingly enough that a developer never needs to know it's there.

02

CONSTRAINTS (NON-GOALS, V1)

  • No multi-cloud portability — targets one cluster type first; abstraction can come later.
  • No billing or usage metering.
  • No serverless/functions-as-a-service model — this platform runs long-lived containers.
03

TECHNICAL DECISIONS

Click a decision to expand it.

The Deployment API (FastAPI) owns auth, validation, and orchestration but never touches Docker or Kubernetes directly — it only writes rows to Postgres and lets Build Workers pick them up. That separation is what makes the worker horizontally scalable and independently deployable.

Workers claim queued deployments with SELECT ... FOR UPDATE SKIP LOCKED — simple, no extra infrastructure, and safe to run more than one worker instance against. Redis/RQ is a later swap only if polling becomes an actual bottleneck.

Native Let's Encrypt integration and dynamic config mean less YAML than Nginx + cert-manager for the same result — every deployment gets HTTPS with zero manual certificates.

Infrastructure-as-code is introduced once manual cluster setup is understood, not before — the whole platform (VPC, cluster, LB, DNS) becomes reproducible via terraform apply after the deploy pipeline already works end to end.

Docker Hub for dev — a self-hosted registry is one more stateful service to operate before the pipeline has even proven itself end to end. Harbor is the rejected-for-now alternative, deliberately deferred to a later phase once registry rate limits or privacy requirements actually force the issue, not before.

Local development targets kind or minikube — free, disposable, no cloud bill for iterating on manifest generation. Production targets EKS. The trade-off: it's two cluster behaviors to keep compatible instead of one, but running a real cloud cluster just to test a Deployment YAML would be slow and expensive for zero benefit at that stage.

04

SYSTEM ARCHITECTURE

Two diagrams. The first is how the platform is organized — its components and who calls whom, independently deployable and independently testable so the build proceeds phase-by-phase without a big-bang integration at the end. The second is what happens to one deployment as it moves through the pipeline.

DIAGRAM 1 — RUNTIME ARCHITECTURE

Boxes are components, lines are who calls whom. Hover a box.

claimpushapply
CLI
$ dockyard deploy
DEPLOYMENT API
Auth + orchestration
POSTGRES
Job queue
BUILD WORKER
Claims + builds
CONTAINER REGISTRY
Docker Hub (dev)
KUBERNETES
Manifest apply
TRAEFIK
Routing + TLS
LIVE URL
project.domain.com

DIAGRAM 2 — DEPLOY STATE MACHINE

The 7 states (§07) a single deployment moves through, and the branch a failure takes instead of silently retrying:

successerror
QUEUED
BUILDING
PUSHING
DEPLOYING
LIVE
FAILED
ROLLED BACK
05

NON-FUNCTIONAL REQUIREMENTS

  • Idempotencyworker job claims use row locking; re-running a claimed job is a no-op.
  • SecurityJWT auth on every route; secrets encrypted at rest via Kubernetes Secrets, not ConfigMaps.
  • Observabilitystructured logs from API + worker; Prometheus metrics on deployments/min and failure rate.
  • Failure isolationone project's failed build must never block the queue for others; per-job timeout enforced.
06

RESULT

Definition of done for v1: a developer with only a Git repo and the Dockyard CLI can go from dockyard login to a public HTTPS URL serving their app — with logs, env vars, and rollbacks — without touching kubectl, Docker, or DNS directly.

07

BY THE NUMBERS

Scope numbers from the design — Dockyard hasn't shipped yet, so these describe what's planned, not measured production results.

12
API ENDPOINTS
7
DEPLOY STATES
13
CLI COMMANDS
15
BUILD PHASES
08

STACK

FastAPI · Docker · Kubernetes · Terraform · Traefik · Prometheus/Grafana · PostgreSQL

09

LESSONS LEARNED (SO FAR)

Dockyard is still pre-implementation, so nothing has broken in production yet — but the first architecture pass didn't survive scoping either, which is the cheaper place for that to happen.

  • The first pass reached for multi-cloud abstraction and a self-hosted registry from day one (§02, §03). Both got cut — targeting one cluster type and Docker Hub first isn't a missing feature, it's the constraint that keeps the first 15 phases actually shippable instead of stuck in infrastructure nobody's using yet.
  • I'd write the failure-state contract (§06 — queued, building, pushing, deploying, live, failed, rolled_back) before any code, not discover it mid-implementation — retrofitting distinguishable failure states onto a pipeline that already conflates them is expensive.
  • I'd resist standing up Terraform (§08, Phase 14) even one phase early — the whole point of sequencing it last is that premature IaC just encodes decisions you haven't actually tested yet.
  • I'd build the rollback path (§08, Phase 12) right after the first successful deploy, not later — a deployment platform without a tested rollback is a platform that will lose someone's production app exactly once.