Enviando um arquivo do contêiner do Docker para o host usando o nc: Por que o host nc fecha a conexão muito cedo?

6

O seguinte script BASH faz o download e cria mpv ( link ) em um contêiner Docker e envia o arquivo para o host usando o netcat (o host está escutando usando o netcat):

HOSTIP="192.168.1.100"
PORT="62514"

nc -v -l $PORT > mpv &

sleep 1

sudo docker run ubuntu:14.04 /bin/bash -c "\
sed -i -e 's/# deb/deb/g' /etc/apt/sources.list; \
cat /etc/apt/sources.list; \
apt-get update; \
apt-get install --yes --force-yes git python-minimal; \
git clone https://github.com/mpv-player/mpv-build.git; \
cd mpv-build/; \
./update; \
apt-get install --yes --force-yes devscripts equivs; \
rm -f mpv-build-deps_*_*.deb; \
mk-build-deps -i -t \"apt-get --yes --force-yes --no-install-recommends\"; \
./build -j\$(nproc); \
cat mpv/build/mpv | nc $HOSTIP $PORT; \
echo Done"

#close any nc process that might be left running
nc $HOSTIP $PORT

Então o script:

  1. Inicia o netcat ( nc ) no host, aguardando conexões em segundo plano
  2. Inicia um contêiner do Docker, no qual clonamos o repositório mpv, construímos o mpv, usamos nc para conectar ao soquete de escuta no host e enviamos o binário resultante de volta para o host

Por algum motivo, o arquivo resultante é reduzido em tamanho, quando recebido no lado do host. Ou é 0 bytes ou algum múltiplo de 1024 bytes. O começo parece intacto, um executável ELF x86_64.

Aqui está uma captura de pacote onde o container docker envia um pouco do binário mpv para o host, mas onde a escuta nc (no host) fecha a conexão prematuramente (envia um pacote com o flag FIN set, alguns milissegundos após a conexão ser estabelecida):

49152 bytes foram transmitidos aqui (é sempre um múltiplo de 1024).

Nem sempre há erros de retransmissão TCP. Fiz outra captura sem erros, mas ainda assim foi enviado um pouco (24576) do total de 21818582 bytes do binário mpv resultante.

Não tem certeza do que está acontecendo aqui, por que nc no lado de escuta / host envia um pacote TCP FIN logo após a conexão ser aberta?

    
por runeks 18.10.2014 / 00:28

3 respostas

0

Usando o comando docker cp , o script pode ser reescrito da seguinte forma:

HOSTIP="192.168.1.100"
PORT="62514"

set -e

CONTAINERID=$(sudo docker run -d ubuntu:14.04 /bin/bash -c "\
sed -i -e 's/# deb/deb/g' /etc/apt/sources.list; \
cat /etc/apt/sources.list; \
apt-get update; \
apt-get install --yes --force-yes git python-minimal; \
git clone https://github.com/mpv-player/mpv-build.git; \
cd mpv-build/; \
./update; \
apt-get install --yes --force-yes devscripts equivs; \
rm -f mpv-build-deps_*_*.deb; \
mk-build-deps -i -t \"apt-get --yes --force-yes --no-install-recommends\"; \
./build -j\$(nproc); \
echo \"From container: done building!\" | nc $HOSTIP $PORT; \
nc -v -l $PORT")

CONTAINERIP=$(sudo docker inspect $CONTAINERID|grep IPAddress|sed 's/.*IPAddress": "//'|sed 's/",$//')

echo "Started mpv-build container with Docker container ID: $CONTAINERID and IP: $CONTAINERIP" 
echo "Waiting to hear from container that the build has finished..."

#listen on host. wait for container to connect and disconnect
nc -l $PORT

#copy file from running container, while it's listening for a connection with nc
sudo docker cp $CONTAINERID:/mpv-build/mpv/build/mpv ./

#connect to the listening socket in the container to make the container finish running
echo "bye" | nc  $CONTAINERIP $PORT

echo "Done"

O netcat agora é usado apenas como uma espécie de mecanismo de mensagens, para o contêiner sinalizar para o host quando ele é feito (assim o host pode iniciar a cópia) e para o host sinalizar para o contêiner que ele fez copiando o arquivo (para que o contêiner possa sair).

    
por 19.10.2014 / 14:39
0

Outra solução é apenas usar o redirecionamento de fluxo, ou seja:

docker run /bin/sh -c '/my/build/command 1>&2 && cat /my/build/artifact' > artifact

Para vários arquivos, adicione tar:

docker run /bin/sh -c '/my/build/command 1>&2 && tar -cf- -C /my/build/artifacts .' | tar -xf- -C artifacts
    
por 12.02.2015 / 01:14
0

Não tenho uma solução para as esquisitices específicas do problema do netcat, mas o Docker fornece um recurso para conseguir isso.

Você pode usar docker cp <containerId>:/path/to/file /host/path/to/file em vez de mexer no netcat.

    
por 19.10.2014 / 13:07

Tags