← All cheat sheets ·

DevOps Commands

Maven, Git, Docker, kubectl, JDK diagnostic tools, Actuator endpoints, a multi-stage Dockerfile and JVM container flags.

Maven

Command Effect
mvn clean verify clean, compile, test, package, integration tests (failsafe)
mvn -q -DskipTests package build jar without running tests (still compiles tests; -Dmaven.test.skip=true skips compiling too)
mvn test -Dtest=FooTest#bar single test / method
mvn -pl api -am package build module api and the modules it depends on
mvn -T 1C package parallel build, one thread per core
mvn dependency:tree -Dincludes=org.slf4j why a dependency is present / conflicts
mvn dependency:analyze unused-declared and used-undeclared
mvn versions:display-dependency-updates outdated dependencies
mvn help:effective-pom resolved POM
mvn -o ... / -U offline / force snapshot update
mvn spring-boot:run run app (-Dspring-boot.run.profiles=dev)
mvn spring-boot:build-image OCI image via Buildpacks (no Dockerfile)
./mvnw ... wrapper, pins Maven version
  • Lifecycle: validate, compile, test, package, verify, install, deploy; running a phase runs all earlier phases.
  • Scopes: compile (default), provided, runtime, test, import (BOM, in dependencyManagement).
  • Surefire runs *Test; Failsafe runs *IT in integration-test / verify.
  • Gradle equivalents: ./gradlew build, test --tests Foo, dependencies, bootRun, bootBuildImage.

Git

git switch -c feature/x               # create + switch (restore/switch replace checkout in 2.23+)
git add -p                            # stage hunks interactively
git commit --amend --no-edit          # fold staged changes into last commit
git fetch --prune && git rebase origin/main
git rebase -i HEAD~4                  # squash/reword/reorder (rewrites history; never on shared branches)
git push --force-with-lease           # safer than --force
git stash push -m "wip" -u            # include untracked; git stash pop
git cherry-pick <sha>                 # copy a commit; -x records origin
git revert <sha>                      # new commit that undoes (safe on shared branches)
git reset --soft HEAD~1               # keep changes staged; --mixed (default) unstaged; --hard discards
git restore --staged <file>           # unstage;  git restore <file> discards working changes
git reflog                            # recover "lost" commits, then git branch rescue <sha>
git bisect start; git bisect bad; git bisect good <sha>   # binary search for a regression
Need Command
Who changed a line git blame -L 10,20 file
Find commit by message / code git log --grep=text, git log -S'symbol' --oneline
Compact graph git log --oneline --graph --decorate --all
Diff staged / vs branch git diff --staged, git diff main...HEAD
Undo merge in progress git merge --abort / git rebase --abort
Tag release git tag -a v1.2.0 -m "msg" && git push origin v1.2.0
Parallel checkouts git worktree add ../hotfix hotfix
  • Merge keeps history (merge commit); rebase rewrites onto a new base for linear history; squash-merge collapses a branch to one commit.
  • HEAD~n = n-th ancestor along first parent; HEAD^2 = second parent of a merge.

Docker

Command Effect
docker build -t app:1.0 . build (BuildKit default since 23.0)
docker run -d --name app -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod --memory=512m app:1.0 run detached
docker ps -a / docker logs -f --tail 100 app list / follow logs
docker exec -it app sh shell in running container
docker stop app && docker rm app stop, remove
docker images / docker rmi / docker system prune -af images / remove / clean everything unused
docker inspect app / docker stats config / live CPU, memory
docker compose up -d --build / down -v / logs -f svc multi-container (v2 plugin: docker compose)
docker cp app:/tmp/heap.hprof . copy file out
docker network ls / docker volume ls networks / volumes
  • CMD is default args, ENTRYPOINT the executable; use exec form (JSON array) so the JVM is PID 1 and receives SIGTERM.
  • Use .dockerignore (target/, .git); order layers least-to-most changing (dependencies before source) for cache.

kubectl

kubectl config get-contexts; kubectl config use-context prod
kubectl get pods -n app -o wide -w          # -w watch
kubectl describe pod web-7d9 -n app         # events: OOMKilled, probe failures, image pull
kubectl logs web-7d9 -c app --previous -f   # previous container instance (after crash)
kubectl exec -it web-7d9 -- sh
kubectl port-forward svc/web 8080:80
kubectl apply -f deploy.yaml; kubectl diff -f deploy.yaml
kubectl rollout status deploy/web; kubectl rollout undo deploy/web
kubectl scale deploy/web --replicas=5
kubectl set image deploy/web app=repo/app:1.1
kubectl top pod -n app                      # needs metrics-server
kubectl get events --sort-by=.lastTimestamp
kubectl debug -it web-7d9 --image=busybox --target=app   # ephemeral container
  • Pod status hints: CrashLoopBackOff (app exits), ImagePullBackOff, Pending (resources/scheduling), OOMKilled (exit 137, memory limit exceeded), Evicted.
  • Probes: startupProbe (slow boot), readinessProbe (receive traffic), livenessProbe (restart). Spring Boot: /actuator/health/readiness and /liveness (enabled automatically on Kubernetes, or management.endpoint.health.probes.enabled=true).
  • Set terminationGracePeriodSeconds >= Spring graceful shutdown timeout.

