chaker
V2EX  ›  Docker

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

By chaker at 2021 年 8 月 12 日 · 2933 次点击

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

不能正常启动的方式

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

比如说我想在容器启动的时候预先运行 dbus, 那这个就可以写在 ENTRYPOINT, 然后容器执行的 CMD 也会传递到里面, 所以判断一下如果不是来自 docker-entrypoint.sh 执行的命令, 就直接执行
maxbon
   15
maxbon  
   2021 年 8 月 12 日
docker 需要一个持久侦听的命令,你可以在脚本里面加个死循环来实现,不然就会挂掉
jingslunt
   16
jingslunt  
   2021 年 8 月 12 日
我是这么做的,用 shc 先把 shell 文件压缩成二进制执行文件,这时候执行旧无需考虑 sh 环境变量问题
luhuisicnu
   17
luhuisicnu  
   2021 年 8 月 12 日
区别在于守护进程不一样,dockerd, k8s 通过 entripoint 启动的进程来判断应用健康,这里面有很多自动化的东西可以做
chaker
   18
chaker  
OP
   2021 年 8 月 12 日
@AoEiuV020 尝试过了,不行;D
chaker
   19
chaker  
OP
   2021 年 8 月 12 日
@Symo 是这样,也做了些尝试,exec 和 shell 模式都尝试过,也试过只用 cmd,都不行
NathanInMac
   20
NathanInMac  
   2021 年 8 月 12 日
printenv 对比一下就知道了
© 2026 V2EX · 41ms · 3.9.8.5