docker 如何从零开始构建一个容器?

huwehgph  于 2023-01-20  发布在  Docker
关注(0)|答案(5)|浏览(153)

我试图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,我希望了解文件是否已经成功地从我的主机复制到容器中(我在Dockerfile中有一个COPY)。

i86rm4rw

i86rm4rw1#

如果你的临时容器正在运行,你可以复制一个shell(和其他需要的工具)到它的文件系统,然后执行它。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 www.example.comhttps://github.com/GoogleContainerTools/distroless/issues/168#issuecomment-371077961

64jmpszr

64jmpszr2#

有几种选择。
1.您可以执行docker container cp ${CONTAINER}:/path/to/file/on/container /path/to/temp/dir/on/host。这将把文件复制到您的主机上,您可以在那里使用主机工具检查内容。
1.你可以添加一个合适的VOLUME到你的Dockerfile。然后你可以docker container inspect ${CONTAINER}。这将暴露文件应该在的卷名。然后你可以在另一个容器中检查那些文件(基于一个镜像,使用你需要的所有工具)。
1.您可以在运行时将容器绑定到卷或主机目录的适当位置。
1.你可以把那些你觉得需要的二进制文件添加到镜像中,如果你需要/bin/ls/bin/sh,那么你可以添加它们。
1.您可以将必要的二进制文件绑定到容器-这样容器就可以使用它们进行验证,而映像不会因它们而膨胀。

htrmnn0y

htrmnn0y3#

你只能使用docker exec来运行容器中实际存在的命令。如果这些命令不存在,你就不能运行它们。正如你所注意到的,scratch基本映像包含 nothing -没有shell,没有库,没有系统文件,nothing
如果您要检查的只是Dockerfile COPY命令是否真的复制了您所说的文件,我通常会假设工具工作正常,只需在应用程序中引用复制的文件。
因为听起来像是你在控制Dockerfile,一个变通的方法是将基本映像更改为轻量级但非空的映像,如FROM busybox。这将为你提供一个最小的工具集,你可以使用它而不会过多地放大映像大小。

u4dcyp6a

u4dcyp6a4#

我尝试做同样的文件检查我的需要。我结束了docker cp复制这个文件从容器。在我的情况下,我使用nats容器,但你可以使用任何其他容器运行scratch-based-image

sudo docker cp nats_nats_1:/nats-server.conf ./nats-server.conf
gupuwyp2

gupuwyp25#

你可以直接获取容器标识符并将其放入一个变量中,例如,假设docker ps -a的(截断的)输出与你正在运行的容器一起列出:

CONTAINER ID  IMAGE

111111111111   neo4j-migrator

为了进一步说明该示例,可以使用所创建的变量docker exec -t。例如:

CONTAINER_ID=`docker ps -aqf "ancestor=neo4j-migrator"`
docker exec -it $CONAINER_ID \
 sh -c "/usr/bin/neo4j-migrations \
 --password $NEO4J_PASSWORD \
 --username $NEO4J_USERNAME \
 --address $NEO4J_URI \
 migrate"

相关问题