instruction: Create a Dockerfile for Node.js with production best practices
output: ```dockerfile
  from v1.31 to v1.32), when a pod with SupplementalGroupsPolicy=Strict are scheduled to a node that does NOT support this feature(i.e. .status.features.supplementalGroupsPolicy=false), the pod's supplemental groups policy falls back to the Merge policy silently.However, since the beta release (v1.33), to enforce the policy more strictly, such pod creation will be rejected by kubelet because the node cannot ensure the specified policy. When your pod is rejected, you will see warning events with reason=SupplementalGroupsPolicyNotSupported like below:apiVersion: v1
  kind: Event
  ...
  type: Warning
  reason: SupplementalGroupsPolicyNotSupported
  message: "SupplementalGroupsPolicy=Strict is not supported in this node"
  involvedObject:
   apiVersion: v1
   kind: Pod
   ...
  Configure volume permission and ownership change policy for PodsFEATURE STATE:
  Kubernetes v1.23 [stable]By default, Kubernetes recursively changes ownership and permissions for the contents of each
  volume to match the fsGroup specified in a Pod's securityContext when that volume is
  mounted.
  For large volumes, checking and changing ownership and permissions can take a lot of time,
  slowing Pod startup. You can use the fsGroupChangePolicy field inside a securityContext
  to control the way that Kubernetes checks and manages ownership and permissions
  for a volume.fsGroupChangePolicy - fsGroupChangePolicy defines behavior for changing ownership
  and permission of the volume before being exposed inside a Pod.
  This field only applies to volume types that support fsGroup controlled ownership and permissions.
  This field has two possible values:OnRootMismatch: Only change permissions and ownership if the permission and the ownership of
  root directory does not match with expected permissions of the volume.
  This could help shorten the time it takes to change ownership and permission of a volume.Always: Always change permission and ownership of the volume when volume is mounted.For example:securityContext:
   runAsUser: 1000
   runAsGroup: 3000
   fsGroup: 2000
   fsGroupChangePolicy: "OnRootMismatch"
  Note:This field has no effect on ephemeral volume types such as
  secret,
  configMap,
  and emptyDir.Delegating volume permission and ownership change to CSI driverFEATURE STATE:
  Kubernetes v1.26 [stable]If you deploy a Container Storage Interface (CSI)
  driver which supports the VOLUME_MOUNT_GROUP NodeServiceCapability, the
  process of setting file ownership and permissions based on the
  fsGroup specified in the securityContext will be performed by the CSI driver
  instead of Kubernetes. In this case, since Kubernetes doesn't perform any
  ownership and permission change, fsGroupChangePolicy does not take effect, and
  as specified by CSI, the driver is expected to mount the volume with the
  provided fsGroup, resulting in a volume that is readable/writable by the
  fsGroup.Set the security context for a ContainerTo specify security settings for a Container, include the securityContext field
  in the Container manifest. The securityContext field is a
  SecurityContext object.
  Security settings that you specify for a Container apply only to
  the individual Container, and they override settings made at the Pod level when
  there is overlap. Container settings do not affect the Pod's Volumes.Here is the configuration file for a Pod that has one Container. Both the Pod
  and the Container have a securityContext field:pods/security/security-context-2.yaml
  apiVersion: v1
  kind: Pod
  metadata:
   name: security-context-demo-2
  spec:
   securityContext:
   runAsUser: 1000
   containers:
   - name: sec-ctx-demo-2
   image: gcr.io/google-samples/hello-app:2.0
   securityContext:
   runAsUser: 2000
   allowPrivilegeEscalation: false
  Create the Pod:kubectl apply -f https://k8s.io/examples/pods/security/security-context-2.yaml
  Verify that the Pod's Container is running:kubectl get pod security-context-demo-2
  Get a shell into the running Container:kubectl exec -it security-context-demo-2 -- sh
  In your shell, list the running processes:ps aux
  The output shows that the processes are running as user 2000. This is the value
  of runAsUser specified for the Container. It overrides the value 1000 that is
  specified for the Pod.USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  2000 1 0.0 0.0 4336 764 ? Ss 20:36 0:00 /bin/sh -c node server.js
  2000 8 0.1 0.5 772124 22604 ? Sl 20:36 0:00 node server.js
  ...
  Exit your shell:exit
  Set capabilities for a ContainerWith Linux capabilities,
  you can grant certain privileges to a process without granting all the privileges
  of the root user. To add or remove Linux capabilities for a Container, include the
  capabilities field in the securityContext section of the Container manifest.First, see what happens when you don't include a capabilities field.
  Here is configuration file that does not add or remove any Container capabilities:pods/security/security-context-3.yaml
  apiVersion: v1
  kind: Pod
  metadata:
   name: security-context-demo-3
  spec:
   containers:
   - name: sec-ctx-3
   image: gcr.io/google-samples/hello-app:2.0
  Create the Pod:kubectl apply -f https://k8s.io/examples/pods/security/security-context-3.yaml
  Verify that the Pod's Container is running:kubectl get pod security-context-demo-3
  Get a shell into the running Container:kubectl exec -it security-context-demo-3 -- sh
  In your shell, list the running processes:ps aux
  The output shows the process IDs (PIDs) for the Container:USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  root 1 0.0 0.0 4336 796 ? Ss 18:17 0:00 /bin/sh -c node server.js
  root 5 0.1 0.5 772124 22700 ? Sl 18:17 0:00 node server.js
  In your shell, view the status for process 1:cd /proc/1
  cat status
  The output shows the capabilities bitmap for the process:...
  CapPrm:	00000000a80425fb
  CapEff:	00000000a80425fb
  ...
  Make a note of the capabilities bitmap, and then exit your shell:exit
  Next, run a Container that is the same as the preceding container, except
  that it has additional capabilities set.Here is the configuration file for a Pod that runs one Container. The configuration
  adds the CAP_NET_ADMIN and CAP_SYS_TIME capabilities:pods/security/security-context-4.yaml
  apiVersion: v1
  kind: Pod
  metadata:
   name: security-context-demo-4
  spec:
   containers:
   - name: sec-ctx-4
   image: gcr.io/google-samples/hello-app:2.0
   securityContext:
   capabilities:
   add: ["NET_ADMIN", "SYS_TIME"]
  Create the Pod:kubectl apply -f https://k8s.io/examples/pods/security/security-context-4.yaml
  Get a shell into the running Container:kubectl exec -it security-context-demo-4 -- sh
  In your shell, view the capabilities for process 1:cd /proc/1
  cat status
  The output shows capabilities bitmap for the process:...
  CapPrm:	00000000aa0435fb
  CapEff:	00000000aa0435fb
  ...
  Compare the capabilities of the two Containers:00000000a80425fb
  00000000aa0435fb
  In the capability bitmap of the first container, bits 12 and 25 are clear. In the second container,
  bits 12 and 25 are set. Bit 12 is CAP_NET_ADMIN, and bit 25 is CAP_SYS_TIME.
  See capability.h
  for definitions of the capability constants.Note:Linux capability constants have the form CAP_XXX.
  But when you list capabilities in your container manifest, you must
  omit the CAP_ portion of the constant.
  For example, to add CAP_SYS_TIME, include SYS_TIME in your list of capabilities.Set the Seccomp Profile for a ContainerTo set the Seccomp profile for a Container, include the seccompProfile field
  in the securityContext section of your Pod or Container manifest. The
  seccompProfile field is a
  SeccompProfile object consisting of type and localhostProfile.
  Valid options for type include RuntimeDefault, Unconfined, and
  Localhost. localhostProfile must only be set if type: Localhost. It
  indicates the path of the pre-configured profile on the node, relative to the
  kubelet's configured Seccomp profile location (configured with the --root-dir
  flag).Here is an example that sets the Seccomp profile to the node's container runtime
  default profile:...
  securityContext:
   seccompProfile:
   type: RuntimeDefault
  Here is an example that sets the Seccomp profile to a pre-configured file at
  <kubelet-root-dir>/seccomp/my-profiles/profile-allow.json:...
  securityContext:
   seccompProfile:
   type: Localhost
   localhostProfile: my-profiles/profile-allow.json
  Set the AppArmor Profile for a ContainerTo set the AppArmor profile for a Container, include the appArmorProfile field
  in the securityContext section of your Container. The appArmorProfile field
  is a
  AppArmorProfile object consisting of type and localhostProfile.
  Valid options for type include RuntimeDefault(default), Unconfined, and
  Localhost. localhostProfile must only be set if type is Localhost. It
  indicates the name of the pre-configured profile on the node. The profile needs
  to be loaded onto all nodes suitable for the Pod, since you don't know where the
  pod will be scheduled.
  Approaches for setting up custom profiles are discussed in
  Setting up nodes with profiles.Note: If containers[*].securityContext.appArmorProfile.type is explicitly set
  to RuntimeDefault, then the Pod will not be admitted if AppArmor is not
  enabled on the Node. However if containers[*].securityContext.appArmorProfile.type
  is not specified, then the default (which is also RuntimeDefault) will only
  be applied if the node has AppArmor enabled. If the node has AppArmor disabled
  the Pod will be admitted but the Container will not be restricted by the
  RuntimeDefault profile.Here is an example that sets the AppArmor profile to the node's container runtime
  default profile:...
  containers:
  - name: container-1
   securityContext:
   appArmorProfile:
   type: RuntimeDefault
  Here is an example that sets the AppArmor profile to a pre-configured profile
  named k8s-apparmor-example-deny-write:...
  containers:
  - name: container-1
   securityContext:
   appArmorProfile:
   type: Localhost
   localhostProfile: k8s-apparmor-example-deny-write
  For more details please see, Restrict a Container's Access to Resources with AppArmor.Assign SELinux labels to a ContainerTo assign SELinux labels to a Container, include the seLinuxOptions field in
  the securityContext section of your Pod or Container manifest. The
  seLinuxOptions field is an
  SELinuxOptions
  object. Here's an example that applies an SELinux level:...
  securityContext:
   seLinuxOptions:
   level: "s0:c123,c456"
  Note:To assign SELinux labels, the SELinux security module must be loaded on the host operating system.
  On Windows and Linux worker nodes without SELinux support, this field and any SELinux feature gates described
  below have no effect.Efficient SELinux volume relabelingFEATURE STATE:
  Kubernetes v1.28 [beta] (enabled by default: true)Note:Kubernetes v1.27 introduced an early limited form of this behavior that was only applicable
  to volumes (and PersistentVolumeClaims) using the ReadWriteOncePod access mode.Kubernetes v1.33 promotes SELinuxChangePolicy and SELinuxMount
  feature gates
  as beta to widen that performance improvement to other kinds of PersistentVolumeClaims,
  as explained in detail below. While in beta, SELinuxMount is still disabled by default.With SELinuxMount feature gate disabled (the default in Kubernetes 1.33 and any previous release),
  the container runtime recursively assigns SELinux label to all
  files on all Pod volumes by default. To speed up this process, Kubernetes can change the
  SELinux label of a volume instantly by using a mount option
  -o context=<label>.To benefit
  ```