Uma tradução do artigo foi preparada antes do início do curso Python Web Developer .
Ao criar uma imagem do Docker, você pode precisar de segredos, como uma senha para um repositório de pacotes particulares. Você não deseja que esse segredo acabe na imagem, pois quem tiver acesso à imagem terá acesso ao seu repositório privado.Nota : Se você pensar em "Por que não usar apenas variáveis de ambiente?", Que são usadas para segredos em tempo de execução ao criar uma imagem. Este artigo se concentra na criação de segredos usados ao criar uma imagem usando um arquivo Docker.
As versões mais recentes do Docker mantêm segredos usando o serviço BuildKit experimental e, no Docker Compose 1.25 e posterior, você já pode criar imagens usando o BuildKit. Infelizmente, em março de 2020, a capacidade de trabalhar com segurança com segredos do Compose ainda está em desenvolvimento .Então o que fazer agora?No artigo de hoje, mostrarei como você pode usar o mesmo Dockerfile para criar com segurança imagens de segredos sem perder os benefícios do desenvolvimento rápido usando o Docker Compose.Duas opções para usar seu arquivo docker
É muito conveniente usar o mesmo Dockerfile para produção e desenvolvimento local com o Docker Compose. Geralmente você usa o Dockerfile junto com a função de compilação do Compose:version: "3.7"
services:
yourapp:
build:
context: "."
Então você pode fazer:$ docker-compose up
Com este comando, você pode (re) montar a imagem e depois executá-la.Para uso na produção, você coleta a imagem e a envia com push :$ docker build -t myimage .
$ docker push myimage
E enquanto tudo está indo bem. Mas e se você precisar de uma construção secreta?Primeira tentativa (insegura)
Suponha que você tenha um script que precise de uma construção secreta, por exemplo, para baixar um pacote Python de um repositório privado do DevPI . Por uma questão de simplicidade, derivaremos simplesmente o segredo com a ajuda use-secret.sh
de mostrar que o temos.
set -euo pipefail
echo "Secret is: $THEPASSWORD"
Você pode simplesmente transmitir o segredo usando os argumentos de construção do Docker, pois eles são suportados em todos os lugares, inclusive no Docker Compose.Nota : Indo além do escopo de nossa discussão, quero dizer que o uso de arquivos do Docker neste artigo não é a melhor prática; no entanto, a complexidade excessiva pode interferir na transmissão do significado principal do artigo.
Portanto, se você deseja executar seu aplicativo Python em produção com o Docker, aqui estão duas boas maneiras de fazer isso:FROM python:3.8-slim-buster
ARG THEPASSWORD
COPY use_secret.sh .
RUN ./use_secret.sh
Podemos escrever docker-compose.yml
, que será transmitido em segredo:version: "3.7"
services:
yourapp:
build:
context: "."
args:
THEPASSWORD: "s3kr!t"
Para o trabalho local, você pode executar ou criar uma imagem usando o Redigir:$ docker-compose build | grep Secret
Secret is: s3kr!t
E está tudo bem.E também podemos montar a imagem usando o Docker, em preparação para movê-la para o registro de imagens:$ docker build -t myimage --build-arg THEPASSWORD=s3krit . | grep Secret
Secret is: s3krit
Fazer isso é inseguro: nunca faça isso . Se decidirmos olhar as camadas da imagem, veremos o segredo nela!$ docker history myimage
IMAGE CREATED CREATED BY SIZE
c224231ec30b 47 seconds ago |1 THEPASSWORD=s3krit /bin/sh -c ./use_secre… 0B
6aef62acf0db 48 seconds ago /bin/sh -c
f88b19ca8e65 About a minute ago /bin/sh -c
...
Quem obtiver acesso a esta imagem reconhecerá sua senha. O que pode ser feito, então?Segredos do BuildKit (solução parcial)
O BuildKit é uma solução nova (e ainda experimental) para a criação de imagens do Docker, que, entre outras coisas, adiciona suporte para o uso seguro de segredos durante a montagem . O Docker Compose tem suporte ao BuildKit desde a v1.25.Mas há um problema: o Docker Compose ainda não suporta a funcionalidade de segredos do BuildKit. Agora, o trabalho está em andamento , mas em março de 2020, não há soluções prontas, para não mencionar uma versão estável.Portanto, vamos combinar essas duas abordagens:- O Docker Compose continuará usando argumentos de construção para passar segredos;
- Para uma imagem de produção criada usando o docker build, usamos o BuildKit para transmitir segredos.
Dessa forma, podemos usar o mesmo Dockerfile para trabalhar localmente e na produção.O BuildKit trabalha com segredos da seguinte maneira: o arquivo com segredos é montado em um diretório temporário enquanto o comando RUN é executado, por exemplo, em /var/secrets/thepassword
. Como ele é montado durante a execução do comando RUN, não será adicionado à imagem final.Modificaremos o arquivo use_secret.sh
para verificar se existe um arquivo temporário. Se existir, ele usa suas configurações de variável de ambiente $THEPASSWORD
. Se o arquivo não existir, retornaremos à variável de ambiente. Ou seja, ele $THEPASSWORD
pode ser instalado usando o BuildKit ou argumentos de construção:
set -euo pipefail
if [ -f /run/secrets/thepassword ]; then
export THEPASSWORD=$(cat /run/secrets/thepassword)
fi
echo "Secret is: $THEPASSWORD"
Em seguida, modificaremos o Dockerfile para adicionar o BuildKit e montar o segredo:
FROM python:3.8-slim-buster
ARG THEPASSWORD
COPY use_secret.sh .
RUN --mount=type=secret,id=thepassword ./use_secret.sh
docker-compose.yml
Nós não alteramos o arquivo :version: "3.7"
services:
yourapp:
build:
context: "."
args:
THEPASSWORD: "s3kr!t"
Agora você precisa definir duas variáveis de ambiente, uma das quais informará ao Docker que você deve usar o BuildKit, a segunda que o Compose precisará usar a versão CLI do Docker e, portanto, o BuildKit. Também escreveremos o segredo do arquivo:$ export DOCKER_BUILDKIT=1
$ export COMPOSE_DOCKER_CLI_BUILD=1
$ echo 's3krit' > /tmp/mypassword
Com o Compose, usamos os argumentos de construção:$ docker-compose build --progress=plain \
--no-cache 2>&1 | grep Secret
Observe que é --no-cache
necessário entender que a imagem será realmente reconstruída se você executar todas as opções acima. Na vida real, esse parâmetro pode ser omitido. 2>&1
redirecionar stderr
para stdout
para a operação correta grep
.Quando estamos prontos para desenvolver a produção, usamos o docker build com a funcionalidade de segredos do BuildKit:$ docker build --no-cache -t myimage \
--secret id=thepassword,src=/tmp/mypassword \
--progress=plain . 2>&1 | grep Secret
É seguro?
Vamos garantir que o segredo não seja visível:$ docker history myimage
IMAGE CREATED CREATED BY SIZE
a77f3c32b723 25 seconds ago RUN |1 THEPASSWORD= /bin/sh -c ./use_secret.… 0B
<missing> 25 seconds ago COPY use_secret.sh .
...
Viva! Passamos o segredo para o mesmo Dockerfile usando o Compose e docker build
, no último caso, não revelamos o segredo da montagem.
Saiba mais sobre o curso.