• 请不要在回答技术问题时复制粘贴 AI 生成的内容
shijingshijing
V2EX  ›  程序员

docker 的 hello-world 这种运行完就退出的容器,有什么方法进去看看?

  •  
  •   shijingshijing · Aug 9, 2022 · 5642 views
    This topic created in 1548 days ago, the information mentioned may be changed or developed.

    体积这么小,纯粹比较好奇想进去看看。

    今天尝试了一下,不管是 attach 还是 exec 好像都不行。

    30 replies  •  2022-08-10 16:18:12 +08:00
    registerrr
    registerrr
    Aug 9, 2022
    1
    你想看啥?里边有啥东西 dockerfile 不都写着了么
    runo
    runo
    Aug 9, 2022
    2
    docker run -it image
    Vegetable
    Vegetable
    Aug 9, 2022
    3
    它本身就一层一条命令,所以小。

    docker run -it --rm hello-world sh
    Nitroethane
    Nitroethane
    Aug 9, 2022 via iPhone
    4
    用 Go 写一个项目,然后静态编译。写 dockerfile 的时候 from 指定 scratch ,然后把编译得到的静态链接的二进制文件扔进去,这样就得到了一个非常精简的镜像
    Noicdi
    Noicdi
    Aug 9, 2022
    5
    我有一个想法,用 hello-world 镜像做底,写 dockerfile ,带一个不断 sleep 的脚本,然后拉起来,再进去看看
    mxT52CRuqR6o5
    mxT52CRuqR6o5
    Aug 9, 2022
    6
    -it
    hwdef
    hwdef
    Aug 9, 2022
    7
    @Noicdi hello-world 镜像那么小,可能都没有 sleep 命令,进去的话也是要 shell 的。。可能都没有 shell
    lovelylain
    lovelylain
    Aug 9, 2022 via Android
    8
    想看什么?看里面有哪些文件的话可以 docker cp 或者 export
    Noicdi
    Noicdi
    Aug 9, 2022
    9
    @hwdef 是的,我用 sh 和 bash 试了半天拉不了
    然后去找了 hello-world 的官方,他们好像是直接写了二进制文件?

    FROM scratch
    COPY hello /
    CMD ["/hello"]

    https://github.com/docker-library/hello-world/tree/master/amd64/hello-world
    shijingshijing
    shijingshijing
    OP
    Aug 9, 2022
    10
    -it 不行的,自己试一下就知道了。官方的 dockerfile 里面只有一个底包,然后 CMD ["/hello"],这个 /hello 应该是编译好的二进制文件,直接执行。

    其实我的初衷是已经执行了 docker run hello-world ,这时候生成了一个 dc73aabc215 的 container ,我能有什么办法再进这个 container 里面去完成一些操作,比如把这个二进制的 hello 拷贝出来,或者添加一个 shell 脚本让 hello 循环跑几次? attach 和 exec /bin/bash 好像都不行。
    Belmode
    Belmode
    Aug 9, 2022
    11
    copy 一个 busybox 到容器里
    rrfeng
    rrfeng
    Aug 9, 2022
    12
    这玩意里面根本没有 shell ,进不去的。

    scratch 直接加二进制文件,整个镜像其实就只有你那个 hello-world 程序,没什么好看的。

    但是可以附加一个调试容器到运行中的容器上,共享一下 ns ,就能用调试容器的工具去调试它了。
    可以参考 kubectl debug ...
    kkocdko
    kkocdko
    Aug 9, 2022
    13
    bing 搜索 “docker shell”,第一条 stackoverflow 就是正确答案。我看了下第二条的文章更简洁: https://www.baeldung.com/ops/docker-container-shell

    总结就是如下命令,新建一个基于 ubuntu 的容器,进入容器的 bash:
    sudo docker rename $(sudo docker run --network=host -h docker -d ubuntu tail -f /dev/null) hi
    sudo docker exec -it hi bash
    kkocdko
    kkocdko
    Aug 9, 2022
    14
    哦上边已经有人提到了,scratch 没有任何东西,也没有 core-utils ,那就别折腾了呗。
    shijingshijing
    shijingshijing
    OP
    Aug 9, 2022
    15
    @kkocdko
    结果:

    docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "tail": executable file not found in $PATH: unknown.

    你给的那个例子里面 image 是 ubuntu ,应该能跑起来。hello-world 这个起不来,有点意思。。。

    我最后还有一个思路,把 hello-world 生成的 container 重新 build 成一个 image ,然后在这个 image 基础上,加一层 fs ,跑一下 /bin/bash
    shijingshijing
    shijingshijing
    OP
    Aug 9, 2022
    16
    @Belmode #11 提到的 busybox 估计也是可以的,毕竟自带一套完整的装备。
    cctv6
    cctv6
    Aug 9, 2022
    17
    `docker history hello-world`
    镜像里面只有一个可执行文件,用`docker run --rm -it hello-world sh`当然执行不了,执行 CMD 的前提是镜像里面有对应的文件。

    类似 golang 打包后,只有一个可执行文件,就可以用这个可执行文件基于 scratch 制作成一个镜像。
    Dockerfile:

    FROM scratch
    COPY abcd /abcd
    CMD abcd

    这样最后的效果和 hello-world 一样。
    cctv6
    cctv6
    Aug 9, 2022
    18
    还有一种情况,当 dockerfile 里面使用 ENTRYPOINT 指定启动脚本时,再使用`docker run -it image:tag bash` 的时候,这里的 bash 会被认为是 ENTRYPOINT 的参数,这个时候如果要进入容器内,就需要:`docker run -it --entrypoint /bin/sh image:tag` 进入容器,用--entrypoint 覆盖原来 dockerfile 里面的 entrypoint 。
    littlewing
    littlewing
    Aug 9, 2022
    19
    直接说你到底想干啥?只是好奇还是想实现某些功能?
    xiaon
    xiaon
    Aug 10, 2022 via iPhone
    21
    强行改变容器启动后的运行命令,一定是要工作在前台的都行,比如 sleep 600 ,让它睡眠 600 秒
    pepesii
    pepesii
    Aug 10, 2022
    22
    这个是个精简镜像,里头只有 hello 这个二进制可执行文件吧,说 sleep 和通过交互式 tty 的都不行的;
    体较小的原因是因为从 stractch 镜像来的,它的代码在这儿 https://github.com/docker-library/hello-world
    justNoBody
    justNoBody
    Aug 10, 2022
    23
    docker run -d --entrypoint sh IMAGE_ID -c "ping 127.0.0.1"

    如果没有 ping ,就试试其他可以一直循环执行的命令
    debuggerx
    debuggerx
    Aug 10, 2022❤️1
    24
    shijingshijing
    shijingshijing
    OP
    Aug 10, 2022
    25
    @debuggerx #24 这个工具不错,有点意思,收藏了。

    上面不管是-it, sleep, ping 都没有用的,基础镜像是 scratch 就真的是啥都没有。
    krly0912
    krly0912
    Aug 10, 2022
    26
    容器内需要有一个进程一直在运行才可以,不然会直接退出。把最后的`/bin/bash`替换为`/usr/sbin/init`
    yujinchn
    yujinchn
    Aug 10, 2022❤️1
    27
    运行这句 tail -f /dev/null
    jwenjian
    jwenjian
    Aug 10, 2022 via Android
    28
    dive
    xiaon
    xiaon
    Aug 10, 2022
    29
    因为这个镜像里面没有可用的 shell ,所以没法连接到容器里面,我试了下,可以这样,你把 busybox 镜像的 /bin 目录拷贝到你的宿主机上,再使用 Dockerfile 基于 hello-world 镜像,将 /bin 目录拷贝到 hello-world 镜像中的 / 目录下(bin 目录本身也要拷贝),做一个新的镜像,比如叫 hello-world2 ,这样你就可以基于 hello-world2 镜像启动一个容器,同时可以使用 -it sh 连接到容器中,其实镜像里面也没什么,主要就是一个主程序 /hello 脚本
    guanzhangzhang
    guanzhangzhang
    Aug 10, 2022
    30
    这个镜像里没 rootfs 阿,没有任何 shell 和命令,你真要搞就不应该用基础镜像是 scratch 的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1282 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 55ms · UTC 22:12 · PVG 06:12 · LAX 14:12 · JFK 17:12
    ♥ Do have faith in what you're doing.