启动Docker容器时如何非交互式调用/bin/login?
解决Docker容器中非交互式执行/bin/login填充utmp的问题
核心问题
Docker容器启动时默认不会执行完整的登录流程,导致utmp文件无登录记录,依赖who命令的应用无法正常工作;直接用ENTRYPOINT/CMD调用/bin/login或bash --login都无法触发utmp更新——前者需要交互式输入,后者仅加载shell配置而非真正完成登录流程。
可行解决方案
方案1:用login -f强制无密码登录(推荐)
多数主流发行版的login命令支持-f参数(force login),可跳过密码验证直接完成登录并更新utmp,无需交互。
不同镜像的Dockerfile配置
Debian/Ubuntu
FROM debian:bookworm # 创建普通用户并删除密码(允许无密码登录) RUN useradd -m appuser && passwd --delete appuser # 启动时强制登录到appuser ENTRYPOINT ["/bin/login", "-f", "appuser"] # 登录后执行bash(替换为你的应用命令即可) CMD ["/bin/bash"]
Alpine
FROM alpine:latest RUN adduser -D appuser && passwd -d appuser ENTRYPOINT ["/bin/login", "-f", "appuser"] CMD ["/bin/sh"]
Fedora
FROM fedora:latest RUN useradd -m appuser && passwd -d appuser ENTRYPOINT ["/bin/login", "-f", "appuser"] CMD ["/bin/bash"]
验证方法
启动容器时需分配伪终端(否则部分系统的login会因无终端报错):
docker run -it --rm <你的镜像名>
执行who命令,就能看到appuser的登录记录。
方案2:用expect自动化交互登录(适用于必须保留密码的场景)
如果业务要求用户必须有密码,可通过expect脚本自动完成密码输入,模拟交互式登录流程。
Dockerfile配置(以Debian为例)
FROM debian:bookworm # 创建用户并设置密码 RUN useradd -m appuser && echo "appuser:mySecurePass123" | chpasswd # 安装expect工具 RUN apt-get update && apt-get install -y expect && rm -rf /var/lib/apt/lists/* # 编写自动登录的expect脚本 RUN echo '#!/usr/bin/expect set username "appuser" set password "mySecurePass123" # 启动login命令 spawn /bin/login $username # 匹配密码输入提示 expect "Password:" # 输入密码 send "$password\r" # 进入交互模式 interact ' > /auto_login.sh && chmod +x /auto_login.sh ENTRYPOINT ["/usr/bin/expect", "/auto_login.sh"]
验证方法
同样通过带终端的方式启动容器:
docker run -it --rm <你的镜像名>
脚本会自动完成登录,who命令可正常读取到登录用户。
额外说明
USER指令仅切换容器进程的运行用户,不会触发登录流程,因此无法更新utmp。- 若需后台运行容器且保持
utmp记录,可结合script命令模拟终端环境:docker run -d --name my_app <你的镜像名> script -q -c "/bin/login -f appuser && /path/to/your/app" /dev/null
内容的提问来源于stack exchange,提问作者Payne747
相关产品推荐
相关产品推荐