JDK diagnostic tools

Command Use
jps -lv list JVMs
jcmd <pid> help list available diagnostic commands
jcmd <pid> Thread.print / jstack -l <pid> thread dump with locks and deadlocks (take 3 dumps, 5-10 s apart)
jcmd <pid> GC.heap_info / GC.class_histogram heap summary / object counts per class
jcmd <pid> GC.heap_dump /tmp/h.hprof heap dump (preferred over jmap; file written by the target JVM)
jmap -dump:live,format=b,file=h.hprof <pid> heap dump (live triggers a full GC)
jmap -histo:live <pid> class histogram
jstat -gcutil <pid> 1000 GC utilization every second (S0 S1 E O M CCS YGC FGC GCT)
jcmd <pid> VM.flags / VM.system_properties / VM.native_memory effective flags / props / NMT (needs -XX:NativeMemoryTracking=summary)
jcmd <pid> JFR.start duration=60s filename=/tmp/r.jfr settings=profile Flight Recorder (open in JDK Mission Control)
jcmd <pid> Thread.dump_to_file -format=json f.json thread dump including virtual threads (21)
  • High CPU: top -H -p <pid>, convert thread id to hex, find nid=0x... in the thread dump.
  • Memory leak: compare two class histograms, heap dump on OOM: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps; analyze with Eclipse MAT.
  • Tools attach as the same user as the JVM; in containers run them inside it (JDK image, not JRE) or use kubectl debug.

Actuator endpoints

Endpoint Purpose
/actuator/health (/liveness, /readiness) status; details with management.endpoint.health.show-details=when-authorized
/actuator/info build/git info
/actuator/metrics, /metrics/jvm.memory.used Micrometer metrics
/actuator/prometheus Prometheus scrape (needs micrometer-registry-prometheus)
/actuator/env, /configprops, /beans, /mappings, /conditions configuration introspection (sensitive)
/actuator/loggers change log level at runtime (POST {"configuredLevel":"DEBUG"})
/actuator/threaddump, /heapdump diagnostics (heapdump is sensitive)
/actuator/httpexchanges recent requests (Boot 3; needs a repository bean)
  • Only health is exposed over HTTP by default; expose others via management.endpoints.web.exposure.include. Put on a separate management.server.port and secure it.

Dockerfile: multi-stage Spring Boot

FROM eclipse-temurin:21-jdk AS build
WORKDIR /src
COPY mvnw pom.xml ./
COPY .mvn .mvn
RUN ./mvnw -q dependency:go-offline
COPY src src
RUN ./mvnw -q -DskipTests package && cp target/*.jar /app.jar

FROM eclipse-temurin:21-jre
RUN useradd -r -u 1001 app
WORKDIR /app
COPY --from=build /app.jar app.jar
USER 1001
EXPOSE 8080
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75", "-jar", "app.jar"]
  • Better caching: extract layers with java -Djarmode=tools -jar app.jar extract --layers (Boot 3.3+; earlier -Djarmode=layertools extract) and COPY dependencies/ and application/ separately.
  • The Boot repackage plugin leaves one *.jar (the original is *.jar.original), so the glob is safe.
  • Alternative: mvn spring-boot:build-image (Buildpacks) or Jib.

JVM container flags

Flag Meaning
-XX:MaxRAMPercentage=75 heap as % of container memory limit (default 25; leave room for metaspace, threads, direct buffers)
-XX:InitialRAMPercentage=50 initial heap
-Xms / -Xmx explicit fixed heap (set equal in steady services)
-XX:ActiveProcessorCount=N override CPU count (JVM reads cgroup quota by default; -XX:+UseContainerSupport on since 10 / 8u191)
-XX:+UseG1GC / -XX:+UseZGC -XX:+ZGenerational / -XX:+UseSerialGC collector; G1 default with 2+ CPUs and 1792 MB+, otherwise Serial
-XX:MaxGCPauseMillis=200 G1 pause goal
-XX:MaxMetaspaceSize=256m, -Xss512k metaspace cap, thread stack
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps dump on OOM
-XX:+ExitOnOutOfMemoryError let the orchestrator restart
-Xlog:gc*:file=/logs/gc.log:time,uptime:filecount=5,filesize=20m unified GC logging (9+)
-XX:NativeMemoryTracking=summary off-heap diagnostics
-XX:TieredStopAtLevel=1 faster startup, lower peak (dev/short jobs)
-XX:+UseStringDeduplication G1 string dedupe
  • Kubernetes: memory limit = heap + metaspace + threads + code cache + direct memory; heap 70-75% of limit. CPU limit < 1 core makes the JVM pick Serial GC and 1 processor.
  • Env var form: JAVA_TOOL_OPTIONS="-XX:MaxRAMPercentage=75" (logged at startup as "Picked up JAVA_TOOL_OPTIONS").
  • Startup: Spring AOT + GraalVM native image (-Pnative), CDS/AppCDS (Boot 3.3+), CRaC (Boot 3.2+ with supported JDK).