Docker.io init.d 脚本在启动容器上不起作用

Posted

技术标签:

【中文标题】Docker.io init.d 脚本在启动容器上不起作用【英文标题】:Docker.io init.d script not working on start container 【发布时间】:2015-01-12 08:34:56 【问题描述】:

我在目录“/opt/odoo/”上有一个带有odoo 的容器。

“/etc/init.d/odoo-server”上的初始化脚本

#!/bin/bash
### BEGIN INIT INFO
# Provides:          odoo
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start openerp daemon at boot time
# Description:       Enable service provided by daemon.
# X-Interactive:     true
### END INIT INFO
## more info: http://wiki.debian.org/LSBInitScripts

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
DAEMON=/opt/odoo/openerp-server
NAME=odoo
DESC=odoo
CONFIG=/etc/odoo-server.conf
LOGFILE=/var/log/odoo/odoo-server.log
PIDFILE=/var/run/$NAME.pid
USER=odoo
export LOGNAME=$USER

test -x $DAEMON || exit 0
set -e

function _start() 
    start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$USER --background --make-pidfile --exec $DAEMON -- --config $CONFIG --logfile $LOGFILE


function _stop() 
    start-stop-daemon --stop --quiet --pidfile $PIDFILE --oknodo --retry 3
    rm -f $PIDFILE


function _status() 
    start-stop-daemon --status --quiet --pidfile $PIDFILE
    return $?



case "$1" in
        start)
                echo -n "Starting $DESC: "
                _start
                echo "ok"
                ;;
        stop)
                echo -n "Stopping $DESC: "
                _stop
                echo "ok"
                ;;
        restart|force-reload)
                echo -n "Restarting $DESC: "
                _stop
                sleep 1
                _start
                echo "ok"
             ;;
        status)
                echo -n "Status of $DESC: "
                _status && echo "running" || echo "stopped"
                ;;
        *)
                N=/etc/init.d/$NAME
                echo "Usage: $N start|stop|restart|force-reload|status" >&2
                exit 1
                ;;
esac

exit 0

那我做

root@cca438c81a87:/# update-rc.d odoo-server defaults
 Adding system startup for /etc/init.d/odoo-server ...
   /etc/rc0.d/K20odoo-server -> ../init.d/odoo-server
   /etc/rc1.d/K20odoo-server -> ../init.d/odoo-server
   /etc/rc6.d/K20odoo-server -> ../init.d/odoo-server
   /etc/rc2.d/S20odoo-server -> ../init.d/odoo-server
   /etc/rc3.d/S20odoo-server -> ../init.d/odoo-server
   /etc/rc4.d/S20odoo-server -> ../init.d/odoo-server
   /etc/rc5.d/S20odoo-server -> ../init.d/odoo-server

当我使用 docker start 启动 docker 时,odoo-server 没有启动,当我在 docker /etc/init.d/odoo-server start 内部运行时,它可以正常工作...

发生了什么?

【问题讨论】:

【参考方案1】:

Docker 容器通常没有正常运行的初始化系统。如果您只是运行一个服务——只需启动它。

如果您需要更复杂的东西,请查看supervisord 或runit。

容器不是虚拟机。

【讨论】:

我找到了将解决方案作为答案发布的要点:***.com/a/37289932/2544762 “容器不是虚拟机。” 不应该。您提供的软件能够提供解决 docker 错误的半解决方案,因此您的答案值得一提。【参考方案2】:

如果您正在寻找一个 Docker 镜像,它的行为与带有初始化系统的完整虚拟机非常相似,请查看 phusion baseimage

【讨论】:

我找到了将解决方案作为答案发布的要点:***.com/a/37289932/2544762【参考方案3】:

看起来你的 shebang 不正确,而不是 #!/bin/bash 应该是 #! /bin/sh

见:https://unix.stackexchange.com/questions/124566/how-to-debug-init-d-script-that-isnt-being-run

【讨论】:

不,添加空格对 shebang 行没有影响。见***.com/questions/10197690/perl-shebang-space【参考方案4】:

发现服务没有启动是因为/usr/sbin/policy-rc.d返回了101码:

见:http://jpetazzo.github.io/2013/10/06/policy-rc-d-do-not-start-services-automatically/

并且 docker 将其设置为在容器中返回 101。

因此,在构建时更改该脚本将起作用,您可以创建一个 build.sh 以在 Dockerfile 中运行并运行以下脚本:

cat << EOF > /usr/sbin/policy-rc.d
#!/bin/sh

# For most Docker users, "apt-get install" only happens during "docker build",
# where starting services doesn't work and often fails in humorous ways. This
# prevents those failures by stopping the services from attempting to start.

# exit 101
exit 0
EOF

【讨论】:

作为构建过程的一部分在 Dockerfile 中运行?因为我试过了。文件已更改,但说 /etc/init.d/postgresql 无法启动 这在更改文件并重新启动容器后不起作用。【参考方案5】:

现在我在几个小时的工作中找到了这个错误。

debian系统的主daemon starter/tester/stopper工具start-stop-daemon通过检查/proc/&lt;pid&gt;/exe中daemon进程的虚拟软链接来检查daemon是否存在的问题原因(应该指向已启动进程的二进制图像)。

现在的问题是,在 docker 中,这个软链接在默认情况下根本不起作用。这是因为 docker 在默认安装中必须使用严格的安全策略(它主要用于运行未识别的软件)。

该任务有很多变通方法,有些需要更改容器的权限设置,有些则不需要。两个例子:

您将初始化脚本更改为不使用带有--test--exec 标志的start-stop-daemon 你可以通过给docker run命令提供--cap-add=SYS_ADMIN选项来启动你的d​​ocker容器(别担心,它不会给你的docker容器任何sysadm权限,它可能只是生产使用的预防措施)李>

在这些旁边,systemd 在 docker 中也不起作用,尽管它可能更像是 systemd 的一个缺点,就像 docker 一样。可以使用upstart 代替systemd


P.s.:docker 开发者/倡导者经常说,“容器不是虚拟机”等等。但是,在日常体验中,两者之间并没有那么明显的区别,并且对于软件的高效 docker 使用,至少对类似 VPS 的功能的最小支持肯定是有用的。希望 docker 开发人员在不久的将来也能将精力集中在这个方向上。

【讨论】:

【参考方案6】:

s6 是轻量级进程管理器,suitable 用于 docker 容器 (via)

【讨论】:

以上是关于Docker.io init.d 脚本在启动容器上不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Mongo mongod init.d 脚本无法在 CentOS 上运行

Cent OS 上 nginx 的 Init.d 脚本 [关闭]

在 Ubuntu 中调试 /etc/init.d 启动脚本

在 openSUSE 上启动时运行脚本

docker容器启动时执行脚本 run /bin/bash执行多条指令

linux init.d启动停止脚本