Geralmente, você não deseja executar um git clone
repo particular de dentro da construção da janela de encaixe. Fazer o clone lá envolve colocar as credenciais ssh privadas dentro da imagem, para que possam ser extraídas posteriormente por qualquer pessoa com acesso à sua imagem.
Em vez disso, a prática comum é clonar o repositório git de fora da janela de encaixe na sua ferramenta de CI preferida e simplesmente COPY
os arquivos na imagem. Isso tem um segundo benefício: cache do docker. O armazenamento em cache do Docker examina o comando que está sendo executado, as variáveis de ambiente que ele inclui, os arquivos de entrada etc., e se eles são idênticos a uma compilação anterior da mesma etapa pai, reutilizam esse cache anterior. Com um git clone
comando, o próprio comando é idêntico; portanto, o docker reutilizará o cache, mesmo que o repositório git externo seja alterado. No entanto, um COPY
comando examinará os arquivos no contexto de construção e poderá ver se eles são idênticos ou foram atualizados e usará o cache somente quando for apropriado.
Se você deseja adicionar credenciais à sua compilação, considere fazê-lo com uma compilação de vários estágios e apenas coloque essas credenciais em um estágio inicial que nunca seja marcado e enviado para fora do host da compilação. O resultado se parece com:
FROM ubuntu as clone
# Update aptitude with new repo
RUN apt-get update \
&& apt-get install -y git
# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
&& touch /root/.ssh/known_hosts \
&& ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts
# Copy over private key, and set permissions
# Warning! Anyone who gets their hands on this image will be able
# to retrieve this private key file from the corresponding image layer
COPY id_rsa /root/.ssh/id_rsa
# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git
FROM ubuntu as release
LABEL maintainer="Luke Crooks <luke@pumalo.org>"
COPY --from=clone /repo /repo
...
Mais recentemente, o BuildKit testou alguns recursos experimentais que permitem passar uma chave ssh como uma montagem que nunca é gravada na imagem:
# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"
# Update aptitude with new repo
RUN apt-get update \
&& apt-get install -y git
# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
&& touch /root/.ssh/known_hosts \
&& ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts
# Clone the conf files into the docker container
RUN --mount=type=secret,id=ssh_id,target=/root/.ssh/id_rsa \
git clone git@bitbucket.org:User/repo.git
E você pode criar isso com:
$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
--secret id=ssh_id,src=$(pwd)/id_rsa .
Observe que isso ainda exige que sua chave ssh não seja protegida por senha, mas você pode pelo menos executar a compilação em um único estágio, removendo um comando COPY e evitando que a credencial ssh faça parte de uma imagem.
O BuildKit também adicionou um recurso apenas para ssh, que permite que você ainda tenha suas chaves ssh protegidas por senha; o resultado é o seguinte:
# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"
# Update aptitude with new repo
RUN apt-get update \
&& apt-get install -y git
# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
&& touch /root/.ssh/known_hosts \
&& ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts
# Clone the conf files into the docker container
RUN --mount=type=ssh \
git clone git@bitbucket.org:User/repo.git
E você pode criar isso com:
$ eval $(ssh-agent)
$ ssh-add ~/.ssh/id_rsa
(Input your passphrase here)
$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
--ssh default=$SSH_AUTH_SOCK .
Novamente, isso é injetado na compilação sem nunca ser gravado em uma camada de imagem, eliminando o risco de a credencial vazar acidentalmente.
Para forçar o docker a executar o git clone
mesmo quando as linhas anteriores foram armazenadas em cache, você pode injetar um ARG de compilação que muda a cada compilação para interromper o cache. Isso se parece com:
# inject a datestamp arg which is treated as an environment variable and
# will break the cache for the next RUN command
ARG DATE_STAMP
# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git
Em seguida, você injeta a alteração do argumento no comando docker build:
date_stamp=$(date +%Y%m%d-%H%M%S)
docker build --build-arg DATE_STAMP=$date_stamp .