V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chaker
V2EX  ›  Docker

docker exec 执行和在 ENTRYPOINT 里执行有什么区别

  •  
  •   chaker · 111 天前 · 1268 次点击
    这是一个创建于 111 天前的主题,其中的信息可能已经有所发展或是发生改变。

    做了个镜像,尝试两种启动方式,一种正常启动,一种启动到一半就直接退出了,啥原因呢?

    不能正常启动的方式

    `$ cat Dockerfile

    ...

    WORKDIR /WORKSPACE

    ...

    ENTRYPOINT ./start_server.sh `

    执行启动命令

    docker run --gpus all --name=XXX -it XXXIMG

    服务初始化到一半就直接崩掉了,日志里看不到错误信息

    可以正常启动的方式

    `$ cat Dockerfile

    ...

    WORKDIR /WORKSPACE

    ...

    #ENTRYPOINT ./start_server.sh `

    执行两步启动命令

    docker run --gpus all --name=XXX -it XXXIMG

    docker exec -it xx /bin/bash -c /workspace/start_server.sh

    服务一切正常,如预期。

    想问下这两种方式有什么区别呢? docker inspect 也看不出异常。和 stdin 、stdout 之类的有关系吗? 谢谢。

    20 条回复    2021-08-12 18:34:47 +08:00
    gux928
        1
    gux928   111 天前 via iPhone
    我之前遇到过从 entrypoint 启动脚本,程序代码中的相对目录会有问题。
    chaker
        2
    chaker   111 天前
    @gux928 不是相对目录的问题,我后来把这些目录都写成绝对路径也不行
    passerbytiny
        3
    passerbytiny   111 天前 via Android
    ENTRYPOINT 不定义的时候,容器启动起来就是个操作系统;定义的时候,容器启动时是先启动操作系统再执行 ENTRYPOINT 。你的两种方式在启动顺序上一样,但是执行脚本时的${PWD} 不一样。
    thet
        4
    thet   111 天前
    ENTRYPOINT 是在 docker run 后就会在容器执行的命令,后续的追加的命令只能作为参数,比如我把 redis-server 作为 ENTRYPOINT,那么 docker run 后只能追加 --port 之类的参数了,新的二进制命令是执行不了的。k8s 中 Command 可以替换 ENTRYPOINT
    freevioce
        5
    freevioce   111 天前
    @chaker 肯定是第一种好点 就一步 ,猜测是第二种 加载 bash 加载了必须的环境变量 对比下两种的环境变量看看
    lcdtyph
        6
    lcdtyph   111 天前 via iPhone
    shell 形式的 entrypoint 等价于
    [ /bin/sh, -c, xxx.sh ]
    /bin/sh 不一定是 bash
    amrnxcdt
        7
    amrnxcdt   111 天前 via Android
    用“bash -x ./start_serve.sh”启动,看停止在哪一行。
    chaker
        8
    chaker   111 天前
    @lcdtyph 用 docker inspect 看了下,ERTRYPOINT 里默认写的确实是 /bin/bash,我用的 tensorflow 的官方镜像
    chaker
        9
    chaker   111 天前
    @passerbytiny @freevioce 对比了下,第一种方式里少了 PWD 、SHLVL 、PS1 、_和 LS_COLOR 这几个量,其他变量都是一样的,感觉不是他们的问题
    chaker
        10
    chaker   111 天前
    @amrnxcdt start_serve.sh 里面其实就执行了一行 python server.py start,停在了一个加载 cdll 的地方,但是这个程序不应该在这里停,路径都是绝对路径,毕竟第二种方式都能起来。
    freevioce
        11
    freevioce   111 天前
    @chaker 你把 ENTRYPOINT 改成 /bin/sh 再 docker run -it .... 进入到 sh 执行 start_server.sh 看看能执行不
    chaker
        12
    chaker   111 天前
    @freevioce 没有问题,可以运行,好像是只要分成两步就没问题,想一步起来就是不可以
    AoEiuV020
        13
    AoEiuV020   111 天前
    我一般不配置 ENTRYPOINT 而是配置 CMD,可以试一下 CMD,
    ENTRYPOINT 就默认的 bash -c,
    Symo
        14
    Symo   111 天前
    主要是用途不一样, ENTRYPOINT 可以做一些初始化的工作, 但是也需要有能力处理 CMD 传进来的参数.

    #!/usr/bin/env sh

    set -e
    if [ "$1" = '/etc/init/docker-entrypoint.sh' ] && [ "$(id -u)" = '0' ]; then
    dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address
    echo "☆☆☆☆☆ base service has started. ☆☆☆☆☆"
    exec gosu www-data "$0" "[email protected]"
    fi
    exec "[email protected]"

    比如说我想在容器启动的时候预先运行 dbus, 那这个就可以写在 ENTRYPOINT, 然后容器执行的 CMD 也会传递到里面, 所以判断一下如果不是来自 docker-entrypoint.sh 执行的命令, 就直接执行
    maxbon
        15
    maxbon   111 天前
    docker 需要一个持久侦听的命令,你可以在脚本里面加个死循环来实现,不然就会挂掉
    jingslunt
        16
    jingslunt   111 天前
    我是这么做的,用 shc 先把 shell 文件压缩成二进制执行文件,这时候执行旧无需考虑 sh 环境变量问题
    luhuisicnu
        17
    luhuisicnu   111 天前
    区别在于守护进程不一样,dockerd, k8s 通过 entripoint 启动的进程来判断应用健康,这里面有很多自动化的东西可以做
    chaker
        18
    chaker   111 天前
    @AoEiuV020 尝试过了,不行;D
    chaker
        19
    chaker   111 天前
    @Symo 是这样,也做了些尝试,exec 和 shell 模式都尝试过,也试过只用 cmd,都不行
    NathanInMac
        20
    NathanInMac   111 天前
    printenv 对比一下就知道了
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2602 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 12:33 · PVG 20:33 · LAX 04:33 · JFK 07:33
    ♥ Do have faith in what you're doing.