# Controlador de almacenamiento OverlayFS


OverlayFS es un sistema de archivos de unión (union filesystem).

Esta página se refiere al controlador del kernel Linux como `OverlayFS` y al controlador de almacenamiento de Docker como `overlay2`.

> [!NOTE]
> Docker Engine 29.0 y versiones posteriores utilizan el
> [almacén de imágenes de containerd](/engine/storage/containerd/) de forma predeterminada.
> El controlador `overlay2` es un controlador de almacenamiento heredado (legacy) que ha sido reemplazado
> por el snapshotter `overlayfs` de containerd. Para obtener más información, consulta
> [Seleccionar un controlador de almacenamiento](/engine/storage/drivers/select-storage-driver/).

> [!NOTE]
> Para el controlador `fuse-overlayfs`, consulta la [documentación del modo Rootless](/engine/security/rootless/).

## Requisitos previos

El controlador `overlay2` es compatible si cumples con los siguientes requisitos previos:

- Versión 4.0 o superior del kernel Linux, o RHEL o CentOS utilizando la versión 3.10.0-514 del kernel o superior.
- El controlador `overlay2` es compatible con sistemas de archivos de respaldo `xfs`, pero solo con `d_type=true` habilitado.
  Utiliza `xfs_info` para verificar que la opción `ftype` esté establecida en `1`. Para formatear correctamente un sistema de archivos `xfs`, usa la bandera `-n ftype=1`.
- Cambiar el controlador de almacenamiento hace que los contenedores e imágenes existentes dejen de estar accesibles en el sistema local. Usa `docker save` para guardar las imágenes que hayas creado o envíalas a Docker Hub o a un registro privado antes de cambiar el controlador de almacenamiento, de modo que no tengas que volver a crearlas más tarde.

## Configurar Docker con el controlador de almacenamiento `overlay2`

<a name="configure-docker-with-the-overlay-or-overlay2-storage-driver"></a>

