我正在尝试docker exec
从头开始构建的容器(例如,NATS容器)。看起来非常简单,但由于它是从头开始构建的,我无法访问/bin/bash
,/bin/sh
以及任何此类命令。
我收到错误:oci runtime error
(找不到命令,找不到文件等,具体取决于我输入的命令)。
我尝试了一些命令:
docker exec -it <container name> /bin/bash
docker exec -it <container name> /bin/sh
docker exec -it <container name> ls
我的问题是,我如何docker exec
一个从头开始构建并仅包含二进制文件的容器?通过做一个docker exec
,我想知道文件是否已经成功地从我的主机复制到容器(我在COPY
有一个Dockerfile
)。
有几种选择。
docker container cp ${CONTAINER}:/path/to/file/on/container /path/to/temp/dir/on/host
。这会将文件复制到主机,您可以使用主机工具检查文件。VOLUME
。然后你可以docker container inspect ${CONTAINER}
。这将显示文件所在的卷名。然后,您可以检查另一个容器中的那些(基于具有您需要的所有工具的图像)。/bin/ls
或/bin/sh
,那么你可以添加它们。如果您的临时容器正在运行,您可以将shell(以及其他所需的utils)复制到其文件系统中,然后执行它。 shell需要是一个静态二进制文件。 Busybox在这里是一个很好的选择,因为它可以像许多其他二进制文件一样加倍。
完整示例:
# Assumes scratch container is last launched one, else replace with container ID of
# scratch image, e.g. from `docker ps`, for example:
# scratch_container_id=401b31621b36
scratch_container_id=$(docker ps -ql)
docker run -d busybox:latest sleep 100
busybox_container_id=$(docker ps -ql)
docker cp "$busybox_container_id":/bin/busybox .
# The busybox binary will become whatever you name it (or the first arg you pass to it), for more info run:
# docker run busybox:latest /bin/busybox
# The `busybox --install` command copies the binary with different names into a directory.
docker cp ./busybox "$scratch_container_id":/busybox
docker exec -it "$scratch_container_id" /busybox sh -c '
export PATH="/busybin:$PATH"
/busybox mkdir /busybin
/busybox --install /busybin
sh'
对于Kubernetes,我认为Ephemeral Containers提供或将提供相同的功能。
参考文献:distroless java docker image error https://github.com/GoogleContainerTools/distroless/issues/168#issuecomment-371077961
您只能使用docker exec
来运行实际存在于容器中的命令。如果这些命令不存在,则无法运行它们。正如您所指出的那样,scratch
基本图像不包含任何内容 - 没有shell,没有库,没有系统文件,没有任何内容。
如果您要检查的是Dockerfile COPY
命令是否实际上复制了您所说的文件,我通常会假设工具正常工作,并且只是在我的应用程序中引用复制的文件。
因为它听起来像你控制Dockerfile,一个解决方法可能是将基本图像更改为轻量级但非空的,如FROM busybox
。这将为您提供一组最小的工具,您可以使用它们而不会过多地夸大图像大小。