

# Uso de montagens vinculadas com o Amazon ECS
<a name="bind-mounts"></a>

Com montagens vinculadas, um arquivo ou diretório em um host, como uma instância do Amazon EC2, é montado em um contêiner. As montagens bind são compatíveis com tarefas hospedadas em instâncias do Fargate e do Amazon EC2. Montagens vinculadas estão associadas ao ciclo de vida do contêiner que as usa. A partir do momento em que todos os contêineres que utilizam uma montagem bind forem interrompidos, por exemplo, quando uma tarefa é interrompida, os dados serão removidos. Para tarefas hospedadas em instâncias do Amazon EC2, os dados podem ser vinculados ao ciclo de vida da instância do Amazon EC2 do host especificando um `host` e um valor opcional de `sourcePath` na definição de tarefa. Para obter mais informações, consulte [Montagens bind](https://docs.docker.com/engine/storage/bind-mounts/) na documentação do Docker.

Veja a seguir alguns casos de uso comuns de montagens bind.
+ Para fornecer um volume de dados vazio para ser montado em um ou mais contêineres.
+ Para montar um volume de dados de host em um ou mais contêineres.
+ Para compartilhar um volume de dados de um contêiner de origem com outros contêineres na mesma tarefa.
+ Para expor um caminho e seu conteúdo de um Dockerfile para um ou mais contêineres.

## Considerações quando forem usadas montagens bind
<a name="bind-mount-considerations"></a>

Ao usar montagens bind, considere o seguinte.
+ Por padrão, as tarefas hospedadas no AWS Fargate usando a versão da plataforma `1.4.0` ou posterior (Linux) ou `1.0.0` ou posterior (Windows) recebem, no mínimo, 20 GiB de armazenamento temporário para montagens vinculadas. É possível aumentar a quantidade total de armazenamento temporário, até um máximo de 200 GiB, com a especificação do parâmetro `ephemeralStorage` na definição da tarefa.
+ Para expor arquivos de um Dockerfile a um volume de dados quando uma tarefa é executada, o plano de dados do Amazon ECS procura uma diretiva `VOLUME`. Se o caminho absoluto especificado na diretiva `VOLUME` é o mesmo que o `containerPath` especificado na definição de tarefa, os dados no caminho da diretiva `VOLUME` são copiados para o volume de dados. No exemplo de Dockerfile a seguir, um arquivo denominado `examplefile` do diretório `/var/log/exported` é gravado no host e, em seguida, montado no contêiner.

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

  Por padrão, as permissões de volume são definidas como `0755` e o proprietário como `root`. É possível personalizar essas permissões no Dockerfile. O exemplo a seguir define o proprietário do diretório 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 tarefas hospedadas em instâncias do Amazon EC2, quando um`host` e `sourcePath` não são especificados, o daemon do Docker gerencia a montagem bind para você. Quando nenhum contêiner fizer referência a essa montagem bind, o serviço de limpeza de tarefas do agente de contêiner do Amazon ECS acabará excluindo-a. Isso ocorre por padrão três horas após o encerramento do contêiner. Porém, é possível configurar essa duração com a variável de agente `ECS_ENGINE_TASK_CLEANUP_WAIT_DURATION`. Para obter mais informações, consulte [Configuração do agente de contêiner do Amazon ECS](ecs-agent-config.md). Se você precisar que esses dados persistam além do ciclo de vida do contêiner, especifique um valor `sourcePath` para a montagem bind.
+ Para tarefas hospedadas em instâncias gerenciadas do Amazon ECS, partes do sistema de arquivos raiz são somente de leitura. As montagens de ligação de leitura/gravação devem utilizar diretórios graváveis, como `/var` para dados persistentes ou `/tmp` para dados temporários. A tentativa de criar montagens vinculadas de leitura/gravação em outros diretórios faz com que a tarefa não seja iniciada, gerando um erro semelhante ao seguinte:

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

  Montagens de associação somente leitura (configuradas com `"readOnly": true` no parâmetro `mountPoints`) podem apontar para qualquer diretório acessível no host.

  Para visualizar uma lista completa dos caminhos graváveis, você pode executar uma tarefa em uma Instância Gerenciada do Amazon ECS e usar o comando para inspecionar a tabela de montagens da instância. Crie uma definição de tarefa com as seguintes configurações para acessar o sistema de arquivos do host:

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

  Em seguida, execute os seguintes comandos dentro do contêiner:

  ```
  # 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**  
A configuração `privileged` concede ao contêiner recursos estendidos no host, equivalentes ao acesso root. Neste exemplo, ele é utilizado para examinar a tabela de montagens do host para fins de diagnóstico. Para obter mais informações, consulte [Evitar executar contêineres como privilegiados (Amazon EC2)](security-tasks-containers.md#security-tasks-containers-recommendations-avoid-privileged-containers).

  Para obter mais informações sobre como executar comandos de forma interativa em contêineres, consulte [Monitoramento de contêineres do Amazon ECS com o ECS Exec](ecs-exec.md).

# Especificar uma montagem associada em uma definição de tarefa do Amazon ECS
<a name="specify-bind-mount-config"></a>

Em tarefas do Amazon ECS hospedadas em instâncias do Fargate ou do Amazon EC2, o trecho JSON de definição de tarefa a seguir mostra a sintaxe dos objetos `volumes`, `mountPoints` e `ephemeralStorage` para uma definição de tarefa.

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

Para tarefas do Amazon ECS que são hospedadas em instâncias do Amazon EC2, é possível utilizar o parâmetro `host` e um `sourcePath` ao especificar detalhes do volume da tarefa. Quando especificado, ele associa a montagem bind ao ciclo de vida da tarefa no lugar do contêiner.

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

A seguir, é descrito em mais detalhes cada parâmetro de definição de tarefa.

`name`  
Tipo: string  
Obrigatório: não  
O nome do volume. São permitidos até 255 letras (caixa alta e baixa), números, hífens (`-`) e sublinhados (`_`). Esse nome é referenciado no parâmetro `sourceVolume` do objeto `mountPoints` de definição do contêiner.

`host`  
Obrigatório: não  
O parâmetro `host` é usado para vincular o ciclo de vida da montagem bind à instância host do Amazon EC2, em vez da tarefa, e onde ela está armazenada. Caso o parâmetro `host` esteja vazio, o daemon do Docker atribui um caminho host para o volume de dados, mas os dados não têm garantia de persistir depois que os contêineres associados deixarem de ser executados.  
Os contêineres do Windows podem montar diretórios inteiros na mesma unidade como `$env:ProgramData`.  
O parâmetro `sourcePath` é compatível apenas quando se utilizam tarefas hospedadas em instâncias do Amazon EC2 ou em instâncias gerenciadas do Amazon ECS.  
`sourcePath`  
Tipo: string  
Obrigatório: não  
Quando o parâmetro `host` é usado, especifique um `sourcePath` para declarar o caminho na instância host do Amazon EC2 que é apresentada ao contêiner. Caso esse parâmetro esteja vazio, o daemon do Docker atribui um caminho host para você. Caso o parâmetro `host` contenha um local de arquivo `sourcePath`, o volume de dados persistirá no local especificado na instância host do Amazon EC2 até você excluí-lo manualmente. Caso o valor `sourcePath` não exista na instância host do Amazon EC2, o daemon do Docker o criará. Caso o local exista, o conteúdo da pasta do caminho de origem é exportado.

`mountPoints`  
Tipo: Matriz de objeto  
Obrigatório: não  
Os pontos de montagem dos volumes de dados no contêiner. Esse parâmetro é mapeado em `Volumes` na API create-container do Docker na opção `--volume` de execução do docker.  
Os contêineres do Windows podem montar diretórios inteiros na mesma unidade como `$env:ProgramData`. Os contêineres do Windows não podem montar diretórios em uma unidade diferente, e os pontos de montagem não podem ser usados ​​entre unidades. Você deve especificar pontos de montagem para anexar um volume do Amazon EBS diretamente a uma tarefa do Amazon ECS.    
`sourceVolume`  
Tipo: string  
Exigido: Sim, quando `mountPoints` são usados  
O nome do volume a ser montado.  
`containerPath`  
Tipo: string  
Exigido: Sim, quando `mountPoints` são usados  
O caminho no contêiner onde o volume será montado.  
`readOnly`  
Tipo: booliano  
Obrigatório: não  
Caso o valor seja `true`, o contêiner tem acesso somente leitura ao volume. Caso esse valor seja `false`, o contêiner pode gravar no volume. O valor padrão é `false`.  
Para tarefas executadas em instâncias do EC2 que executam o sistema operacional Windows, deixe o valor como o padrão de `false`.

`ephemeralStorage`  
Tipo: Objeto  
Obrigatório: não  
A quantidade de armazenamento temporário a ser alocada para a tarefa. Esse parâmetro é usado para expandir a quantidade total de armazenamento temporário, além da quantidade padrão, para tarefas hospedadas no AWS Fargate, usando a versão `1.4.0` ou posterior (Linux) ou `1.0.0` ou posterior (Windows) da plataforma.  
É possível usar a CLI do Copilot, o CloudFormation, o AWS SDK ou a CLI para especificar o armazenamento temporário para uma montagem bind.

# Exemplos de montagem de associação para o Amazon ECS
<a name="bind-mount-examples"></a>

Os exemplos a seguir abrangem casos de uso comuns de uma montagem bind para contêineres.

**Para alocar uma quantidade maior de espaço de armazenamento temporário para uma tarefa do Fargate**

Para tarefas do Amazon ECS hospedadas no Fargate usando a versão `1.4.0` ou posterior (Linux) ou `1.0.0` (windows) da plataforma, você pode alocar mais do que a quantidade padrão de armazenamento temporário para os contêineres da tarefa que serão usados. Esse exemplo pode ser incorporado aos outros exemplos para alocar mais armazenamento temporário para suas tarefas do Fargate.
+ Na definição da tarefa, defina um objeto `ephemeralStorage`. O `sizeInGiB` deve ser um número inteiro entre os valores de `21` e `200` e é expresso em GiB.

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

**Para fornecer um volume de dados vazio para um ou mais contêineres**

Em alguns casos, você pode querer fornecer aos contêineres de uma tarefa algum espaço temporário. Por exemplo, você pode ter dois contêineres de banco de dados que precisam acessar o mesmo local de armazenamento de arquivos temporários durante uma tarefa. Isso pode ser feito usando uma montagem bind.

1. Na seção `volumes` da definição de tarefa, defina uma montagem bind com o nome `database_scratch`.

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

1. Na seção `containerDefinitions`, crie as definições de contêiner de banco de dados. Isso deve ser feito para que elas montem o volume.

   ```
   "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 expor um caminho e seu conteúdo em um Dockerfile para um contêiner**

Neste exemplo, você tem um Dockerfile que grava dados que você quer montar em um contêiner. Este exemplo funciona para tarefas hospedadas em instâncias do Fargate ou do Amazon EC2.

1. Crie um Dockerfile. O exemplo a seguir usa a imagem pública do contêiner do Amazon Linux 2 e cria um arquivo denominado `examplefile` no diretório `/var/log/exported`que queremos montar dentro do contêiner. A diretiva `VOLUME` deve especificar um caminho absoluto.

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

   Por padrão, as permissões de volume são definidas como `0755` e o proprietário como `root`. Essas permissões podem ser alteradas no Dockerfile. No exemplo a seguir, o proprietário do diretório `/var/log/exported` é definido 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. Na seção `volumes` da definição da tarefa, defina um volume com o nome `application_logs`.

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

1. Na seção `containerDefinitions`, crie as definições do contêiner da aplicação. Isso deve ser feito para que elas montem o armazenamento. O valor `containerPath` deve corresponder ao caminho absoluto especificado na diretiva `VOLUME` do 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 fornecer um volume de dados vazio para um contêiner vinculado ao ciclo de vida da instância host do Amazon EC2**

Para tarefas hospedadas em instâncias do Amazon EC2, você pode usar montagens bind e ter os dados vinculados ao ciclo de vida da instância host do Amazon EC2. É possível fazer isso usando o parâmetro `host` e especificando um valor `sourcePath`. Todos os arquivos existentes em `sourcePath` são apresentados aos contêineres no valor `containerPath`. Todos os arquivos que são gravados no valor `containerPath` são gravados no valor `sourcePath` na instância do host do Amazon EC2.
**Importante**  
O Amazon ECS não sincroniza seu armazenamento entre instâncias do Amazon EC2. As tarefas que usam armazenamento persistente podem ser colocadas em qualquer instância do Amazon EC2, no cluster que tiver capacidade disponível. Se suas tarefas exigirem armazenamento persistente após a interrupção e a reinicialização, sempre especifique a mesma instância do Amazon EC2 no momento da inicialização da tarefa com o comando [start-task](https://docs.aws.amazon.com/cli/latest/reference/ecs/start-task.html) da AWS CLI. Também podem ser usados volumes do Amazon EFS para armazenamento persistente. Para obter mais informações, consulte [Uso de volumes do Amazon EFS com o Amazon ECS](efs-volumes.md).

1. Na seção `volumes` da definição de tarefa, defina uma montagem bind com os valores `name` e `sourcePath`. No exemplo a seguir, a instância host do Amazon EC2 contém dados em `/ecs/webdata` que você quer montar no contêiner.

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

1. Na seção `containerDefinitions`, defina um contêiner com um valor `mountPoints` que faça referência ao nome da montagem bind definida e ao valor `containerPath` para montar a montagem bind no contêiner.

   ```
     "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 um volume definido em vários contêineres em diferentes locais**

É possível definir um volume de dados em uma definição de tarefa e montar esse volume em locais diferentes em diferentes contêineres. Por exemplo, seu contêiner host tem uma pasta de dados de site em `/data/webroot`. É possível montar esse volume de dados como somente leitura em dois servidores Web diferentes com raízes de documentos distintas.

1. Na seção `volumes` de definição de tarefa, defina um volume de dados com o nome `webroot` e o caminho de origem `/data/webroot`.

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

1. Na seção `containerDefinitions`, defina um contêiner para cada servidor da Web com valores `mountPoints` que associam o volume `webroot` com o valor `containerPath` apontando para a raiz do documento desse contêiner.

   ```
     "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 volumes de outro contêiner usando `volumesFrom`**

Para tarefas hospedadas em instâncias do Amazon EC2, é possível definir um ou mais volumes em um contêiner e, em seguida, usar o parâmetro `volumesFrom` em uma definição de contêiner diferente (dentro da mesma tarefa) para montar todos os volumes do `sourceContainer` em seus pontos de montagem definidos originalmente. O parâmetro `volumesFrom` se aplica a volumes determinados na definição de tarefa, e os que são incorporados na imagem com um Dockerfile.

1. (Opcional) Para compartilhar um volume incorporado em uma imagem, utilize a instrução `VOLUME` no arquivo Dockerfile. O Dockerfile de exemplo a seguir usa uma imagem `httpd` e, em seguida, adiciona um volume e monta-o em `dockerfile_volume` na raiz do documento Apache. É a pasta usada pelo servidor Web `httpd`.

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

   É possível incorporar uma imagem com esse Dockerfile e enviá-la para um repositório, como o Docker Hub, e usá-la em sua definição de tarefa. A imagem de exemplo `my-repo/httpd_dockerfile_volume` usada nas etapas a seguir foi criada com o Dockerfile anterior.

1. Crie uma definição de tarefa que defina seus outros volumes e pontos de montagem para os contêineres. Nesta seção `volumes` de exemplo, você cria um volume vazio chamado `empty`, que o daemon do Docker gerencia. Há também um volume host definido que se chama `host_etc`. Ele exporta a pasta `/etc` na instância de contêiner host.

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

   Na seção definições de contêiner, crie um contêiner que monte os volumes definidos anteriormente. Neste exemplo, o contêiner `web` monta os volumes `empty` e `host_etc`. Este é o contêiner que utiliza a imagem criada com um volume no 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
       },
   ```

   Crie outro contêiner que use `volumesFrom` para montar todos os volumes que estão associados com o contêiner `web`. Todos os volumes no contêiner `web` também são montados no contêiner `busybox`. Isso inclui o volume especificado no Dockerfile que foi utilizado para criar a imagem `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
       }
     ]
   }
   ```

   Quando essa tarefa é executada, os dois contêineres montam os volumes, e o `command` no contêiner `busybox` grava a data e a hora em um arquivo. Esse arquivo se chama `date` em cada uma das pastas de volume. As pastas ficam visíveis no site exibido pelo contêiner `web`.
**nota**  
Como o contêiner `busybox` executa um comando rápido e, em seguida, é encerrado, ele deve ser definido como `"essential": false` na definição do contêiner. Caso contrário, ele interromperá toda a tarefa quando for encerrado.