

# Uso de montajes de unión con Amazon ECS
<a name="bind-mounts"></a>

Con los montajes de unión, se monta un archivo o directorio de un host en un contenedor, como, por ejemplo, una instancia de Amazon EC2. Se admiten montajes de enlace para tareas que están alojadas en instancias de Fargate y Amazon EC2. Los montajes de unión están vinculados al ciclo de vida del contenedor que los utiliza. Una vez que se detienen todos los contenedores que utilizan un montaje de enlace, como cuando se detiene una tarea, se eliminan los datos. En el caso de las tareas que están alojadas en instancias de Amazon EC2, para vincular los datos al ciclo de vida de la instancia de Amazon EC2 del host, se puede especificar un `host` y un valor de `sourcePath` opcional en la definición de tareas. Para obtener más información, consulte [Montajes vinculados](https://docs.docker.com/engine/storage/bind-mounts/) en la documentación de Docker.

A continuación, se indican algunos casos de uso comunes de los montajes de enlace.
+ Para proporcionar un volumen de datos vacío y montarlo en uno o más contenedores.
+ Para montar un volumen de datos del host en uno o más contenedores.
+ Para compartir un volumen de datos de un contenedor de origen con otros contenedores de la misma tarea.
+ Para exponer una ruta de acceso y su contenido desde un Dockerfile a uno o más contenedores.

## Consideraciones acerca del uso de los montajes de enlace
<a name="bind-mount-considerations"></a>

Al utilizar montajes de enlace, tenga en cuenta lo siguiente.
+ De manera predeterminada, las tareas alojadas en AWS Fargate que utilizan la versión de la plataforma `1.4.0` o una posterior (Linux) o `1.0.0` o una posterior (Windows) reciben un mínimo de 20 GiB de almacenamiento efímero para los montajes de unión. Para aumentar la cantidad total de almacenamiento efímero, hasta un máximo de 200 GiB, indique el parámetro `ephemeralStorage` en la definición de tareas.
+ Para exponer los archivos de un Dockerfile a un volumen de datos cuando se ejecuta una tarea, el plano de datos de Amazon ECS busca una directiva `VOLUME`. Si la ruta absoluta especificada en la directiva `VOLUME` es la misma que la `containerPath` especificada en la definición de tarea, los datos de la ruta de la directiva `VOLUME` se copian en el volumen de datos. En el siguiente ejemplo de Dockerfile, un archivo con el nombre `examplefile` en el directorio `/var/log/exported` se escribe en el host y, a continuación, se monta dentro del contenedor.

  ```
  FROM public.ecr.aws/amazonlinux/amazonlinux:latest
  RUN mkdir -p /var/log/exported
  RUN touch /var/log/exported/examplefile
  VOLUME ["/var/log/exported"]
  ```

  De forma predeterminada, los permisos de los volúmenes se establecen en`0755` y el propietario como `root`. Puede personalizar estos permisos en el Dockerfile. En el siguiente ejemplo, se define al propietario del directorio como `node`.

  ```
  FROM public.ecr.aws/amazonlinux/amazonlinux:latest
  RUN yum install -y shadow-utils && yum clean all
  RUN useradd node
  RUN mkdir -p /var/log/exported && chown node:node /var/log/exported
  RUN touch /var/log/exported/examplefile
  USER node
  VOLUME ["/var/log/exported"]
  ```
+ Para las tareas que están alojadas en instancias de Amazon EC2, cuando no se especifica el valor de `host` ni de `sourcePath`, es el daemon de Docker el que administra el montaje de enlace. Cuando ningún contenedor hace referencia a este montaje de enlace, el servicio de limpieza de tareas del agente de contenedor de Amazon ECS lo elimina finalmente. De forma predeterminada, esto sucede tres horas después de que el contenedor se cierre. Sin embargo, es posible configurar esta duración con la variable de agente `ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION`. Para obtener más información, consulte [Configuración del agente de contenedor de Amazon ECS](ecs-agent-config.md). Si necesita que estos datos persistan más allá del ciclo de vida del contenedor, especifique un valor de `sourcePath` para el montaje de enlace.
+ En el caso de las tareas alojadas en instancias administradas por Amazon ECS, algunas partes del sistema de archivos del host son de solo lectura. Los montajes de enlace de lectura/escritura deben utilizar directorios que admitan escritura, por ejemplo, `/var` para datos persistentes o `/tmp` para datos temporales. Si se intenta crear montajes de enlace de lectura y escritura en otros directorios, la tarea no se podrá iniciar y se producirá un error similar al siguiente:

  ```
  error creating empty volume: error while creating volume path '/path': mkdir /path: read-only file system
  ```

  Los montajes de enlace de solo lectura (configurados con `"readOnly": true` en el parámetro `mountPoints`) pueden apuntar a cualquier directorio accesible del host.

  Para ver una lista completa de rutas que admiten escritura, puede ejecutar una tarea en una instancia administrada por Amazon ECS y utilizarla para inspeccionar la tabla de montaje de la instancia. Cree una definición de tarea con los siguientes ajustes para acceder al sistema de archivos del host:

  ```
  {
      "pidMode": "host",
      "containerDefinitions": [{
          "privileged": true,
          ...
      }]
  }
  ```

  A continuación, ejecute los siguientes comandos desde dentro del contenedor:

  ```
  # List writable mounts
  cat /proc/1/root/proc/1/mounts | awk '$4 ~ /^rw,/ || $4 == "rw" {print $2}' | sort
  
  # List read-only mounts
  cat /proc/1/root/proc/1/mounts | awk '$4 ~ /^ro,/ || $4 == "ro" {print $2}' | sort
  ```
**importante**  
La configuración `privileged` otorga al contenedor capacidades ampliadas en el host, equivalentes al acceso raíz. En este ejemplo, se utiliza para inspeccionar la tabla de montaje del host con fines de diagnóstico. Para obtener más información, consulte [Evitar ejecutar contenedores con privilegios (Amazon EC2)](security-tasks-containers.md#security-tasks-containers-recommendations-avoid-privileged-containers).

  Para obtener más información sobre la ejecución de comandos interactivos en contenedores, consulte [Supervisión de los contenedores de Amazon ECS con ECS Exec](ecs-exec.md).

# Especificación de un montaje de unión en la definición de tareas de Amazon ECS
<a name="specify-bind-mount-config"></a>

En el siguiente fragmento de JSON de definición de tareas, se muestra la sintaxis de los objetos `volumes`, `mountPoints` y `ephemeralStorage` para una definición de las tareas de Amazon ECS alojadas en instancias de Amazon EC2 o Fargate.

```
{
   "family": "",
   ...
   "containerDefinitions" : [
      {
         "mountPoints" : [
            {
               "containerPath" : "/path/to/mount_volume",
               "sourceVolume" : "string"
            }
          ],
          "name" : "string"
       }
    ],
    ...
    "volumes" : [
       {
          "name" : "string"
       }
    ],
    "ephemeralStorage": {
	   "sizeInGiB": integer
    }
}
```

Para las tareas de Amazon ECS que están alojadas en instancias de Amazon EC2, puede utilizar el parámetro `host` opcional y un `sourcePath` al especificar los detalles del volumen de tareas. Cuando se especifica, vincula el montaje de enlace al ciclo de vida de la tarea en lugar del contenedor.

```
"volumes" : [
    {
        "host" : {
            "sourcePath" : "string"
        },
        "name" : "string"
    }
]
```

A continuación, se describe en más detalle cada uno de los parámetros de la definición de tarea.

`name`  
Tipo: cadena  
Requerido: no  
El nombre del volumen. Se admiten hasta 255 letras (mayúsculas y minúsculas), números, guiones (`-`) y caracteres de subrayado (`_`). Se hace referencia a este nombre en el parámetro `sourceVolume` del objeto `mountPoints` de la definición de contenedor.

`host`  
Obligatorio: no  
El parámetro `host` se utiliza para vincular el ciclo de vida del montaje de enlace a la instancia de Amazon EC2 del host, en lugar de a la tarea, y donde se almacena. Si el parámetro `host` está vacío, entonces el daemon de Docker asigna una ruta de host a su volumen de datos, pero no se garantiza que los datos persistan después de que los contenedores asociados dejen de funcionar.  
Los contenedores de Windows pueden montar directorios completos en la misma unidad que `$env:ProgramData`.  
El parámetro `sourcePath` se admite solo cuando se utilizan las tareas que se alojan en instancias de Amazon EC2 o instancias administradas de Amazon ECS.  
`sourcePath`  
Tipo: cadena  
Requerido: no  
Cuando utilice el parámetro `host`, especifique una `sourcePath` para declarar la ruta de la instancia de Amazon EC2 del host que se presenta al contenedor. Si este parámetro está vacío, el daemon de Docker asigna una ruta de host. Si el parámetro `host` contiene una ubicación de archivos `sourcePath`, el volumen de datos persiste en la ubicación especificada en la instancia de Amazon EC2 del host hasta que la elimine manualmente. Si el valor `sourcePath` no existe en la instancia de Amazon EC2 del host, el daemon de Docker lo crea. Si la ubicación existe, el contenido de la carpeta de la ruta de origen se exporta.

`mountPoints`  
Tipo: matriz de objetos  
Obligatorio: no  
Puntos de montaje para los volúmenes de datos del contenedor. Este parámetro asigna a `Volumes` en la API create-container de Docker y la opción `--volume` a docker run.  
Los contenedores de Windows pueden montar directorios completos en la misma unidad que `$env:ProgramData`. Los contenedores de Windows no pueden montar directorios en una unidad diferente y los puntos de montaje no se pueden utilizar entre unidades. Debe especificar los puntos de montaje para adjuntar un volumen de Amazon EBS directamente a una tarea de Amazon ECS.    
`sourceVolume`  
Tipo: cadena  
Obligatorio: sí, si se utilizan `mountPoints`.  
El nombre del volumen a montar.  
`containerPath`  
Tipo: cadena  
Obligatorio: sí, si se utilizan `mountPoints`.  
La ruta del contenedor donde se montará el volumen.  
`readOnly`  
Tipo: Booleano  
Obligatorio: no  
Si este valor es `true`, el acceso del contenedor al volumen es de solo lectura. Si este valor es `false`, el contenedor puede escribir en el volumen. El valor predeterminado es `false`.  
Para las tareas que se ejecutan en instancias de EC2 con sistema operativo Windows, deje el valor predeterminado `false`.

`ephemeralStorage`  
Tipo: objeto  
Obligatorio: no  
Cantidad de almacenamiento efímero que se asignará a la tarea. Este parámetro se utiliza para expandir la cantidad total de almacenamiento efímero disponible, más allá de la cantidad predeterminada, para las tareas alojadas en AWS Fargate que utilizan la versión `1.4.0` o posterior (Linux) o `1.0.0` o posterior (Windows) de la plataforma.  
Se puede utilizar la CLI de Copilot, CloudFormation, el SDK de AWS o la CLI para especificar almacenamiento efímero para un montaje de enlace.

# Ejemplos de montajes vinculados para Amazon ECS
<a name="bind-mount-examples"></a>

En los siguientes ejemplos se cubren los casos de uso más comunes de montaje vinculado para los contenedores.

**Para asignar una mayor cantidad de espacio de almacenamiento efímero a una tarea de Fargate**

Para las tareas de Amazon ECS alojadas en Fargate que utilizan la versión `1.4.0` o posterior (Linux) o `1.0.0` (Windows) de la plataforma, se puede asignar una cantidad mayor de almacenamiento efímero que la predeterminada para que la utilicen los contenedores de la tarea. Este ejemplo se puede incorporar a los otros ejemplos para asignar un almacenamiento más efímero para sus tareas de Fargate.
+ En la definición de tarea, defina un objeto `ephemeralStorage`. El valor de `sizeInGiB` se expresa en GiB y debe ser un número entero entre `21` y `200`.

  ```
  "ephemeralStorage": {
      "sizeInGiB": integer
  }
  ```

**Para proporcionar un volumen de datos vacío para uno o más contenedores**

En algunos casos, es posible que desee proporcionar a los contenedores de una tarea algo de espacio de almacenamiento temporal. Por ejemplo, podría tener dos contenedores de base de datos que deben acceder a la misma ubicación de almacenamiento de archivos scratch durante una tarea. Esto se puede lograr con un montaje de enlace.

1. En la sección de definición de tarea `volumes`, defina un montaje vinculado con el nombre `database_scratch`.

   ```
     "volumes": [
       {
         "name": "database_scratch"
       }
     ]
   ```

1. En la sección `containerDefinitions`, cree las definiciones de contenedor de base de datos. Esto es para que monten el volumen.

   ```
   "containerDefinitions": [
       {
         "name": "database1",
         "image": "my-repo/database",
         "cpu": 100,
         "memory": 100,
         "essential": true,
         "mountPoints": [
           {
             "sourceVolume": "database_scratch",
             "containerPath": "/var/scratch"
           }
         ]
       },
       {
         "name": "database2",
         "image": "my-repo/database",
         "cpu": 100,
         "memory": 100,
         "essential": true,
         "mountPoints": [
           {
             "sourceVolume": "database_scratch",
             "containerPath": "/var/scratch"
           }
         ]
       }
     ]
   ```

**Para exponer una ruta y su contenido en un Dockerfile a un contenedor**

En este ejemplo, tiene un Dockerfile que escribe los datos que va a montar dentro de un contenedor. Este ejemplo funciona para tareas que están alojadas en instancias de Fargate o Amazon EC2.

1. Cree un Dockerfile. En el siguiente ejemplo, se utiliza la imagen de contenedor pública de Amazon Linux 2 y se crea un archivo con el nombre `examplefile` en el directorio `/var/log/exported` que queremos montar dentro del contenedor. La directiva `VOLUME` debe especificar una ruta absoluta.

   ```
   FROM public.ecr.aws/amazonlinux/amazonlinux:latest
   RUN mkdir -p /var/log/exported
   RUN touch /var/log/exported/examplefile
   VOLUME ["/var/log/exported"]
   ```

   De forma predeterminada, los permisos de los volúmenes se establecen en`0755` y el propietario como `root`. Estos permisos se pueden cambiar en el Dockerfile. En el ejemplo siguiente, el propietario del directorio `/var/log/exported` se establece como `node`.

   ```
   FROM public.ecr.aws/amazonlinux/amazonlinux:latest
   RUN yum install -y shadow-utils && yum clean all
   RUN useradd node
   RUN mkdir -p /var/log/exported && chown node:node /var/log/exported					    
   USER node
   RUN touch /var/log/exported/examplefile
   VOLUME ["/var/log/exported"]
   ```

1. En la sección de definición de tarea de `volumes`, defina un volumen con el nombre `application_logs`.

   ```
     "volumes": [
       {
         "name": "application_logs"
       }
     ]
   ```

1. En la sección `containerDefinitions`, cree las definiciones de contenedor de aplicaciones. Esto es para que monten el almacenamiento. El valor de `containerPath` debe coincidir con la ruta absoluta especificada en la directiva `VOLUME` del Dockerfile.

   ```
     "containerDefinitions": [
       {
         "name": "application1",
         "image": "my-repo/application",
         "cpu": 100,
         "memory": 100,
         "essential": true,
         "mountPoints": [
           {
             "sourceVolume": "application_logs",
             "containerPath": "/var/log/exported"
           }
         ]
       },
       {
         "name": "application2",
         "image": "my-repo/application",
         "cpu": 100,
         "memory": 100,
         "essential": true,
         "mountPoints": [
           {
             "sourceVolume": "application_logs",
             "containerPath": "/var/log/exported"
           }
         ]
       }
     ]
   ```

**Para proporcionar un volumen de datos vacío para un contenedor que está vinculado al ciclo de vida de la instancia de Amazon EC2 del host**

Para las tareas que están alojadas en instancias de Amazon EC2, se pueden utilizar montajes de enlace y vincular los datos al ciclo de vida de la instancia de Amazon EC2 del host. Para ello, se utiliza el parámetro `host` y se especifica un valor de `sourcePath`. Cualquier archivo que exista en `sourcePath` se presenta a los contenedores con el valor `containerPath`. Cualquier archivo que se escriba en el valor `containerPath`, se escribe en el valor `sourcePath` en la instancia de Amazon EC2 del host.
**importante**  
Amazon ECS no sincroniza el almacenamiento en todas las instancias de Amazon EC2. Las tareas que utilizan almacenamiento persistente se pueden colocar en cualquier instancia de Amazon EC2 del clúster que tenga capacidad disponible. Si las tareas requieren almacenamiento persistente después de detenerse y reiniciarse, especifique siempre la misma instancia de Amazon EC2 en el momento de lanzar la tarea con el comando [start-task](https://docs.aws.amazon.com/cli/latest/reference/ecs/start-task.html) de la AWS CLI. También puede utilizar volúmenes de Amazon EFS para el almacenamiento persistente. Para obtener más información, consulte [Uso de volúmenes de Amazon EFS con Amazon ECS](efs-volumes.md).

1. En la sección de la definición de tarea `volumes`, defina un montaje vinculado con los valores de `name` y `sourcePath`. En el ejemplo siguiente, la instancia de Amazon EC2 del host contiene datos de `/ecs/webdata` que va a montar dentro del contenedor.

   ```
     "volumes": [
       {
         "name": "webdata",
         "host": {
           "sourcePath": "/ecs/webdata"
         }
       }
     ]
   ```

1. En la sección `containerDefinitions`, defina un contenedor con un valor de `mountPoints` que haga referencia al nombre del montaje de enlace y el valor de `containerPath` en el que va a realizar el montaje de enlace en el contenedor.

   ```
     "containerDefinitions": [
       {
         "name": "web",
         "image": "public.ecr.aws/docker/library/nginx:latest",
         "cpu": 99,
         "memory": 100,
         "portMappings": [
           {
             "containerPort": 80,
             "hostPort": 80
           }
         ],
         "essential": true,
         "mountPoints": [
           {
             "sourceVolume": "webdata",
             "containerPath": "/usr/share/nginx/html"
           }
         ]
       }
     ]
   ```

**Para montar un volumen definido en varios contenedores en diferentes ubicaciones**

Puede definir un volumen de datos en una definición de tarea y montarlo en diferentes ubicaciones en distintos contenedores. Por ejemplo, el contenedor del host tiene una carpeta de datos del sitio web en `/data/webroot`. Es posible que desee montar ese volumen de datos como de solo lectura en dos servidores web diferentes que tengan diferentes raíces de documentos.

1. En la sección de definición de tarea de `volumes`, defina un volumen de datos con el nombre `webroot` y la ruta de origen `/data/webroot`.

   ```
     "volumes": [
       {
         "name": "webroot",
         "host": {
           "sourcePath": "/data/webroot"
         }
       }
     ]
   ```

1. En la sección `containerDefinitions`, defina un contenedor para cada servidor web con valores de `mountPoints` que permitan asociar el volumen de `webroot` con el valor de `containerPath` apuntando a la raíz de documentos para ese contenedor.

   ```
     "containerDefinitions": [
       {
         "name": "web-server-1",
         "image": "my-repo/ubuntu-apache",
         "cpu": 100,
         "memory": 100,
         "portMappings": [
           {
             "containerPort": 80,
             "hostPort": 80
           }
         ],
         "essential": true,
         "mountPoints": [
           {
             "sourceVolume": "webroot",
             "containerPath": "/var/www/html",
             "readOnly": true
           }
         ]
       },
       {
         "name": "web-server-2",
         "image": "my-repo/sles11-apache",
         "cpu": 100,
         "memory": 100,
         "portMappings": [
           {
             "containerPort": 8080,
             "hostPort": 8080
           }
         ],
         "essential": true,
         "mountPoints": [
           {
             "sourceVolume": "webroot",
             "containerPath": "/srv/www/htdocs",
             "readOnly": true
           }
         ]
       }
     ]
   ```

**Para montar volúmenes desde otro contenedor con `volumesFrom`**

Para las tareas alojadas en instancias de Amazon EC2, puede definir uno o más volúmenes en un contenedor y, a continuación, utilizar el parámetro `volumesFrom` en una definición de contenedor diferente dentro de la misma tarea para montar todos los volúmenes de `sourceContainer` en sus puntos de montaje definidos originalmente. El parámetro `volumesFrom` se aplica a volúmenes definidos en la definición de tarea, y a los que están integrados en la imagen con un Dockerfile.

1. (Opcional) Para compartir un volumen integrado en una imagen, utilice la instrucción `VOLUME` del Dockerfile. En el siguiente ejemplo de Dockerfile se utiliza una imagen `httpd` y, a continuación, se agrega un volumen y se lo monta en `dockerfile_volume` en la raíz de documentos de Apache. Es la carpeta que utiliza el servidor web `httpd`.

   ```
   FROM httpd
   VOLUME ["/usr/local/apache2/htdocs/dockerfile_volume"]
   ```

   Puede crear una imagen con este Dockerfile y enviarla a un repositorio, como Docker Hub, y utilizarla en su definición de tarea. La imagen de ejemplo `my-repo/httpd_dockerfile_volume` que se utiliza en los pasos siguientes se diseñó con el Dockerfile anterior.

1. Cree una definición de tarea que defina los otros volúmenes y puntos de montaje para los contenedores. En esta sección de ejemplo `volumes`, se crea un volumen vacío llamado `empty`, que será administrado por el daemon de Docker. También hay un volumen de host definido denominado `host_etc`. Exporta la carpeta `/etc` en la instancia de contenedor del host.

   ```
   {
     "family": "test-volumes-from",
     "volumes": [
       {
         "name": "empty",
         "host": {}
       },
       {
         "name": "host_etc",
         "host": {
           "sourcePath": "/etc"
         }
       }
     ],
   ```

   En la sección de definiciones de contenedor, cree un contenedor para montar los volúmenes definidos anteriormente. En este ejemplo, el contenedor `web` monta los volúmenes `empty` y `host_etc`. Este es el contenedor que utiliza la imagen creada con un volumen en el Dockerfile.

   ```
   "containerDefinitions": [
       {
         "name": "web",
         "image": "my-repo/httpd_dockerfile_volume",
         "cpu": 100,
         "memory": 500,
         "portMappings": [
           {
             "containerPort": 80,
             "hostPort": 80
           }
         ],
         "mountPoints": [
           {
             "sourceVolume": "empty",
             "containerPath": "/usr/local/apache2/htdocs/empty_volume"
           },
           {
             "sourceVolume": "host_etc",
             "containerPath": "/usr/local/apache2/htdocs/host_etc"
           }
         ],
         "essential": true
       },
   ```

   Cree otro contenedor que utiliza `volumesFrom` para montar todos los volúmenes que están asociados con el contenedor `web`. Todos los volúmenes del contenedor `web` se montan también en el contenedor `busybox`. Esto incluye el volumen especificado en el Dockerfile que se utilizó para crear la imagen `my-repo/httpd_dockerfile_volume`.

   ```
       {
         "name": "busybox",
         "image": "busybox",
         "volumesFrom": [
           {
             "sourceContainer": "web"
           }
         ],
         "cpu": 100,
         "memory": 500,
         "entryPoint": [
           "sh",
           "-c"
         ],
         "command": [
           "echo $(date) > /usr/local/apache2/htdocs/empty_volume/date && echo $(date) > /usr/local/apache2/htdocs/host_etc/date && echo $(date) > /usr/local/apache2/htdocs/dockerfile_volume/date"
         ],
         "essential": false
       }
     ]
   }
   ```

   Cuando esta tarea se ejecuta, los dos contenedores montan los volúmenes y el `command` en el contenedor `busybox` escribe la fecha y la hora en un archivo. Este archivo se denomina `date` en cada una de las carpetas de volumen. Las carpetas se pueden ver en el sitio web mostrado por el contenedor `web`.
**nota**  
Como el contenedor `busybox` ejecuta un comando rápido y, a continuación, se cierra, debe establecerse como `"essential": false` en la definición de contenedor. De no ser así, detiene toda la tarea cuando se cierra.