Extrair arquivo da imagem do docker?

24

Gostaria de extrair um arquivo de uma imagem do Docker sem precisar executá-la.

A docker saveopção não é atualmente uma opção viável para mim, pois está salvando um arquivo muito grande apenas para desmarcar um arquivo específico.

BlakBat
fonte
Que distro você está usando?
ryekayo
@ryekayo: Ubuntu 14, docker 1.12.4 (api 1.24)
BlakBat

Respostas:

21

Você pode extrair arquivos de uma imagem com os seguintes comandos:

docker create $image  # returns container ID
docker cp $container_id:$source_path $destination_path
docker rm $container_id

De acordo com a docker create documentação , isso não executa o contêiner:

O docker createcomando cria uma camada de contêiner gravável sobre a imagem especificada e a prepara para executar o comando especificado. O ID do contêiner é impresso para STDOUT. É semelhante a, docker run -dexceto que o contêiner nunca é iniciado. Você pode usar o docker start <container_id>comando para iniciar o contêiner a qualquer momento.


Para referência (minha resposta anterior), uma maneira menos eficiente de extrair um arquivo de uma imagem é a seguinte:

docker run some_image cat $file_path > $output_path
bbc
fonte
3
Você pode substituir o ponto de entrada. docker run --entrypoint /bin/sh my_image -c /bin/cat some_file
Andrew
1
Isso executa a imagem, que é especificamente o que eu não queria fazer como indicado na minha pergunta.
BlakBat 26/03
Ah, esse é um bom argumento. Concordo que minha resposta atual não é satisfatória então.
bbc
1
@BlakBat Esta resposta atualizada funciona para você? Acho que deveria ter criado uma nova resposta, mas está pronta agora.
bbc
1
@bbc Esta resposta atualizada, na verdade, não inicia um contêiner (o cerne da questão) e não precisa ser raiz.
BlakBat 20/04
2

Nenhuma das opções acima funcionou para mim. O comando de trabalho completo é:

docker run --rm --entrypoint /bin/sh image_name -c "cat /path/filename" > output_filename

Sem aspas caté passado sem nome do arquivo, portanto, ele não sabe o que mostrar. Também é uma boa idéia excluir o contêiner após a conclusão do comando.

sekrett
fonte
O comando ao qual você está se referindo funcionará apenas dependendo da janela de encaixe e quão corretamente ENTRYPOINT / CMD foi definido no Dockerfile; isso não tem nada a ver com citação. Você também diz para excluir o contêiner, mas especifica --rm. Por fim, depois de postar minha pergunta, especifiquei "sem precisar executar a imagem" e nenhuma resposta foi uma solução levando isso em consideração.
BlakBat
1
Independentemente de qual CMD e ENTRYPOINT foram definidos no Dockerfile, eu substituo ambos, para que funcione sempre (no Linux, é claro). O que você quer dizer com "dependendo da janela de encaixe"? Configurações, versão, env, o que? Sua pergunta não está correta porque as imagens não podem ser executadas, apenas os contêineres. Eu acho que não há resposta correta, você precisa lidar com muitos arquivos ou criar um contêiner temporário. --rm remove o contêiner temporário, as respostas de outros deixam algum lixo no seu disco.
sekrett
1

Se não me engano, acredito que os contêineres do docker armazenam arquivos em cache criados no seguinte diretório do Ubuntu:

/var/lib/docker/aufs/diff/<container_id>

A partir daí, você poderá acessar o sistema de arquivos e recuperar seus arquivos.

ryekayo
fonte
Não. Esse diretório contém apenas layersizee json, e também não é legível pelo usuário (mesmo se o usuário estiver no grupo de janelas de encaixe). /var/lib/docker/aufs/diffconterá o arquivo que eu procuro (mas não é categorizado pelo ID do contêiner) e também não é legível.
BlakBat
Dê-me alguns e eu procurarei. Sei que existe uma maneira de recuperar os arquivos sem entrar no contêiner ou executá-lo.
ryekayo
Por não legível, como isso mostra? Eu encontrei um exemplo onde você pode puxar arquivos de texto a partir dos recipientes, indo para o / var / lib / janela de encaixe / aufs / diff / * diretório
ryekayo
Meu erro. O usuário pode acessar /var/lib/docker/aufs(mas não todos os outros diretórios em /var/lib/docker/)
BlakBat
Você pode acessar como root?
precisa saber é o seguinte
0

Se armazenar a saída completa de docker savenão for uma opção, você poderá usar pipelines para extrair apenas o arquivo necessário.

Infelizmente, como a saída é um "alcatrão de alcatrão", pode ser um processo ligeiramente iterativo.

O que fiz quando precisei extrair um arquivo agora foi:

1) Determine em qual versão da imagem o arquivo em que você está interessado mudou mais recentemente (como você faz isso provavelmente depende da sua imagem) e a data em que foi criada / salva

2) Obtenha o índice completo da saída do docker savecomando com:

docker save IMAGE_NAME | tar -tvf -

3) Ajuste os layer.tararquivos na saída desse comando que correspondem à data da imagem que você determinou na etapa 1. (você pode adicionar | grep layer.tarpara mostrar apenas esses arquivos)

4) Extraia esse layer.tararquivo para o padrão e obtenha o sumário:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -tvf -

5) Verifique se o arquivo que você deseja está listado e extraia-o quando encontrar o nome:

docker save IMAGE_NAME | tar -xf - -O CHECKSUM_FROM_LIST/layer.tar | tar -xf - PATH/TO/YOUR/FILE

Se houver mais de um layer.tararquivo correspondente à data que você está procurando na etapa 2/3, talvez seja necessário repetir a etapa 4 para cada um deles até encontrar o caminho certo.

Substitua o texto em maiúsculas nos comandos acima pelos nomes de imagem, somas de verificação e nomes de arquivos corretos para o seu caso.

Michael Firth
fonte