以下 BASH 脚本下载并构建mpv
(https://github.com/mpv-player/mpv-build) 放在 Docker 容器中,并使用 netcat 将文件发送到主机(主机正在使用 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
因此脚本:
nc
在主机上启动 netcat ( ),在后台监听连接- 启动一个 Docker 容器,在其中克隆 mpv repo、构建 mpv、用于
nc
连接主机上的监听套接字,并将生成的二进制文件发送回主机
由于某种原因,主机端接收到生成的文件时,文件大小会减小。要么是 0 字节,要么是 1024 字节的倍数。开头看起来完好无损,是一个 x86_64 ELF 可执行文件。
下面是一个数据包捕获,其中 docker 容器将一些 mpv 二进制文件发送到主机,但监听nc
(在主机上)过早关闭连接(它发送一个设置了 FIN 标志的数据包,在连接建立后几毫秒):
这里传输了 49152 个字节(它始终是 1024 的倍数)。
TCP 重传错误并不总是存在。我又进行了一次捕获,没有出现任何错误,但仍然只发送了一小部分(24576),而生成的 mpv 二进制文件总共有 21818582 个字节。
不确定这里发生了什么,为什么nc
在连接打开后不久,监听/主机端会发送 FIN TCP 数据包?
答案1
使用该docker cp
命令,可以像这样重写脚本:
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"
netcat 现在仅用作一种消息传递机制,用于容器在构建完成时向主机发出信号(以便主机可以启动复制),以及用于主机向容器发出信号,表示它已完成文件复制(以便容器可以退出)。
答案2
另一个解决方案是仅使用流重定向,即:
docker run /bin/sh -c '/my/build/command 1>&2 && cat /my/build/artifact' > artifact
对于多个文件,添加 tar:
docker run /bin/sh -c '/my/build/command 1>&2 && tar -cf- -C /my/build/artifacts .' | tar -xf- -C artifacts
答案3
我没有针对 netcat 问题的具体解决方案,但是Docker 确实提供了一个工具来实现这一点。
您可以使用docker cp <containerId>:/path/to/file /host/path/to/file
netcat,而不必担心弄乱它。