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

2021-08-12 09:09:08 +08:00
 chaker

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

不能正常启动的方式

`$ 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 之类的有关系吗? 谢谢。

2076 次点击
所在节点    Docker
20 条回复
gux928
2021-08-12 09:14:43 +08:00
我之前遇到过从 entrypoint 启动脚本,程序代码中的相对目录会有问题。
chaker
2021-08-12 09:21:54 +08:00
@gux928 不是相对目录的问题,我后来把这些目录都写成绝对路径也不行
passerbytiny
2021-08-12 09:29:24 +08:00
ENTRYPOINT 不定义的时候,容器启动起来就是个操作系统;定义的时候,容器启动时是先启动操作系统再执行 ENTRYPOINT 。你的两种方式在启动顺序上一样,但是执行脚本时的${PWD} 不一样。
thet
2021-08-12 09:32:07 +08:00
ENTRYPOINT 是在 docker run 后就会在容器执行的命令,后续的追加的命令只能作为参数,比如我把 redis-server 作为 ENTRYPOINT,那么 docker run 后只能追加 --port 之类的参数了,新的二进制命令是执行不了的。k8s 中 Command 可以替换 ENTRYPOINT
freevioce
2021-08-12 09:33:05 +08:00
@chaker 肯定是第一种好点 就一步 ,猜测是第二种 加载 bash 加载了必须的环境变量 对比下两种的环境变量看看
lcdtyph
2021-08-12 09:35:34 +08:00
shell 形式的 entrypoint 等价于
[ /bin/sh, -c, xxx.sh ]
/bin/sh 不一定是 bash
amrnxcdt
2021-08-12 09:52:36 +08:00
用“bash -x ./start_serve.sh”启动,看停止在哪一行。
chaker
2021-08-12 09:53:48 +08:00
@lcdtyph 用 docker inspect 看了下,ERTRYPOINT 里默认写的确实是 /bin/bash,我用的 tensorflow 的官方镜像
chaker
2021-08-12 09:55:55 +08:00
@passerbytiny @freevioce 对比了下,第一种方式里少了 PWD 、SHLVL 、PS1 、_和 LS_COLOR 这几个量,其他变量都是一样的,感觉不是他们的问题
chaker
2021-08-12 09:58:00 +08:00
@amrnxcdt start_serve.sh 里面其实就执行了一行 python server.py start,停在了一个加载 cdll 的地方,但是这个程序不应该在这里停,路径都是绝对路径,毕竟第二种方式都能起来。
freevioce
2021-08-12 10:06:04 +08:00
@chaker 你把 ENTRYPOINT 改成 /bin/sh 再 docker run -it .... 进入到 sh 执行 start_server.sh 看看能执行不
chaker
2021-08-12 10:13:29 +08:00
@freevioce 没有问题,可以运行,好像是只要分成两步就没问题,想一步起来就是不可以
AoEiuV020
2021-08-12 11:13:25 +08:00
我一般不配置 ENTRYPOINT 而是配置 CMD,可以试一下 CMD,
ENTRYPOINT 就默认的 bash -c,
Symo
2021-08-12 11:19:46 +08:00
主要是用途不一样, 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
2021-08-12 11:41:53 +08:00
docker 需要一个持久侦听的命令,你可以在脚本里面加个死循环来实现,不然就会挂掉
jingslunt
2021-08-12 12:15:52 +08:00
我是这么做的,用 shc 先把 shell 文件压缩成二进制执行文件,这时候执行旧无需考虑 sh 环境变量问题
luhuisicnu
2021-08-12 12:20:11 +08:00
区别在于守护进程不一样,dockerd, k8s 通过 entripoint 启动的进程来判断应用健康,这里面有很多自动化的东西可以做
chaker
2021-08-12 13:25:56 +08:00
@AoEiuV020 尝试过了,不行;D
chaker
2021-08-12 13:27:35 +08:00
@Symo 是这样,也做了些尝试,exec 和 shell 模式都尝试过,也试过只用 cmd,都不行
NathanInMac
2021-08-12 18:34:47 +08:00
printenv 对比一下就知道了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/795232

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX