A minimal Go HTTP server demo.
cmd/server/main.go Entry point
internal/handlers/ HTTP handlers
internal/service/ Business logic
internal/models/ Structs/models
internal/middleware/ Request-logging middleware
k8s/ Kubernetes manifests
GET /hello?name=X— returns{"message":"Hello, X!"}GET /health— returns{"status":"ok"}, used by Kubernetes probes
The server reads APP_ENV at startup (dev/qa/prod, defaults to development) and logs which environment it's running as.
go run ./cmd/serverStarts the server directly on your machine.
curl "http://localhost:8080/hello?name=Go"Hits the running server.
docker build -t go-demo .Builds the image from the Dockerfile (multi-stage: compiles a static binary in a Go builder stage, copies just the binary into a minimal Alpine final stage).
docker run -d -p 8080:8080 -e APP_ENV=qa --name go-demo go-demoRuns the image as a detached container, maps port 8080, and sets the environment to qa (swap for dev/prod/omit for development).
docker psLists running containers — confirm go-demo is Up.
docker logs -f go-demoStreams the container's logs live (Ctrl+C to stop following). Shows the startup environment line and each request logged by the middleware.
docker exec -it go-demo shOpens a shell inside the running container to inspect its filesystem. Alpine only has sh, not bash.
ls
ps
cat /etc/os-release
exitInside the container shell: list files, list processes, check the base OS, then leave the shell.
docker stats go-demo --no-streamPrints a single snapshot of CPU/memory/network/disk usage for the container.
docker stop go-demoStops the running container.
docker rm go-demoRemoves the stopped container so the name can be reused.
kind runs a real Kubernetes cluster as Docker containers on your machine — no cloud account needed.
go install sigs.k8s.io/kind@latestInstalls the kind CLI (via Go, since it's already set up on this machine).
kind versionConfirms kind installed correctly.
kind create clusterCreates a local cluster and points kubectl at it (context kind-kind).
kubectl config get-contextsLists every cluster kubectl knows how to talk to.
kubectl cluster-info --context kind-kindConfirms the cluster's control plane is reachable.
kubectl get nodesLists the cluster's nodes — should show one Ready node.
kind load docker-image go-demo:latestCopies your locally built image into the kind node's image store, since kind doesn't share your regular docker images cache.
kubectl apply -f k8s/deployment.yamlCreates/updates the Deployment — Kubernetes creates the replica Pods to match the spec (image, ports, probes, resource limits).
kubectl apply -f k8s/service.yamlCreates/updates the Service — a stable internal address that load-balances traffic across the Deployment's pods.
kubectl get podsLists current pods and their status.
kubectl get pods -wSame as above, but streams live updates as pod status changes (Ctrl+C to stop watching).
kubectl describe pod <pod-name>Shows full detail for one pod, including its event history — the main tool for diagnosing why a pod isn't starting (e.g. image pull errors).
kubectl get deploymentsShows the Deployment's desired vs. actual replica counts.
kubectl get svcShows Services and their assigned internal ClusterIP.
kubectl port-forward svc/go-demo 8080:80Tunnels localhost:8080 into the cluster's Service, so you can curl it from your machine. Note: this pins to a single backing pod for the life of the tunnel — it does not demonstrate real Service load-balancing.
kubectl logs -l app=go-demo --all-containers --prefixShows logs from every pod matching the app=go-demo label, prefixed with which pod each line came from.
kubectl run curl-test --image=curlimages/curl --rm -it --restart=Never -- shLaunches a temporary pod with curl inside the cluster, for testing real Service load-balancing (kube-proxy) rather than the pinned behavior of port-forward. Deletes itself on exit (--rm).
for i in $(seq 1 10); do curl -s "http://go-demo/hello?name=Test$i"; echo; done
exitRun from inside the curl-test pod: hits the Service by its in-cluster DNS name 10 times, then leaves the shell (which deletes the pod).
kubectl delete -f k8s/deployment.yaml
kubectl delete -f k8s/service.yamlRemoves the Deployment and Service from the cluster.
kubectl scale deployment/go-demo --replicas=4Changes the desired replica count — the Deployment controller creates (or removes) pods to match.
kubectl delete pod <pod-name>Deletes one pod directly. The Deployment notices actual replicas dropped below desired and immediately creates a replacement — this is "self-healing": nothing explicit triggers it, the controller just continuously reconciles desired vs. actual state.
kubectl set image deployment/go-demo go-demo=<image:tag>Imperatively changes the container image for the Deployment, triggering a rolling update. Using a tag that doesn't exist is a good way to safely rehearse a bad rollout.
kubectl rollout status deployment/go-demoWatches a rollout's progress; hangs/times out if new pods never become healthy (e.g. bad image).
kubectl rollout history deployment/go-demoLists past revisions of the Deployment's pod template. Numbers only increase — they don't map 1:1 to "how many revisions currently exist."
kubectl annotate deployment/go-demo kubernetes.io/change-cause="<message>" --overwriteRecords a reason for the next change, so rollout history shows something more useful than <none> in CHANGE-CAUSE.
kubectl rollout undo deployment/go-demoReverts the Deployment to its previous revision — the standard fix for a stuck/bad rollout. Since this is an imperative command, it doesn't update the last-applied-configuration annotation kubectl apply relies on; re-run kubectl apply -f k8s/deployment.yaml afterward to resync.