给容器加上 --read-only 之后,到底哪些地方还能写?为什么程序会因为找不到临时目录而启动失败?这篇逐个位置验证,并演示用 tmpfs 和 volume 开口子。
默认:
/new-file=可写; /tmp/x=可写; /var/tmp/x=可写; /dev/shm/x=可写; /run/x=可写; /etc/hosts=可写; /etc/resolv.conf=可写; /etc/hostname=可写; /data/x=可写; /usr/local/x=可写; MOUNT_/ ['rw']; tempfile=可用
--read-only:
/new-file=EROFS; /tmp/x=EROFS; /var/tmp/x=EROFS; /dev/shm/x=可写; /run/x=EROFS; /etc/hosts=EROFS; /etc/resolv.conf=EROFS; /etc/hostname=EROFS; /data/x=EROFS; /usr/local/x=EROFS; MOUNT_/ ['ro']; tempfile=FileNotFoundError [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp'默认容器里到处可写;加 --read-only 后根文件系统是 ro,连 Docker 生成的 /etc/hosts、/etc/resolv.conf、/etc/hostname 也变成只读。/dev/shm 仍然可写。
--read-only --tmpfs /tmp --tmpfs /run:
/new-file=EROFS; /tmp/x=可写; /var/tmp/x=EROFS; /dev/shm/x=可写; /run/x=可写; /etc/hosts=EROFS; /etc/resolv.conf=EROFS; /etc/hostname=EROFS; /data/x=EROFS; /usr/local/x=EROFS; MOUNT_/ ['ro']; tempfile=可用
--read-only -v 命名卷:/data:
/new-file=EROFS; /tmp/x=EROFS; /var/tmp/x=EROFS; /dev/shm/x=可写; /run/x=EROFS; /etc/hosts=EROFS; /etc/resolv.conf=EROFS; /etc/hostname=EROFS; /data/x=可写; /usr/local/x=EROFS; MOUNT_/ ['ro']; tempfile=FileNotFoundError [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp'
--read-only -v 命名卷:/data:ro:
/new-file=EROFS; /tmp/x=EROFS; /var/tmp/x=EROFS; /dev/shm/x=可写; /run/x=EROFS; /etc/hosts=EROFS; /etc/resolv.conf=EROFS; /etc/hostname=EROFS; /data/x=EROFS; /usr/local/x=EROFS; MOUNT_/ ['ro']; tempfile=FileNotFoundError [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp'很多程序默认往 /tmp 写临时文件。只读容器里 Python 的 tempfile 直接报找不到可用的临时目录。给 --tmpfs /tmp 就能恢复(c24 讲了 tmpfs 的大小和内存占用)。要保存的数据放命名卷或 bind mount,加 :ro 则也变只读。
HostConfig.ReadonlyRootfs = true 容器里往 /tmp(tmpfs)写了文件后,docker diff 输出:(空) 往 /root 写 → 退出码 1;sh: can't create /root/a: Read-only file system 对比:不带 --read-only 写 /root/a 和 /tmp/b 后,docker diff:C /tmp ; A /tmp/b ; C /root ; A /root/a
只读容器里没有可写层的改动,往 tmpfs 写的内容也不会出现在 docker diff;普通容器则会列出新增(A)和改动(C)。