Skip to main content
DevOps

From Git Push to Live Website

9 min read

Shipping software answers two questions: is the code correct? and does it run in production? Split those into separate tools — CI validates, Docker packages, a host runs.

Vocabulary

Station Tool Job
Validate GitHub Actions / GitLab CI Lint, test, typecheck on every push
Package Docker Same runnable image everywhere
Run Railway / Fly.io / Render Host container, attach DB, set env vars

CI does not deploy. The host does not skip tests.

Steps

Step 1 — CI on every push

A workflow file triggers on push and pull request. It installs deps, generates the Prisma client, and runs tests:

yaml

The dummy DATABASE_URL exists only so prisma generate succeeds — CI does not need a live database.

Step 2 — Build a Docker image

Multi-stage Dockerfile: install deps, build app, copy only what the runner needs:

dockerfile

Build locally: docker build -t myapp .

Step 3 — Start production with migrations

The startup script runs migrations before serving:

sh

Step 4 — Deploy to a host

Connect your repo to Railway (or similar). Set environment variables in the dashboard:

  • DATABASE_URL — from a managed Postgres plugin
  • BASE_URL — your public domain (https://yoursite.com)
  • API keys for email, auth, etc.

Never commit secrets to git.

Common pitfalls

  • Running migrate dev in production — it can reset data. Use migrate deploy.
  • Hard-coding localhost in SEO links — set BASE_URL in production.
  • Skipping CI before merge — broken code reaches the host.

Verify it works

Run docker build and docker run locally with a .env file. Hit localhost:3000. Check logs for "Applying database migrations" before "Starting production server."

Takeaway

CI guards quality. Docker guards consistency. The host guards uptime. Secrets live in the platform dashboard — not in your repo.