# Restricciones de recursos


Por defecto, un contenedor no tiene restricciones de recursos y puede utilizar tanto de un recurso dado como lo permita el programador del kernel del host. Docker proporciona formas de controlar cuánta memoria o CPU puede utilizar un contenedor, configurando banderas en tiempo de ejecución del comando `docker run`. Esta sección detalla cuándo debes configurar dichos límites y las posibles implicaciones de establecerlos.

Muchas de estas características requieren que tu kernel admita capacidades de Linux. Para comprobar si son compatibles, puedes utilizar el comando [`docker info`](/reference/cli/docker/system/info/). Si una capacidad está deshabilitada en tu kernel, es posible que veas una advertencia al final de la salida como la siguiente:

```console
WARNING: No swap limit support
```

Consulta la documentación de tu sistema operativo para habilitarlas. Consulta también la [guía de resolución de problemas de Docker Engine](/engine/daemon/troubleshoot/#kernel-cgroup-swap-limit-capabilities) para obtener más información.

## Memoria

## Comprender los riesgos de quedarse sin memoria

Es importante no permitir que un contenedor en ejecución consuma demasiada memoria de la máquina host. En hosts Linux, si el kernel detecta que no hay suficiente memoria para realizar funciones importantes del sistema, lanza una excepción `OOME` o `Out Of Memory Exception` y comienza a finalizar procesos para liberar memoria. Cualquier proceso está sujeto a ser finalizado, incluyendo Docker y otras aplicaciones importantes. Esto puede provocar la caída de todo el sistema si se finaliza el proceso equivocado.

Docker intenta mitigar estos riesgos ajustando la prioridad OOM en el demonio de Docker para que sea menos probable que sea finalizado en comparación con otros procesos del sistema. La prioridad OOM en los contenedores no se ajusta. Esto hace que sea más probable que se finalice un contenedor individual antes que el demonio de Docker u otros procesos del sistema. No debes intentar eludir estas salvaguardas configurando manualmente `--oom-score-adj` a un número negativo extremo en el demonio o en un contenedor, ni configurando `--oom-kill-disable` en un contenedor.

Para obtener más información sobre la gestión de OOM del kernel de Linux, consulta [Out of Memory Management](https://www.kernel.org/doc/gorman/html/understand/understand016.html).

Puedes mitigar el riesgo de inestabilidad del sistema debido a OOME mediante:

- Realizar pruebas para comprender los requisitos de memoria de tu aplicación antes de llevarla a producción.
- Asegurarte de que tu aplicación se ejecute únicamente en hosts con recursos adecuados.
- Limitar la cantidad de memoria que puede utilizar tu contenedor, como se describe a continuación.
- Prestar atención al configurar el espacio de intercambio (swap) en tus hosts Docker. El swap es más lento que la memoria física, pero puede proporcionar un colchón contra la falta de memoria del sistema.
- Considerar la conversión de tu contenedor en un [servicio](/engine/swarm/services/), y utilizar restricciones a nivel de servicio y etiquetas de nodo para asegurar que la aplicación se ejecute solo en hosts con suficiente memoria.

### Limitar el acceso a la memoria de un contenedor

Docker puede aplicar límites de memoria estrictos (hard) o flexibles (soft).

- Los límites estrictos impiden que el contenedor utilice más de una cantidad fija de memoria.
- Los límites flexibles permiten al contenedor utilizar tanta memoria como necesite a menos que se cumplan ciertas condiciones, como cuando el kernel detecta poca memoria o contención en la máquina host.

Algunas de estas opciones tienen efectos diferentes cuando se usan solas o cuando se configura más de una opción.

La mayoría de estas opciones aceptan un entero positivo, seguido de un sufijo `b`, `k`, `m`, `g`, para indicar bytes, kilobytes, megabytes o gigabytes.

| Opción                 | Descripción                                                                                                                                                                                                                                                                                                                                                                                     |
| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-m` o `--memory=`    | La cantidad máxima de memoria que el contenedor puede utilizar. Si configuras esta opción, el valor mínimo permitido es `6m` (6 megabytes). Es decir, debes establecer el valor en al menos 6 megabytes.                                                                                                                                                                                                           |
| `--memory-swap`\*      | La cantidad de memoria que este contenedor tiene permitido intercambiar a disco. Consulta [detalles de `--memory-swap`](#--memory-swap-details).                                                                                                                                                                                                                                                                          |
| `--memory-swappiness`  | Por defecto, el kernel del host puede intercambiar un porcentaje de páginas anónimas utilizadas por un contenedor. Puedes configurar `--memory-swappiness` a un valor entre 0 y 100 para ajustar este porcentaje. Consulta [detalles de `--memory-swappiness`](#--memory-swappiness-details).                                                                                                                                       |
| `--memory-reservation` | Te permite especificar un límite flexible menor que `--memory`, el cual se activa cuando Docker detecta contención o poca memoria en la máquina host. Si utilizas `--memory-reservation`, debe configurarse a un valor inferior a `--memory` para que tenga precedencia. Al ser un límite flexible, no garantiza que el contenedor no supere el límite.                                                |
| `--oom-kill-disable`   | Por defecto, si ocurre un error de falta de memoria (OOM), el kernel finaliza los procesos dentro del contenedor. Para cambiar este comportamiento, utiliza la opción `--oom-kill-disable`. Solo deshabilita el OOM killer en contenedores donde también hayas configurado la opción `-m/--memory`. Si la bandera `-m` no está configurada, el host puede quedarse sin memoria y el kernel podría necesitar finalizar procesos del sistema host para liberar memoria. |

Para obtener más información sobre cgroups y la memoria en general, consulta la documentación de [Memory Resource Controller](https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt).

### Detalles de `--memory-swap`

`--memory-swap` es una bandera modificadora que solo tiene sentido si también está configurada `--memory`. El uso de swap permite al contenedor escribir los requisitos de memoria excedentes en el disco cuando el contenedor ha agotado toda la memoria RAM disponible para él. Existe una penalización en el rendimiento para las aplicaciones que intercambian memoria a disco con frecuencia.

Su configuración puede tener efectos complejos:

- Si `--memory-swap` se configura con un entero positivo, entonces deben establecerse tanto `--memory` como `--memory-swap`. `--memory-swap` representa la cantidad total de memoria y swap que se puede utilizar, y `--memory` controla la cantidad utilizada por la memoria física (sin swap). Por lo tanto, si `--memory="300m"` y `--memory-swap="1g"`, el contenedor puede utilizar 300m de memoria y 700m (`1g - 300m`) de swap.

- Si `--memory-swap` se configura en `0`, la configuración se ignora y el valor se trata como no establecido.

- Si `--memory-swap` se configura con el mismo valor que `--memory`, y `--memory` está configurada con un entero positivo, **el contenedor no tendrá acceso al swap**. Consulta [Evitar que un contenedor utilice swap](#prevent-a-container-from-using-swap).

- Si `--memory-swap` no está configurada y `--memory` sí lo está, el contenedor puede utilizar tanto swap como la configuración de `--memory`, siempre que el contenedor host tenga memoria swap configurada. Por ejemplo, si `--memory="300m"` y `--memory-swap` no está establecida, el contenedor puede utilizar 600m en total de memoria y swap.

- Si `--memory-swap` se configura explícitamente en `-1`, el contenedor tiene permitido utilizar swap ilimitado, hasta la cantidad disponible en el sistema host.

- Dentro del contenedor, herramientas como `free` reportan el swap disponible en el host, no el disponible dentro del contenedor. No confíes en la salida de `free` o herramientas similares para determinar si el swap está presente.

#### Evitar que un contenedor utilice swap

Si `--memory` y `--memory-swap` se configuran con el mismo valor, esto evita que los contenedores utilicen swap. Esto se debe a que `--memory-swap` es la cantidad combinada de memoria y swap que se puede utilizar, mientras que `--memory` es solo la cantidad de memoria física que se puede usar.

### Detalles de `--memory-swappiness`

- Un valor de 0 desactiva el intercambio de páginas anónimas.
- Un valor de 100 establece todas las páginas anónimas como intercambiables.
- Por defecto, si no configuras `--memory-swappiness`, el valor se hereda de la máquina host.

## CPU

Por defecto, el acceso de cada contenedor a los ciclos de CPU de la máquina host es ilimitado. Puedes establecer varias restricciones para limitar el acceso de un contenedor dado a los ciclos de CPU de la máquina host. La mayoría de los usuarios utilizan y configuran el [programador CFS por defecto](#configure-the-default-cfs-scheduler). También puedes configurar el [programador en tiempo real](#configure-the-real-time-scheduler).

### Configurar el programador CFS por defecto

El CFS es el programador de CPU del kernel de Linux para procesos normales de Linux. Varias banderas en tiempo de ejecución te permiten configurar la cantidad de acceso a los recursos de CPU que tiene tu contenedor. Cuando utilizas estas configuraciones, Docker modifica los ajustes para el cgroup del contenedor en la máquina host.

| Opción                 | Descripción                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--cpus=<value>`       | Especifica qué cantidad de los recursos de CPU disponibles puede utilizar un contenedor. Por ejemplo, si la máquina host tiene dos CPUs y configuras `--cpus="1.5"`, se garantiza al contenedor como máximo una CPU y media. Esto equivale a configurar `--cpu-period="100000"` y `--cpu-quota="150000"`.                                                                                                                                                                                                                                                                                              |
| `--cpu-period=<value>` | Especifica el período del programador CFS de CPU, que se utiliza junto con `--cpu-quota`. El valor predeterminado es 100000 microsegundos (100 milisegundos). La mayoría de los usuarios no cambian este valor. Para la mayoría de los casos de uso, `--cpus` es una alternativa más conveniente.                                                                                                                                                                                                                                                                                                                                                     |
| `--cpu-quota=<value>`  | Impone una cuota de CPU CFS al contenedor. El número de microsegundos por `--cpu-period` al que se limita el contenedor antes de ser restringido. De este modo actúa como el límite máximo efectivo. Para la mayoría de los casos de uso, `--cpus` es una alternativa más conveniente.                                                                                                                                                                                                                                                                                                                                                  |
| `--cpuset-cpus`        | Limita las CPUs o núcleos específicos que puede utilizar un contenedor. Una lista separada por comas o un rango separado por guiones de las CPUs que puede utilizar un contenedor, si dispones de más de una CPU. La primera CPU se numera como 0. Un valor válido podría ser `0-3` (para usar la primera, segunda, tercera y cuarta CPU) o `1,3` (para usar la segunda y cuarta CPU).                                                                                                                                                                                                                                                                        |
| `--cpu-shares`         | Configura esta bandera con un valor superior o inferior al valor predeterminado de 1024 para aumentar o reducir el peso del contenedor y darle acceso a una proporción mayor o menor de los ciclos de CPU de la máquina host. Esto solo se aplica cuando los ciclos de CPU están limitados. Cuando hay suficientes ciclos de CPU disponibles, todos los contenedores utilizan tanta CPU como necesiten. De este modo, se trata de un límite flexible. `--cpu-shares` no impide que los contenedores se programen en modo Swarm. Prioriza los recursos de CPU del contenedor para los ciclos de CPU disponibles. No garantiza ni reserva ningún acceso de CPU específico. |

Si tienes 1 CPU, cada uno de los siguientes comandos garantiza al contenedor como máximo el 50% de la CPU cada segundo.

```console
$ docker run -it --cpus=".5" ubuntu /bin/bash
```

Lo cual equivale a especificar manualmente `--cpu-period` y `--cpu-quota`:

```console
$ docker run -it --cpu-period=100000 --cpu-quota=50000 ubuntu /bin/bash
```

### Configurar el programador en tiempo real

Puedes configurar tu contenedor para utilizar el programador en tiempo real para tareas que no pueden utilizar el programador CFS. Debes [asegurarte de que el kernel de la máquina host esté configurado correctamente](#configure-the-host-machines-kernel) antes de poder [configurar el demonio de Docker](#configure-the-docker-daemon) o [configurar contenedores individuales](#configure-individual-containers).

> [!WARNING]
>
> La programación y priorización de la CPU son características avanzadas a nivel de kernel. La mayoría de los usuarios no necesitan cambiar estos valores de sus valores predeterminados. Configurar estos valores de forma incorrecta puede provocar que tu sistema host se vuelva inestable o inutilizable.

#### Configurar el kernel de la máquina host

Verifica que `CONFIG_RT_GROUP_SCHED` esté habilitado en el kernel de Linux ejecutando `zcat /proc/config.gz | grep CONFIG_RT_GROUP_SCHED` o comprobando la existencia del archivo `/sys/fs/cgroup/cpu.rt_runtime_us`. Para obtener orientación sobre cómo configurar el programador en tiempo real del kernel, consulta la documentación de tu sistema operativo.

#### Configurar el demonio de Docker

Para ejecutar contenedores utilizando el programador en tiempo real, ejecuta el demonio de Docker con la bandera `--cpu-rt-runtime` establecida en el número máximo de microsegundos reservados para tareas en tiempo real por período de tiempo de ejecución. Por ejemplo, con el período predeterminado de 1000000 microsegundos (1 segundo), establecer `--cpu-rt-runtime=950000` garantiza que los contenedores que utilizan el programador en tiempo real puedan ejecutarse durante 950000 microsegundos por cada período de 1000000 de microsegundos, dejando al menos 50000 microsegundos disponibles para tareas que no son en tiempo real. Para hacer esta configuración permanente en sistemas que utilizan `systemd`, crea un archivo de unidad de systemd para el servicio `docker`. Por ejemplo, consulta las instrucciones sobre cómo configurar el demonio para usar un proxy con un [archivo de unidad de systemd](/engine/daemon/proxy/#systemd-unit-file).

#### Configurar contenedores individuales

Puedes pasar varias banderas para controlar la prioridad de CPU de un contenedor cuando inicias el contenedor utilizando `docker run`. Consulta la documentación de tu sistema operativo o el comando `ulimit` para obtener información sobre los valores adecuados.

| Opción                     | Descripción                                                                                                                                                                               |
| :------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--cap-add=sys_nice`       | Otorga al contenedor la capacidad `CAP_SYS_NICE`, lo que le permite aumentar los valores `nice` del proceso, establecer políticas de programación en tiempo real, establecer la afinidad de la CPU y otras operaciones. |
| `--cpu-rt-runtime=<value>` | El número máximo de microsegundos que el contenedor puede ejecutarse con prioridad en tiempo real dentro del período del programador en tiempo real del demonio de Docker. También necesitas la bandera `--cap-add=sys_nice`.        |
| `--ulimit rtprio=<value>`  | La prioridad máxima en tiempo real permitida para el contenedor. También necesitas la bandera `--cap-add=sys_nice`.                                                                                    |

El siguiente comando de ejemplo establece cada una de estas tres banderas en un contenedor `debian:jessie`.

```console
$ docker run -it \
    --cpu-rt-runtime=950000 \
    --ulimit rtprio=99 \
    --cap-add=sys_nice \
    debian:jessie
```

Si el kernel o el demonio de Docker no están configurados correctamente, se produce un error.

## GPU

Para obtener información sobre cómo acceder a las GPUs de NVIDIA desde un contenedor, consulta [Acceso a la GPU](/engine/containers/resource_constraints/gpu/).

