docker 容器中的 rm -rf
似乎只适用于文件。
docker run ubuntu /bin/bash -c 'sudo rm -rf ./mydir; ls'
它在目录中列出mydir
而不打印任何错误。
我使用 ubuntu 14.04 作为主机和镜像。
编辑:
我以为是我在目录中添加了另一个文件后出现了这个错误,但我错了。最后,更改存储驱动程序有助于解决问题。
最佳答案
当您似乎无法删除目录时,有两种可能:
- 图像和容器之间的用户混淆。每个
docker run
创建一个新容器,并且容器中的任何更改(例如删除目录或运行修改文件系统的操作)都与原始镜像和所有其他容器隔离。 - Aufs layering bug/feature .看
docker info
查看您使用的是存储驱动程序 aufs 还是 imagemapper。要重新安装 docker 以使用 imagemapper:将任何不可替代的唯一图像备份到 tar 文件,删除 docker.io,从 ppa 中安装 lxc-docker,如 official install docs 中所述并更改/etc/default/docker
包含DOCKER_OPTS="--storage-driver=devicemapper"
提交目录然后删除它们也可能是一种反模式,因为该数据可能仍然存在于某处。即使它从文件系统中消失,它仍然可能在内部浪费空间。
Docker 镜像是分层构建的,每次提交就是一个层。
要查看此内容,请尝试 docker history <image>
看看你的图像中有什么。
第一个案例值得一个简短的例子,但看起来您可能正在经历第二个案例。
图像与容器和删除目录
让我们创建一个名为 mystuff
的私有(private)图像来自 ubuntu:14.04
然后在下面尝试 rm -rf/opt:
$ docker run -it ubuntu:14.04 /bin/bash
root@435e68479c5b:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@435e68479c5b:/# exit
$ docker commit 435e6 mystuff
让我们看看里面(-t
在这里只用于一行 pretty-print ):
docker run -t mystuff ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
现在让我们尝试删除 /opt
(通常这是可选的东西,可以安全删除):
docker run -t mystuff rm -rf /opt
再往里找,它还在!!! (似乎是报告的问题):
docker run -t mystuff ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
发生了什么?
- 每次
docker run mystuff
使用时,它会根据图像mystuff
创建一个新容器 - 除非您使用 docker commit,否则不会提交对镜像的更改
如果你查看容器,变化就在那里:
docker ps -a
... lots of stuff...
e9e8be13d928 mystuff:latest "rm -rf /opt" 2 minutes ago Exited (0) 2 minutes ago nostalgic_archimedes
取出一个 tarball 并查找 opt,用 grep 查找以 opt 开头的 dir,它不存在!:
docker export e9e8 | tar tv | grep ^opt
注意:e9e8
对我运行这个例子来说是特别的。要引用容器,您可以使用 docker ps
中的部分十六进制字符串在第一列。
现在我将具有 rm -rf 更改的容器提交到新镜像 noopt
:
docker commit e9e8 noopt
然后查看从 noopt 创建的容器内部:
docker run -t noopt ls
bin boot dev etc home lib lib64 media mnt proc root run sbin srv sys tmp usr var
果然,opt 不见了!
但是因为 docker 镜像是分层的,所以分发 noopt 会在更早的历史镜像中包含/opt,所以你不能阻止其他人取回它:
docker history noopt
IMAGE CREATED CREATED BY SIZE
bc4e69f9e871 59 minutes ago rm -rf /opt 0 B
d198d23dab38 About an hour ago /bin/bash 3 B
04c5d3b7b065 9 days ago /bin/sh -c #(nop) CMD [/bin/bash] 0 B
d735006ad9c1 9 days ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB
70c8faa62a44 9 days ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB
c7b7c6419568 9 days ago /bin/sh -c #(nop) ADD file:d4aab24fc178303dc0 192.5 MB
511136ea3c5a 18 months ago 0 B
要回到/opt 被移除之前的层,我们只需要选择 d198d... 并运行它
docker run -t d198d23dab38 ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
总结:
- Docker 有容器和镜像。
- 图像旨在更加永久。
- 图像在称为 commits 的层中创建,在概念上类似于 git 存储库
- 容器是从镜像创建的,容器中的更改不会保存在镜像中(除非明确提交)
Docker 还有一个很棒的构建系统,应该在这里使用。编写该脚本的人应该了解 docker build
并编写一个合适的 Dockerfile
关于ubuntu - 如何删除docker中的目录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27641558/