Chapter 2: Make CD

Deploy Locally (CD to Minikube)

make cd

What you should see

t@Mac ship-securely-devsecops % make cd
⛵ Minikube (ship) is running
docker build -t ship-securely/app:dev app
[+] Building 0.3s (15/15) FINISHED                            docker:desktop-linux
 => [internal] load build definition from Dockerfile                          0.0s
 => => transferring dockerfile: 876B                                          0.0s 
 => [internal] load metadata for docker.io/library/alpine:3.20                0.3s 
 => [internal] load metadata for docker.io/library/golang:1.22-alpine         0.3s
 => [internal] load .dockerignore                                             0.0s
 => => transferring context: 2B                                               0.0s 
 => [build 1/4] FROM docker.io/library/golang:1.22-alpine@sha256:1699c10032c  0.0s 
 => [stage-1 1/5] FROM docker.io/library/alpine:3.20@sha256:765942a403999233  0.0s 
 => [internal] load build context                                             0.0s 
 => => transferring context: 447B                                             0.0s 
 => CACHED [stage-1 2/5] RUN addgroup -g 10001 app && adduser -D -H -u 10001  0.0s 
 => CACHED [stage-1 3/5] WORKDIR /home/appuser                                0.0s 
 => CACHED [build 2/4] WORKDIR /src                                           0.0s 
 => CACHED [build 3/4] COPY . .                                               0.0s 
 => CACHED [build 4/4] RUN --mount=type=cache,target=/go/pkg/mod     --mount  0.0s 
 => CACHED [stage-1 4/5] COPY --from=build /out/server /usr/local/bin/server  0.0s 
 => CACHED [stage-1 5/5] RUN chown -R 10001:10001 /home/appuser               0.0s 
 => exporting to image                                                        0.0s 
 => => exporting layers                                                       0.0s 
 => => writing image sha256:7e699d375101f7b1246378e22a53a70e9d89f63138a7f666  0.0s 
 => => naming to docker.io/ship-securely/app:dev                              0.0s 
                                                                                   
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/ipq16egtws0nkd6twx07u5xs7

What's next:
    View a summary of image vulnerabilities and recommendations → docker scout quickview                                                                              
minikube -p ship image load ship-securely/app:dev
kubectl get ns ship >/dev/null 2>&1 || kubectl create ns ship
service/app unchanged
deployment.apps/app unchanged
kubectl -n ship set image deploy/app app=ship-securely/app:dev
kubectl -n ship rollout status deploy/app
deployment "app" successfully rolled out
== OWASP ZAP (baseline via port-forward) ==
( kubectl -n ship port-forward deploy/app 8080:3000 >/dev/null 2>&1 & echo $! > .pf.pid )
Port-forward is live
ZAP target: http://host.docker.internal:8080
Using the Automation Framework
WARN-NEW: Missing Anti-clickjacking Header [10020] x 6 
WARN-NEW: X-Content-Type-Options Header Missing [10021] x 7 
WARN-NEW: Content Security Policy (CSP) Header Not Set [10038] x 7 
WARN-NEW: Storable and Cacheable Content [10049] x 8 
WARN-NEW: Permissions Policy Header Not Set [10063] x 7 
WARN-NEW: Modern Web Application [10109] x 1 
WARN-NEW: Insufficient Site Isolation Against Spectre Vulnerability [90004] x 19 
FAIL-NEW: 0     FAIL-INPROG: 0  WARN-NEW: 7     WARN-INPROG: 0  INFO: 0 IGNORE: 0 PASS: 60
✅ Deployed app to Minikube (ship) in namespace ship

Evidence Packet

Open ./artifacts/ and skim:

  • sbom.json (Syft) — supply-chain inventory
  • trivy-image.json or grype.json — vuln scan
  • checkov.json — IaC misconfigs
  • hadolint.txt — Dockerfile issues
  • trufflehog.json — secrets scan
  • tools/zap/report.html — DAST baseline

What’s next

  • If any prereqs are red ❌, follow the “Installing …” pages or Troubleshooting.