instruction: Create a Dockerfile for Node.js with production best practices
output: ```dockerfile
  from those limits and set them to be the same as the defined limits.At admission time the RuntimeClass admission controller
  updates the workload's PodSpec to include the overhead as described in the RuntimeClass. If the PodSpec already has this field defined,
  the Pod will be rejected. In the given example, since only the RuntimeClass name is specified, the admission controller mutates the Pod
  to include an overhead.After the RuntimeClass admission controller has made modifications, you can check the updated
  Pod overhead value:kubectl get pod test-pod -o jsonpath='{.spec.overhead}'
  The output is:map[cpu:250m memory:120Mi]
  If a ResourceQuota is defined, the sum of container requests as well as the
  overhead field are counted.When the kube-scheduler is deciding which node should run a new Pod, the scheduler considers that Pod's
  overhead as well as the sum of container requests for that Pod. For this example, the scheduler adds the
  requests and the overhead, then looks for a node that has 2.25 CPU and 320 MiB of memory available.Once a Pod is scheduled to a node, the kubelet on that node creates a new cgroup for the Pod. It is within this pod that the underlying
  container runtime will create containers.If the resource has a limit defined for each container (Guaranteed QoS or Burstable QoS with limits defined),
  the kubelet will set an upper limit for the pod cgroup associated with that resource (cpu.cfs_quota_us for CPU
  and memory.limit_in_bytes memory). This upper limit is based on the sum of the container limits plus the overhead
  defined in the PodSpec.For CPU, if the Pod is Guaranteed or Burstable QoS, the kubelet will set cpu.shares based on the
  sum of container requests plus the overhead defined in the PodSpec.Looking at our example, verify the container requests for the workload:kubectl get pod test-pod -o jsonpath='{.spec.containers[*].resources.limits}'
  The total container requests are 2000m CPU and 200MiB of memory:map[cpu: 500m memory:100Mi] map[cpu:1500m memory:100Mi]
  Check this against what is observed by the node:kubectl describe node | grep test-pod -B2
  The output shows requests for 2250m CPU, and for 320MiB of memory. The requests include Pod overhead: Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
   --------- ---- ------------ ---------- --------------- ------------- ---
   default test-pod 2250m (56%) 2250m (56%) 320Mi (1%) 320Mi (1%) 36m
  Verify Pod cgroup limitsCheck the Pod's memory cgroups on the node where the workload is running. In the following example,
  crictl
  is used on the node, which provides a CLI for CRI-compatible container runtimes. This is an
  advanced example to show Pod overhead behavior, and it is not expected that users should need to check
  cgroups directly on the node.First, on the particular node, determine the Pod identifier:# Run this on the node where the Pod is scheduled
  POD_ID="$(sudo crictl pods --name test-pod -q)"
  ```