Estou executando o docker-container no Amazon EC2. Atualmente, adicionei as credenciais da AWS ao Dockerfile. Você poderia me informar a melhor maneira de fazer isso?
Estou executando o docker-container no Amazon EC2. Atualmente, adicionei as credenciais da AWS ao Dockerfile. Você poderia me informar a melhor maneira de fazer isso?
Respostas:
A melhor maneira é usar a função IAM e não lidar com credenciais. (consulte http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )
As credenciais podem ser recuperadas http://169.254.169.254.....
por ser um endereço IP privado, ele só pode ser acessado por instâncias EC2.
Todas as bibliotecas cliente modernas da AWS "sabem" como buscar, atualizar e usar credenciais a partir daí. Portanto, na maioria dos casos, você nem precisa saber sobre isso. Basta executar o ec2 com a função IAM correta e pronto.
Como opção, você pode passá-los no tempo de execução como variáveis de ambiente (ou seja docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage
)
Você pode acessar essas variáveis de ambiente executando printenv no terminal.
AWS_SECRET_ACCESS_KEY
, não AWS_SECRET_KEY
, de qualquer maneira sua resposta foi muito útil. Obrigado.
Muita coisa mudou no Docker desde que essa pergunta foi feita, então aqui está uma tentativa de uma resposta atualizada.
Primeiro, especificamente com as credenciais da AWS em contêineres já em execução dentro da nuvem, usar funções de IAM, como sugere Vor, é uma opção realmente boa. Se você puder fazer isso, adicione mais um mais um à sua resposta e pule o resto.
Depois que você começa a executar coisas fora da nuvem ou tem um tipo diferente de segredo, há dois pontos-chave que eu recomendo contra o armazenamento de segredos:
Variáveis de ambiente: quando são definidas em um contêiner, todos os processos dentro do contêiner têm acesso a elas, são visíveis por meio de / proc, os aplicativos podem despejar seu ambiente para o stdout, onde fica armazenado nos logs e, o mais importante, eles aparecem em texto claro ao inspecionar o contêiner.
Na própria imagem: as imagens muitas vezes são enviadas para registros onde muitos usuários têm acesso de pull, às vezes sem nenhuma credencial necessária para puxar a imagem. Mesmo se você excluir o segredo de uma camada, a imagem pode ser desmontada com utilitários comuns do Linux, como tar
e o segredo pode ser encontrado a partir da etapa em que foi adicionado pela primeira vez à imagem.
Então, quais outras opções existem para segredos em contêineres do Docker?
Opção A: Se você precisar desse segredo apenas durante a construção de sua imagem, não puder usar o segredo antes do início da construção e ainda não tiver acesso ao BuildKit, uma construção de vários estágios é a melhor das opções ruins. Você adicionaria o segredo aos estágios iniciais da compilação, usaria lá e, em seguida, copiaria a saída desse estágio sem o segredo para o estágio de lançamento e apenas enviaria esse estágio de lançamento para os servidores de registro. Esse segredo ainda está no cache de imagem no servidor de compilação, então costumo usar isso apenas como último recurso.
Opção B: também durante o tempo de construção, se você pode usar o BuildKit que foi lançado em 18.09, existem atualmente recursos experimentais para permitir a injeção de segredos como uma montagem de volume para uma única linha RUN. Essa montagem não é gravada nas camadas da imagem, então você pode acessar o segredo durante a construção sem se preocupar se ele será enviado a um servidor de registro público. O Dockerfile resultante se parece com:
# syntax = docker/dockerfile:experimental
FROM python:3
RUN pip install awscli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://... ...
E você o constrói com um comando em 18.09 ou mais recente, como:
DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .
Opção C:No tempo de execução em um único nó, sem o modo Swarm ou outra orquestração, você pode montar as credenciais como um volume somente leitura. O acesso a essa credencial requer o mesmo acesso que você teria fora do docker para o mesmo arquivo de credenciais, portanto, não é melhor nem pior do que o cenário sem docker. Mais importante ainda, o conteúdo desse arquivo não deve ser visível quando você inspeciona o contêiner, visualiza os logs ou envia a imagem para um servidor de registro, uma vez que o volume está fora disso em todos os cenários. Isso exige que você copie suas credenciais no host docker, separado da implantação do contêiner. (Observe, qualquer pessoa com a capacidade de executar contêineres nesse host pode visualizar sua credencial, já que o acesso à API docker é root no host e root pode visualizar os arquivos de qualquer usuário. Se você não confiar em usuários com root no host ,
Para um docker run
, isso se parece com:
docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image
Ou para um arquivo de composição, você teria:
version: '3'
services:
app:
image: your_image
volumes:
- $HOME/.aws/credentials:/home/app/.aws/credentials:ro
Opção D:Com ferramentas de orquestração como o Modo Swarm e Kubernetes, agora temos suporte a segredos que é melhor do que um volume. Com o Modo Swarm, o arquivo é criptografado no sistema de arquivos do gerenciador (embora a chave de descriptografia frequentemente também esteja lá, permitindo que o gerenciador seja reiniciado sem que um administrador insira uma chave de descriptografia). Mais importante ainda, o segredo é enviado apenas para os trabalhadores que precisam do segredo (executando um contêiner com esse segredo), é armazenado apenas na memória do trabalhador, nunca no disco, e é injetado como um arquivo no contêiner com um tmpfs montar. Os usuários no host fora do swarm não podem montar esse segredo diretamente em seu próprio contêiner, no entanto, com acesso aberto à API docker, eles podem extrair o segredo de um contêiner em execução no nó, portanto, novamente, limite quem tem esse acesso ao API. Na composição, essa injeção secreta se parece com:
version: '3.7'
secrets:
aws_creds:
external: true
services:
app:
image: your_image
secrets:
- source: aws_creds
target: /home/user/.aws/credentials
uid: '1000'
gid: '1000'
mode: 0700
Você ativa o modo de enxame com docker swarm init
para um único nó e, a seguir, segue as instruções para adicionar nós adicionais. Você pode criar o segredo externamente com docker secret create aws_creds $HOME/.aws/credentials
. E você implanta o arquivo de composição com docker stack deploy -c docker-compose.yml stack_name
.
Costumo criar versões de meus segredos usando um script de: https://github.com/sudo-bmitch/docker-config-update
Opção E: Existem outras ferramentas para gerenciar segredos, e minha favorita é o Vault porque oferece a capacidade de criar segredos com limite de tempo que expiram automaticamente. Cada aplicativo obtém seu próprio conjunto de tokens para solicitar segredos, e esses tokens dão a eles a capacidade de solicitar esses segredos de tempo limitado, desde que possam acessar o servidor do vault. Isso reduz o risco de um segredo ser retirado de sua rede, já que ele não funcionará ou expirará rapidamente. A funcionalidade específica do AWS para Vault está documentada em https://www.vaultproject.io/docs/secrets/aws/index.html
Outra abordagem é passar as chaves da máquina host para o contêiner do docker. Você pode adicionar as seguintes linhas ao docker-compose
arquivo.
services:
web:
build: .
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
AWS_DEFAULT_REGION
docs.aws.amazon.com/cli/latest/userguide/…
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
Outra abordagem é criar um volume somente leitura temporário em docker-compose.yaml. AWS CLI e SDK (como boto3 ou AWS SDK para Java etc.) estão procurando por um default
perfil no ~/.aws/credentials
arquivo.
Se você quiser usar outros perfis, você só precisa exportar a variável AWS_PROFILE antes de executar o docker-compose
comando
export AWS_PROFILE=some_other_profile_name
version: '3'
services:
service-name:
image: docker-image-name:latest
environment:
- AWS_PROFILE=${AWS_PROFILE}
volumes:
- ~/.aws/:/root/.aws:ro
Neste exemplo, usei o usuário root no docker. Se você estiver usando outro usuário, basta mudar /root/.aws
para o diretório inicial do usuário
:ro
- significa volume docker somente leitura
É muito útil quando você tem vários perfis no ~/.aws/credentials
arquivo e também está usando o MFA. Também é útil quando você deseja testar localmente o docker-container antes de implantá-lo no ECS no qual você tem funções de IAM, mas não localmente.
"%UserProfile%\.aws"
. Então eu suponho que você tenha que mudar: - ~/.aws/:/root/.aws:ro
para- %UserProfile%\.aws:/root/.aws:ro
- host:container
sintaxe, se o arquivo / pasta não existir no host, ele foi criado (como root) e o awscli não agradecerá por alimentá-lo com um arquivo de zero bytes. Você deve usar o "formato longo" que especifica o tipo é bind, o caminho do host e o caminho do contêiner em linhas separadas; isso falhará se o arquivo não existir, que é o que você deseja em seu docker-compose.dev. yml, mas não em docker-compose.yml (prod / AWS deploy).
Você pode criar ~/aws_env_creds
contendo
touch ~/aws_env_creds
chmod 777 ~/aws_env_creds
vi ~/aws_env_creds
adicione o valor abaixo (substitua a sua chave)
AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C
"esc" para salvar o arquivo.
Execute e teste o contêiner
my_service:
build: .
image: my_image
env_file:
- ~/aws_env_creds