问题现象
使用 budtmo/docker-android:emulator_14.0 首次启动正常,但 docker restart
之后只有 VNC 背景,Android 系统不再启动。
相关 issue:
https://github.com/budtmo/docker-android/issues/476
根因
cli/src/device/emulator.py 的 change_permission() 每次启动都会执行:
sudo chown 1300:1301 /dev/kvm
sudo sed -i '1d' /etc/passwd
其中 sed -i '1d' /etc/passwd 会删除 /etc/passwd 第一行(root 用户)。
首次启动: chown 成功 + root 被删除,模拟器正常。
重启后: sudo 因 "sudo: unknown user: root" 失败,
导致 chown /dev/kvm 无法执行,模拟器拿不到 KVM 权限,
于是无法启动。
修复内容
- 移除破坏性的 sudo sed -i '1d' /etc/passwd。
- chown 改用动态 uid/gid: sudo chown (os.getuid()):(os.getuid()):(os.getuid()):(os.getgid()) /dev/kvm。
- 新增 change_permission 单元测试(共 25 个测试全部通过)。
改动文件
- cli/src/device/emulator.py (核心修复)
- cli/src/tests/device/test_emulator.py (新增测试)
- Dockerfile.restart-fix (基于官方镜像打修复补丁)
核心代码修复 (change_permission)
修改前:
def change_permission(self) -> None:
kvm_path = "/dev/kvm"
if os.path.exists(kvm_path):
cmds = (f"sudo chown 1300:1301 {kvm_path}",
"sudo sed -i '1d' /etc/passwd")
for c in cmds:
subprocess.check_call(c, shell=True)
self.logger.info("KVM permission is granted!")
else:
raise RuntimeError("/dev/kvm cannot be found!")
修改后:
def change_permission(self) -> None:
kvm_path = "/dev/kvm"
if os.path.exists(kvm_path):
cmd = f"sudo chown {os.getuid()}:{os.getgid()} {kvm_path}"
subprocess.check_call(cmd, shell=True)
self.logger.info("KVM permission is granted!")
else:
raise RuntimeError("/dev/kvm cannot be found!")
Dockerfile.restart-fix 完整内容
FROM budtmo/docker-android:emulator_14.0
# Fix emulator not starting after `docker restart`.
#
# Root cause: change_permission() ran `sudo sed -i '1d' /etc/passwd` on every
# container start, deleting the `root` user from /etc/passwd. After the first
# run sudo breaks ("sudo: unknown user: root"), so on restart the
# `sudo chown ... /dev/kvm` command fails and the emulator can no longer
# access /dev/kvm (only the VNC background is shown).
# See https://github.com/budtmo/docker-android/issues/476
USER root
COPY cli/src/device/emulator.py /home/androidusr/docker-android/cli/src/device/emulator.py
RUN chown 1300:1301 /home/androidusr/docker-android/cli/src/device/emulator.py \
&& rm -rf /home/androidusr/docker-android/cli/src/device/__pycache__
USER 1300:1301
构建镜像
docker build -f Dockerfile.restart-fix -t yeshen/docker-android:emulator_14.0 .
使用方式
docker run -d --rm -p 6080:6080 \
-e EMULATOR_DEVICE="Samsung Galaxy S10" \
-e WEB_VNC=true \
--device /dev/kvm \
--name android-container \
yeshen/docker-android:emulator_14.0
https://hub.docker.com/repository/docker/yeshen/docker-android/general
验证结果
- 首次启动: 模拟器状态 READY
- docker restart 后: /dev/kvm 恢复为 root,但 /etc/passwd 中 root 保留
- 重启后模拟器再次 READY,/dev/kvm 正确 chown 为 androidusr