ubuntu - 如何删除docker中的目录?

标签 ubuntu docker

docker 容器中的 rm -rf 似乎只适用于文件。

docker run ubuntu /bin/bash -c 'sudo rm  -rf ./mydir; ls'

它在目录中列出mydir而不打印任何错误。

我使用 ubuntu 14.04 作为主机和镜像。

编辑:

我以为是我在目录中添加了另一个文件后出现了这个错误,但我错了。最后,更改存储驱动程序有助于解决问题。

最佳答案

当您似乎无法删除目录时,有两种可能:

  1. 图像和容器之间的用户混淆。每个 docker run创建一个新容器,并且容器中的任何更改(例如删除目录或运行修改文件系统的操作)都与原始镜像和所有其他容器隔离。
  2. 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/

相关文章:

docker - 通过缓存模式拉入的私有(private) Docker 注册表返回 "invalid authorization credential"

适用于 Windows 10 的 ubuntu 应用程序上的 Docker 启动但未运行

ruby-on-rails - 如何在已经安装了 XAMPP 的 Ubuntu 12.10 中安装完整的 Ruby on Rails 环境?

ubuntu - 将 Ubuntu 14.04.5 LTS 中的 Solr 6.5.1 安装到自定义目录中

javascript - 只有 office 版本更改问题

amazon-web-services - 面临将 EFS 卷附加到 Kubernetes pod 的问题

python - 在Docker项目中保存更改

子进程等待父进程然后它执行,然后在 C linux 中反之亦然

c - 如何在Ubuntu 14.04上安装Frama-c影响分析插件?

angular - 动态部署 Angular。一个docker镜像,多个部署