# The interactive build pod: one privileged Docker daemon in a Nitro sandbox, which you
# exec into to run `docker build` and `docker run` by hand.
#
# scripts/setup.sh renders <NAMESPACE>.
#
# runtimeClassName: isolated-sandbox is the whole opt-in. The RuntimeClass carries the
# scheduling constraints, so there is no node selector, toleration or sidecar here.
apiVersion: v1
kind: Pod
metadata:
  name: hello-docker
  namespace: <NAMESPACE>
  labels:
    app: hello-docker
    # The egress policy selects every build pod in the sample by this label.
    app.kubernetes.io/part-of: docker-builds
  annotations:
    # Pin the node while this long-lived build pod runs. Auto Mode's node consolidation
    # would otherwise remove an underused node, and nothing recreates a bare pod.
    karpenter.sh/do-not-disrupt: "true"
spec:
  runtimeClassName: isolated-sandbox
  serviceAccountName: docker-builds-builder
  # Pod Identity does not need the Kubernetes token mounted, and the build never calls the
  # Kubernetes API, so the token stays out of the pod.
  automountServiceAccountToken: false
  terminationGracePeriodSeconds: 0
  containers:
    - name: dind
      image: public.ecr.aws/docker/library/docker:29.9.2-dind
      # The one privilege the sample asks for. It reaches only this pod's own guest: the
      # daemon can mount, chroot, manage cgroups, unpack layers and run nested containers
      # inside the sandbox, and nothing of that reaches the node (Amazon EKS User Guide,
      # "Developing with sandboxes", Privileged pods). A privileged container gets every
      # capability and no seccomp filter (it reads Seccomp: 0 in /proc/1/status even with a
      # RuntimeDefault profile set), so there is no capability or seccomp setting to add:
      # the sandbox is the boundary, not the container's own settings.
      #
      # The root file system is read-only all the same, so the daemon and the CLI write only
      # to the volumes below: its data directory, /run (/var/run links to it) for the socket
      # and containerd state, the CLI's ~/.docker, and /build for Step 3. The image's dind
      # wrapper mounts its own tmpfs on /tmp.
      securityContext:
        privileged: true
        readOnlyRootFilesystem: true
      # Start the daemon on its local Unix socket and NOTHING else. The image's entrypoint
      # would otherwise add --host=tcp://0.0.0.0:2375 (or 2376 with TLS) and put a daemon
      # that is root-equivalent on the pod network; naming `dockerd` and its --host here
      # keeps the entrypoint's own setup (tini as PID 1, iptables modules) and leaves the
      # daemon reachable only from inside this pod.
      args: ["dockerd", "--host=unix:///var/run/docker.sock"]
      # Report Ready only once the daemon answers, so an exec straight after the wait finds
      # a working `docker` CLI.
      readinessProbe:
        exec:
          command: ["docker", "info"]
        initialDelaySeconds: 5
        periodSeconds: 5
        failureThreshold: 30
      # Restart a daemon that stops answering. The startup probe holds the liveness probe
      # off until the daemon first answers, for up to 150 seconds (30 x 5 s), close to the
      # 155 the readiness probe allows (5 s delay plus 30 x 5 s), so a slow cold start is
      # not killed for being slow.
      startupProbe:
        exec:
          command: ["docker", "info"]
        periodSeconds: 5
        timeoutSeconds: 5
        failureThreshold: 30
      livenessProbe:
        exec:
          command: ["docker", "info"]
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 3
      volumeMounts:
        # Cover the image's declared VOLUME /var/lib/docker with a volume the pod provides.
        # An emptyDir is enough for a throwaway build; the Jobs put an EBS claim here so the
        # layer cache survives the run.
        - name: docker-storage
          mountPath: /var/lib/docker
        - name: run              # the socket, dockerd and containerd state (/var/run -> /run)
          mountPath: /run
        - name: docker-config    # the docker CLI writes ~/.docker during a build
          mountPath: /root/.docker
        - name: build            # Step 3 writes its Dockerfile here
          mountPath: /build
      resources:
        # A sandbox is sized when it boots and cannot be resized in place (Amazon EKS User
        # Guide, "Isolated and confidential pods limitations", In-place resource resize), so
        # a multi-minute build asks for what it needs up front. Without these the guest gets
        # the small default size, which is not enough to compile and pull base images.
        requests:
          cpu: "1"
          memory: 2Gi
        limits:
          cpu: "1"
          memory: 2Gi
  volumes:
    - name: docker-storage
      emptyDir: {}
    - name: run
      emptyDir: {}
    - name: docker-config
      emptyDir: {}
    - name: build
      emptyDir: {}