Antes de seguir este procedimiento, primero debes cumplir con todos los [requisitos previos](#requisitos-previos).

Los siguientes pasos describen cómo configurar el controlador de almacenamiento `overlay2`.

1. Detén Docker.

   ```console
   $ sudo systemctl stop docker
   ```

2. Copia el contenido de `/var/lib/docker` en una ubicación temporal.

   ```console
   $ cp -au /var/lib/docker /var/lib/docker.bk
   ```

3. Si deseas utilizar un sistema de archivos de respaldo independiente del utilizado por `/var/lib/`, formatea el sistema de archivos y móntalo en `/var/lib/docker`. Asegúrate de añadir este montaje a `/etc/fstab` para que sea permanente.

4. Edita `/etc/docker/daemon.json`. Si aún no existe, créalo. Suponiendo que el archivo estuviera vacío, añade el siguiente contenido.

   ```json
   {
     "storage-driver": "overlay2"
   }
   ```

   Docker no se iniciará si el archivo `daemon.json` contiene un JSON no válido.

5. Inicia Docker.

   ```console
   $ sudo systemctl start docker
   ```

6. Verifica que el demonio esté utilizando el controlador de almacenamiento `overlay2`. Usa el comando `docker info` y busca `Storage Driver` y `Backing filesystem`.

   ```console
   $ docker info

   Containers: 0
   Images: 0
   Storage Driver: overlay2
    Backing Filesystem: xfs
    Supports d_type: true
    Native Overlay Diff: true
   <...>
   ```

Docker ahora está utilizando el controlador de almacenamiento `overlay2` y ha creado automáticamente el montaje overlay con las estructuras requeridas `lowerdir`, `upperdir`, `merged` y `workdir`.

Continúa leyendo para obtener detalles sobre cómo funciona OverlayFS dentro de tus contenedores de Docker, así como consejos de rendimiento e información sobre las limitaciones de su compatibilidad con diferentes sistemas de archivos de respaldo.

## Cómo funciona el controlador `overlay2`

OverlayFS superpone dos directorios en un único host Linux y los presenta como un solo directorio. Estos directorios se denominan capas y el proceso de unificación se conoce como un montaje de unión (union mount). OverlayFS se refiere al directorio inferior como `lowerdir` y al directorio superior como `upperdir`. La vista unificada se expone a través de su propio directorio llamado `merged`.

El controlador `overlay2` admite de forma nativa hasta 128 capas inferiores de OverlayFS. Esta capacidad proporciona un mejor rendimiento para los comandos de Docker relacionados con capas, como `docker build` y `docker commit`, y consume menos inodes en el sistema de archivos de respaldo.

### Capas de imágenes y contenedores en disco

Después de descargar una imagen de cinco capas utilizando `docker pull ubuntu`, puedes ver seis directorios bajo `/var/lib/docker/overlay2`.

> [!WARNING]
>
> No manipules directamente ningún archivo o directorio dentro de
> `/var/lib/docker/`. Docker se encarga de gestionar estos archivos y directorios.

```console
$ ls -l /var/lib/docker/overlay2

total 24
drwx------ 5 root root 4096 Jun 20 07:36 223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7
drwx------ 3 root root 4096 Jun 20 07:36 3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b
drwx------ 5 root root 4096 Jun 20 07:36 4e9fa83caff3e8f4cc83693fa407a4a9fac9573deaf481506c102d484dd1e6a1
drwx------ 5 root root 4096 Jun 20 07:36 e8876a226237217ec61c4baf238a32992291d059fdac95ed6303bdff3f59cff5
drwx------ 5 root root 4096 Jun 20 07:36 eca1e4e1694283e001f200a667bb3cb40853cf2d1b12c29feda7422fed78afed
drwx------ 2 root root 4096 Jun 20 07:36 l
```

El nuevo directorio `l` (L minúscula) contiene identificadores de capa acortados en forma de enlaces simbólicos. Estos identificadores se utilizan para evitar alcanzar el límite de tamaño de página en los argumentos del comando `mount`.

```console
$ ls -l /var/lib/docker/overlay2/l

total 20
lrwxrwxrwx 1 root root 72 Jun 20 07:36 6Y5IM2XC7TSNIJZZFLJCS6I4I4 -> ../3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/diff
lrwxrwxrwx 1 root root 72 Jun 20 07:36 B3WWEFKBG3PLLV737KZFIASSW7 -> ../4e9fa83caff3e8f4cc83693fa407a4a9fac9573deaf481506c102d484dd1e6a1/diff
lrwxrwxrwx 1 root root 72 Jun 20 07:36 JEYMODZYFCZFYSDABYXD5MF6YO -> ../eca1e4e1694283e001f200a667bb3cb40853cf2d1b12c29feda7422fed78afed/diff
lrwxrwxrwx 1 root root 72 Jun 20 07:36 NFYKDW6APBCCUCTOUSYDH4DXAT -> ../223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/diff
lrwxrwxrwx 1 root root 72 Jun 20 07:36 UL2MW33MSE3Q5VYIKBRN4ZAGQP -> ../e8876a226237217ec61c4baf238a32992291d059fdac95ed6303bdff3f59cff5/diff
```

La capa más baja contiene un archivo llamado `link`, que contiene el nombre del identificador acortado, y un directorio llamado `diff` que contiene el contenido de la capa.

```console
$ ls /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/

diff  link

$ cat /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/link

6Y5IM2XC7TSNIJZZFLJCS6I4I4

$ ls  /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/diff

bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
```

La segunda capa más baja, y cada capa superior, contienen un archivo llamado `lower` que indica su padre (parent), y un directorio llamado `diff` que contiene su contenido. También contiene un directorio `merged`, que contiene el contenido unificado de su capa padre y de sí misma, y un directorio `work` que OverlayFS utiliza internamente.

```console
$ ls /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7

diff  link  lower  merged  work

$ cat /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/lower

l/6Y5IM2XC7TSNIJZZFLJCS6I4I4

$ ls /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/diff/

etc  sbin  usr  var
```

Para ver los montajes que existen cuando utilizas el controlador de almacenamiento `overlay` con Docker, usa el comando `mount`. La salida a continuación se ha acortado para mayor legibilidad.

```console
$ mount | grep overlay

overlay on /var/lib/docker/overlay2/9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/merged
type overlay (rw,relatime,
lowerdir=l/DJA75GUWHWG7EWICFYX54FIOVT:l/B3WWEFKBG3PLLV737KZFIASSW7:l/JEYMODZYFCZFYSDABYXD5MF6YO:l/UL2MW33MSE3Q5VYIKBRN4ZAGQP:l/NFYKDW6APBCCUCTOUSYDH4DXAT:l/6Y5IM2XC7TSNIJZZFLJCS6I4I4,
upperdir=9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/diff,
workdir=9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/work)
```

El `rw` en la segunda línea indica que el montaje `overlay` es de lectura y escritura.

El siguiente diagrama muestra cómo se apilan una imagen de Docker y un contenedor de Docker. La capa de la imagen es el `lowerdir` y la capa del contenedor es el `upperdir`. Si la imagen tiene varias capas, se utilizan múltiples directorios `lowerdir`. La vista unificada se expone a través de un directorio llamado `merged`, que es efectivamente el punto de montaje del contenedor.

![Cómo se asignan las estructuras de Docker a las de OverlayFS](/engine/storage/drivers/overlayfs-driver/images/overlay_constructs.webp)

Cuando la capa de la imagen y la capa del contenedor contienen los mismos archivos, la capa del contenedor (`upperdir`) tiene prioridad y oculta la existencia de los mismos archivos en la capa de la imagen.

Para crear un contenedor, el controlador `overlay2` combina el directorio que representa la capa superior de la imagen más un nuevo directorio para el contenedor. Las capas de la imagen son los `lowerdirs` en el overlay y son de solo lectura. El nuevo directorio para el contenedor es el `upperdir` y es de escritura.

### Capas de imágenes y contenedores en disco (controlador overlay heredado)

El siguiente comando `docker pull` muestra un host Docker descargando una imagen de Docker que consta de cinco capas.

```console
$ docker pull ubuntu

Using default tag: latest
latest: Pulling from library/ubuntu

5ba4f30e5bea: Pull complete
9d7d19c9dc56: Pull complete
ac6ad7efd0f9: Pull complete
e7491a747824: Pull complete
a3ed95caeb02: Pull complete
Digest: sha256:46fb5d001b88ad904c5c732b086b596b92cfb4a4840a3abd0e35dbb6870585e4
Status: Downloaded newer image for ubuntu:latest
```

#### Las capas de la imagen

Cada capa de imagen tiene su propio directorio dentro de `/var/lib/docker/overlay/`, que contiene su contenido, como se muestra en el siguiente ejemplo. Los IDs de las capas de imagen no se corresponden con los IDs de los directorios.

> [!WARNING]
>
> No manipules directamente ningún archivo o directorio dentro de
> `/var/lib/docker/`. Docker se encarga de gestionar estos archivos y directorios.

```console
$ ls -l /var/lib/docker/overlay/

total 20
drwx------ 3 root root 4096 Jun 20 16:11 38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8
drwx------ 3 root root 4096 Jun 20 16:11 55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358
drwx------ 3 root root 4096 Jun 20 16:11 824c8a961a4f5e8fe4f4243dab57c5be798e7fd195f6d88ab06aea92ba931654
drwx------ 3 root root 4096 Jun 20 16:11 ad0fe55125ebf599da124da175174a4b8c1878afe6907bf7c78570341f308461
drwx------ 3 root root 4096 Jun 20 16:11 edab9b5e5bf73f2997524eebeac1de4cf9c8b904fa8ad3ec43b3504196aa3801
```

Los directorios de las capas de imágenes contienen los archivos exclusivos de esa capa, así como enlaces duros (hard links) a los datos compartidos con las capas inferiores. Esto permite un uso eficiente del espacio en disco.

```console
$ ls -i /var/lib/docker/overlay2/38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8/root/bin/ls

19793696 /var/lib/docker/overlay2/38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8/root/bin/ls

$ ls -i /var/lib/docker/overlay2/55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358/root/bin/ls

19793696 /var/lib/docker/overlay2/55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358/root/bin/ls
```

#### Las capa del contenedor

Los contenedores también existen en disco en el sistema de archivos del host Docker bajo `/var/lib/docker/overlay/`. Si listas el subdirectorio de un contenedor en ejecución con el comando `ls -l`, verás tres directorios y un archivo:

```console
$ ls -l /var/lib/docker/overlay2/<directory-of-running-container>

total 16
-rw-r--r-- 1 root root   64 Jun 20 16:39 lower-id
drwxr-xr-x 1 root root 4096 Jun 20 16:39 merged
drwxr-xr-x 4 root root 4096 Jun 20 16:39 upper
drwx------ 3 root root 4096 Jun 20 16:39 work
```

El archivo `lower-id` contiene el ID de la capa superior de la imagen en la que se basa el contenedor, que representa el `lowerdir` de OverlayFS.

```console
$ cat /var/lib/docker/overlay2/ec444863a55a9f1ca2df72223d459c5d940a721b2288ff86a3f27be28b53be6c/lower-id

55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358
```

El directorio `upper` contiene el contenido de la capa de lectura y escritura del contenedor, que corresponde al `upperdir` de OverlayFS.

El directorio `merged` es el montaje de unión de `lowerdir` y `upperdirs`, que constituye la vista del sistema de archivos desde dentro del contenedor en ejecución.

El directorio `work` es de uso interno para OverlayFS.

Para ver los montajes que existen cuando utilizas el controlador de almacenamiento `overlay2` con Docker, usa el comando `mount`. La siguiente salida se ha acortado para mayor legibilidad.

```console
$ mount | grep overlay

overlay on /var/lib/docker/overlay2/l/ec444863a55a.../merged
type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/55f1e14c361b.../root,
upperdir=/var/lib/docker/overlay2/l/ec444863a55a.../upper,
workdir=/var/lib/docker/overlay2/l/ec444863a55a.../work)
```

El `rw` en la segunda línea indica que el montaje `overlay` es de lectura y escritura.

## Cómo funcionan las lecturas y escrituras de contenedores con `overlay2`

<a name="how-container-reads-and-writes-work-with-overlay-or-overlay2"></a>

### Lectura de archivos

Considera tres escenarios en los que un contenedor abre un archivo para acceso de lectura con overlay.

#### El archivo no existe en la capa del contenedor

Si un contenedor abre un archivo para acceso de lectura y el archivo aún no existe en el contenedor (`upperdir`), se lee desde la imagen (`lowerdir`). Esto incurre en una sobrecarga de rendimiento muy baja.

#### El archivo solo existe en la capa del contenedor

Si un contenedor abre un archivo para acceso de lectura y el archivo existe en el contenedor (`upperdir`) y no en la imagen (`lowerdir`), se lee directamente desde el contenedor.

#### El archivo existe tanto en la capa del contenedor como en la capa de la imagen

Si un contenedor abre un archivo para acceso de lectura y el archivo existe en la capa de la imagen y en la capa del contenedor, se lee la versión del archivo en la capa del contenedor. Los archivos en la capa del contenedor (`upperdir`) ocultan los archivos con el mismo nombre en la capa de la imagen (`lowerdir`).

### Modificación de archivos o directorios

Considera algunos escenarios en los que se modifican archivos en un contenedor.

#### Escribir en un archivo por primera vez

La primera vez que un contenedor escribe en un archivo existente, ese archivo no existe en el contenedor (`upperdir`). El controlador `overlay2` realiza una operación `copy_up` para copiar el archivo desde la imagen (`lowerdir`) al contenedor (`upperdir`). Luego, el contenedor escribe los cambios en la nueva copia del archivo en la capa del contenedor.

Sin embargo, OverlayFS funciona a nivel de archivo en lugar de a nivel de bloque. Esto significa que todas las operaciones `copy_up` de OverlayFS copian el archivo completo, incluso si el archivo es grande y solo se modifica una pequeña parte de él. Esto puede tener un impacto notable en el rendimiento de escritura del contenedor. Sin embargo, vale la pena señalar dos cosas:

- La operación `copy_up` solo ocurre la primera vez que se escribe en un archivo determinado. Las escrituras posteriores en el mismo archivo se realizan sobre la copia del archivo que ya se ha copiado al contenedor.

- OverlayFS funciona con múltiples capas. Esto significa que el rendimiento se puede ver afectado al buscar archivos en imágenes con muchas capas.

#### Eliminación de archivos y directorios

- Cuando se elimina un _archivo_ dentro de un contenedor, se crea un archivo _whiteout_ en el contenedor (`upperdir`). La versión del archivo en la capa de la imagen (`lowerdir`) no se elimina (porque el `lowerdir` es de solo lectura). Sin embargo, el archivo whiteout impide que esté disponible para el contenedor.

- Cuando se elimina un _directorio_ dentro de un contenedor, se crea un _directorio opaco_ dentro del contenedor (`upperdir`). Esto funciona de la misma manera que un archivo whiteout e impide de forma efectiva que se acceda al directorio, aunque este siga existiendo en la imagen (`lowerdir`).

#### Renombrar directorios

Llamar a `rename(2)` para un directorio se permite solo cuando tanto la ruta de origen como la de destino están en la capa superior. De lo contrario, devuelve el error `EXDEV` ("enlace entre dispositivos no permitido"). Tu aplicación debe estar diseñada para manejar `EXDEV` y recurrir a una estrategia de "copiar y desenlazar".

## Rendimiento de OverlayFS y Docker

`overlay2` puede funcionar mejor que `btrfs`. Sin embargo, ten en cuenta los siguientes detalles:

### Caché de páginas

OverlayFS admite el uso compartido de la caché de páginas. Varios contenedores que acceden al mismo archivo comparten una única entrada de caché de página para ese archivo. Esto hace que el controlador `overlay2` sea eficiente con la memoria y una buena opción para casos de uso de alta densidad como PaaS.

### Copy-up

Al igual que con otros sistemas de archivos copy-on-write, OverlayFS realiza operaciones copy-up cada vez que un contenedor escribe en un archivo por primera vez. Esto puede añadir latencia a la operación de escritura, especialmente en archivos grandes. Sin embargo, una vez que el archivo ha sido copiado, todas las escrituras posteriores en ese archivo ocurren en la capa superior, sin necesidad de realizar más operaciones copy-up.

### Buenas prácticas de rendimiento

Las siguientes buenas prácticas de rendimiento generales se aplican a OverlayFS.

#### Utilizar almacenamiento rápido

Las unidades de estado sólido (SSD) proporcionan lecturas y escrituras más rápidas que los discos mecánicos.

#### Utilizar volúmenes para cargas de trabajo con uso intensivo de escritura

Los volúmenes ofrecen el mejor y más predecible rendimiento para cargas de trabajo con uso intensivo de escritura. Esto se debe a que omiten el controlador de almacenamiento y no incurren en ninguna de las posibles sobrecargas introducidas por el aprovisionamiento dinámico y copy-on-write. Los volúmenes tienen otros beneficios, como permitirte compartir datos entre contenedores y persistir tus datos incluso si ningún contenedor en ejecución los está utilizando.

## Limitaciones en la compatibilidad de OverlayFS

Para resumir los aspectos de OverlayFS que son incompatibles con otros sistemas de archivos:

[`open(2)`](https://linux.die.net/man/2/open)
: OverlayFS solo implementa un subconjunto de los estándares POSIX. Esto puede provocar que ciertas operaciones de OverlayFS infrinjan los estándares POSIX. Una de esas operaciones es la operación copy-up. Supón que tu aplicación llama a `fd1=open("foo", O_RDONLY)` y luego a `fd2=open("foo", O_RDWR)`. En este caso, tu aplicación espera que `fd1` y `fd2` se refieran al mismo archivo. Sin embargo, debido a una operación copy-up que ocurre después de la segunda llamada a `open(2)`, los descriptores se refieren a archivos diferentes. El descriptor `fd1` continúa haciendo referencia al archivo en la imagen (`lowerdir`) y `fd2` hace referencia al archivo en el contenedor (`upperdir`). Una solución para esto es ejecutar `touch` en los archivos, lo que obliga a que se realice la operación copy-up. Todas las operaciones `open(2)` posteriores, independientemente del modo de acceso de solo lectura o lectura-escritura, harán referencia al archivo en el contenedor (`upperdir`).

Se sabe que `yum` se ve afectado a menos que el paquete `yum-plugin-ovl` esté instalado. Si el paquete `yum-plugin-ovl` no está disponible en tu distribución (como en RHEL/CentOS anterior a 6.8 o 7.2), es posible que debas ejecutar `touch /var/lib/rpm/*` antes de ejecutar `yum install`. Este paquete implementa la solución alternativa `touch` mencionada anteriormente para `yum`.

[`rename(2)`](https://linux.die.net/man/2/rename)
: OverlayFS no admite completamente la llamada al sistema `rename(2)`. Tu aplicación debe detectar este fallo y recurrir a una estrategia de "copiar y desenlazar".

