CentOS 8 Docker环境中systemctl命令失效问题求助
问题背景
在Docker容器中安装Nuance Speech Suite时,安装脚本调用systemctl命令启动服务,出现错误:
System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down
使用以下命令构建镜像:
docker build -t myapp:11 .
即使添加--privileged或--cap-add=NET_ADMIN参数启动容器,执行systemctl仍报错:
docker run -it --privileged app:11 /bin/bash
docker run -it --cap-add=NET_ADMIN nuance:11 /bin/bash
Dockerfile内容
# syntax=docker/dockerfile:1 FROM centos:latest USER root RUN cd /etc/yum.repos.d/ RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* RUN yum -y update && \ yum clean all RUN yum -y install \ java-11-openjdk-devel \ perl-Data-Dumper \ redhat-lsb-core.x86_64 \ glibc.x86_64 \ glibc.i686 \ libstdc++.x86_64 \ libstdc++.i686 \ openssl \ libgcc \ libgcc.i686 \ libaio.x86_64 \ libaio.i686 \ libnsl.i686 \ ncurses-libs \ httpd.x86_64 \ unzip \ -x postfix \ -x mariadb-libs \ zlib.i686 \ zlib.x86_64 WORKDIR /tmp COPY Nuance_Speech_Suite-11.0.10-x86_64-linux.tgz ./Nuance_Speech_Suite-11.0.10-x86_64-linux.tgz COPY NRec-fr-FR-10.0.0-10.1.0.i686-linux.tar.gz ./languages/NRec-fr-FR-10.0.0-10.1.0.i686-linux.tar.gz COPY NVE_fr_FR_audrey-ml_xpremium-2.1.0_linux.zip ./languages/NVE_fr_FR_audrey-ml_xpremium-2.1.0_linux.zip COPY NRec-fr-FR-10.0.0-10.1.0-CumulativePatch-1_linux.zip ./languages/NRec-fr-FR-10.0.0-10.1.0-CumulativePatch-1_linux.zip COPY NRec-fr-FR-10.0.0-10.1.0-CumulativePatch-2_linux.zip ./languages/NRec-fr-FR-10.0.0-10.1.0-CumulativePatch-2_linux.zip COPY nuance.lic ./nuance.lic RUN tar -zxf Nuance_Speech_Suite-11.0.10-x86_64-linux.tgz RUN tar -zxf languages/NRec-fr-FR-10.0.0-10.1.0.i686-linux.tar.gz RUN unzip languages/NVE_fr_FR_audrey-ml_xpremium-2.1.0_linux.zip RUN unzip languages/NRec-fr-FR-10.0.0-10.1.0-CumulativePatch-1_linux.zip RUN unzip languages/NRec-fr-FR-10.0.0-10.1.0-CumulativePatch-2_linux.zip WORKDIR /tmp/Nuance_Speech_Suite-11.0.10 RUN ./setup.sh -s -f "/tmp/nuance.lic" -j "/usr/lib/jvm/java-11-openjdk" -V "/tmp/languages" -I "NLM,NSS"
构建日志错误片段
2022-12-16 09:22:11 setup.sh: info: Restarting the Nuance License Manager service
2022-12-16 09:22:11 setup.sh: info: starting command 'systemctl restart nuance-licmgr'; output sent to log
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
2022-12-16 09:22:11 setup.sh: info: Command 'systemctl restart nuance-licmgr' returned 1
2022-12-16 09:22:11 setup.sh: error: install_postprocessing_nlm_startservices() failed to start services
2022-12-16 09:22:11 setup.sh: info: skipping invocation of install_postprocessing_nms() due to previous post processing errors
2022-12-16 09:22:11 setup.sh: info: Skipping install_execute_installsuite due to previous errors
解决办法
方法1:让容器以systemd为PID 1运行
Docker容器默认PID 1不是systemd,需修改启动方式让systemd成为init进程:
- 修改Dockerfile,在末尾添加:
CMD ["/usr/sbin/init"] - 构建镜像后,用以下命令启动容器:
docker run -d --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro myapp:11--privileged和挂载/sys/fs/cgroup是systemd正常运行的必要条件。
方法2:修改安装脚本跳过systemctl调用
若不想用systemd管理容器服务,可修改setup.sh脚本:
- 解压安装包后,编辑
setup.sh,找到调用systemctl restart nuance-licmgr的部分,注释掉或替换为直接启动服务的命令(如/path/to/nuance-licmgr start)。 - 查看
./setup.sh --help是否有跳过服务启动的参数(如--no-start-services),若有则添加该参数运行脚本。
方法3:用supervisord管理服务
放弃systemd,改用supervisord管理Nuance服务:
- 在Dockerfile中安装supervisord:
RUN yum install -y supervisor && mkdir -p /var/log/supervisor - 创建
/etc/supervisord.conf配置文件,添加Nuance服务启动配置:[supervisord] nodaemon=true [program:nuance-licmgr] command=/path/to/nuance-licmgr start autorestart=true stdout_logfile=/var/log/supervisor/nuance-licmgr.log stderr_logfile=/var/log/supervisor/nuance-licmgr.err.log - 修改Dockerfile的CMD为启动supervisord:
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
内容的提问来源于stack exchange,提问作者jeyGey

