instruction: Create a Dockerfile for Node.js with production best practices
output: ```dockerfile
  From the containerized task, in the environment variable JOB_COMPLETION_INDEX.
  
  The Job is considered complete when there is one successfully completed Pod
  for each index. For more information about how to use this mode, see
  Indexed Job for Parallel Processing with Static Work Assignment.
  
  Note:Although rare, more than one Pod could be started for the same index (due to various reasons such as node failures,
  kubelet restarts, or Pod evictions). In this case, only the first Pod that completes successfully will
  count towards the completion count and update the status of the Job. The other Pods that are running
  or completed for the same index will be deleted by the Job controller once they are detected.
  Handling Pod and container failures
  A container in a Pod may fail for a number of reasons, such as because the process in it exited with
  a non-zero exit code, or the container was killed for exceeding a memory limit, etc. If this
  happens, and the .spec.template.spec.restartPolicy = "OnFailure", then the Pod stays
  on the node, but the container is re-run. Therefore, your program needs to handle the case when it is
  restarted locally, or else specify .spec.template.spec.restartPolicy = "Never".
  See pod lifecycle for more information on restartPolicy.
  An entire Pod can also fail, for a number of reasons, such as when the pod is kicked off the node
  (node is upgraded, rebooted, deleted, etc.), or if a container of the Pod fails and the
  .spec.template.spec.restartPolicy = "Never". When a Pod fails, then the Job controller
  starts a new Pod. This means that your application needs to handle the case when it is restarted in a new
  pod. In particular, it needs to handle temporary files, locks, incomplete output and the like
  caused by previous runs.
  By default, each pod failure is counted towards the .spec.backoffLimit limit,
  see pod backoff failure policy. However, you can
  customize handling of pod failures by setting the Job's pod failure policy.
  Additionally, you can choose to count the pod failures independently for each
  index of an Indexed Job by setting the .spec.backoffLimitPerIndex field
  (for more information, see backoff limit per index).
  Note that even if you specify .spec.parallelism = 1 and .spec.completions = 1 and
  .spec.template.spec.restartPolicy = "Never", the same program may
  sometimes be started twice.
  If you do specify .spec.parallelism and .spec.completions both greater than 1, then there may be
  multiple pods running at once. Therefore, your pods must also be tolerant of concurrency.
  If you specify the .spec.podFailurePolicy field, the Job controller does not consider a terminating
  Pod (a pod that has a .metadata.deletionTimestamp field set) as a failure until that Pod is
  terminal (its .status.phase is Failed or Succeeded). However, the Job controller
  creates a replacement Pod as soon as the termination becomes apparent. Once the
  pod terminates, the Job controller evaluates .backoffLimit and .podFailurePolicy
  for the relevant Job, taking this now-terminated Pod into consideration.
  If either of these requirements is not satisfied, the Job controller counts
  a terminating Pod as an immediate failure, even if that Pod later terminates
  with phase: "Succeeded".
  Pod backoff failure policy
  There are situations where you want to fail a Job after some amount of retries
  due to a logical error in configuration etc.
  To do so, set .spec.backoffLimit to specify the number of retries before
  considering a Job as failed. The back-off limit is set by default to 6. Failed
  Pods associated with the Job are recreated by the Job controller with an
  exponential back-off delay (10s, 20s, 40s ...) capped at six minutes.
  The number of retries is calculated in two ways:
  
  The number of Pods with .status.phase = "Failed".
  When using restartPolicy = "OnFailure", the number of retries in all the
  containers of Pods with .status.phase equal to Pending or Running.
  
  If either of the calculations reaches the .spec.backoffLimit, the Job is
  considered failed.
  Note:If your job has restartPolicy = "OnFailure", keep in mind that your Pod running the Job
  will be terminated once the job backoff limit has been reached. This can make debugging
  the Job's executable more difficult. We suggest setting
  restartPolicy = "Never" when debugging the Job or using a logging system to ensure output
  ```
  
  ## Production Considerations
  
  ### Security Best Practices
  
  1. **Use non-root user**
  ```dockerfile
  # Create non-root user
  RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
  USER nodejs
  ```
  
  2. **Scan for vulnerabilities**
  ```bash
  # Scan container image
  docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image <image_name>
  ```
  
  3. **Apply security policies**
  ```yaml
  apiVersion: v1
  kind: Pod
  spec:
    securityContext:
      runAsNonRoot: true
      runAsUser: 1001
      fsGroup: 1001
    containers:
    - name: app
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
          - ALL
  ```
  
  ### Performance Optimization
  
  1. **Resource management**
  ```yaml
  resources:
    requests:
      memory: "128Mi"
      cpu: "100m"
    limits:
      memory: "256Mi"
      cpu: "200m"
  ```
  
  2. **Horizontal Pod Autoscaling**
  ```yaml
  apiVersion: autoscaling/v2
  kind: HorizontalPodAutoscaler
  metadata:
    name: app-hpa
  spec:
    scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: my-app
    minReplicas: 3
    maxReplicas: 10
    metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
  ```
  
  ### Backup and Disaster Recovery
  
  1. **Data backup strategy**
  ```bash
  # Automated backup script
  kubectl create job --from=cronjob/backup-job backup-manual-$(date +%Y%m%d-%H%M%S)
  ```
  
  2. **Multi-region deployment**
  ```yaml
  # Anti-affinity rules
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - my-app
          topologyKey: kubernetes.io/zone
  ```