dind(docker in docker)镜像-使用Docker学习Docker

article/2025/8/17 16:50:01

文章目录

  • 使用Docker学习Docker
    • 一、搭建演示环境
    • 二、关联基础
        • docker image 文件系统
        • 什么是image layer
        • Dockerfile VOLUME(数据卷) 指令
          • Volume命令的使用
        • 什么是container-diff
          • 使用
    • 三、演示时间
      • 探索 docker create 命令
      • 探索 docker start 命令
      • 探索 docker stop 命令
      • 探索 docker exec 命令
    • 四、总结

使用Docker学习Docker

Learning Docker with Docker - Toying With DinD For Fun And Profit

您是否曾经注意到,一半的容器管理命令看起来像进程管理操作,而另一半则看起来像文件管理操作?
在这里插入图片描述

这里有一个小练习来加深你对容器的理解… 通过玩转它们,我们的目标是证明容器不仅仅是 Linux 进程,它也是 Linux文件!

这个想法很简单——用一台安装了 Docker 守护进程的 Linux 机器,在上面运行一系列常用的命令,比如 Docker create | start | exec | … 密切关注机器的文件系统,希望能有一些有趣的发现。

🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱🌱

一、搭建演示环境

首先,简单介绍一下临时演示环境。基本上,任何运行 Docker 的干净 Linux 机器都可以。但是由于我们想要跟踪主机文件系统上 created/deleted/modified的文件,我们应该在每个 docker <command> 之后对它进行快照,以便之后对比这些快照。

这听起来确实像是 Docker-in-Docker 的一个很好的用例。如果实验的Docker 守护进程本身运行在容器中,我们可以随时使用标准 docker commit <CONTAINER> 命令将容器的文件系统转储到 image layer。由于容器镜像可以很容易地进行对比,我们可以使用类似 container-diff 的工具来计算两个对比快照的文件差异。

但是官方的 docker:dind容器镜像 不能用,因为它包含一个特定的 VOLUME 指令。该指令存在的理由很充分——将 /var/lib/docker文件夹移出容器的(slow and expensive)联合文件系统。然而,正如你马上会看到的,这个文件夹将是我们实验中最热门的位置之一。因此,我们需要确保将/var/lib/docker提交到快照镜像,不需要volumes。

$ git clone https://github.com/docker-library/docker.git
$ cd docker/20.10/dind
$ sed -i '/VOLUME/d' ./Dockerfile
$ docker build -t my-dind:origin .

另一个重要的要求是保持环境的足够小和可控性。为此,我们需要使用一个超小的测试容器镜像,其中包含我们在对实验Docker 守护进程(guinea-pig Docker daemon)进行实验时所需要的内容。一个从头开始的镜像,里面有一个简单的 Go 二进制文件,听起来是一个不错的选择。但是,这个镜像应该在实例构建容器镜像之外构建,因为这涉及到运行临时容器,因此可能会破坏临时环境。

There are many ways to build and distribute images, but for our experiment, I ended up with probably the simplest possible setup:
有许多方法可以构建和发布镜像,但是对于我们的实验,最终得到了可能是最简单的设置:
在这里插入图片描述
以下是如何在运行 Docker 的Linux计算机上运行上述设置:

# 1. Prepare config to make Docker trust the local registry:
$ cat > daemon.json <<EOF
{"insecure-registries" : ["my-registry:5000"]
}
EOF# 2. 将上述配置放入
#    the host's /etc/docker/daemon.json# 3. Restart the host's Docker daemon:
$ sudo systemctl restart docker.service# 4. Create a user-defined network to allow the DinD container
#    access the Registry container by its hostname:
$ docker network create skynet# 5. Run an (insecure) local registry:
$ docker run --detach \--network skynet \--publish 5000:5000 \--name my-registry \registry:2# 6. Make the local registry addressible from the host system:
$ REGISTRY_IP=$(docker inspect \-f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \my-registry)
$ echo "$REGISTRY_IP my-registry" | sudo tee --append /etc/hosts# 7. Run the guinea-pig Docker daemon using the patched DinD image:
$ docker run --detach --privileged \--network skynet \--volume `pwd`/daemon.json:/etc/docker/daemon.json \--name my-dind \my-dind:origin# 8. Commit the initial state of the guinea-pig Docker system
#    as the starting point for further comparisons:
$ docker commit my-dind my-dind:just-started# [Optional] See what changes have been made to my-dind
# container's filesystem during the container's startup:
$ container-diff diff --type=file \daemon://my-dind:origin \daemon://my-dind:just-started

现在,准备测试应用程序——一个简单的 HTTP 程序和一个sleep的cli工具:

# syntax=docker/dockerfile:1.4# ---=== This part is just for building ===---
FROM golang:1.18 as builderWORKDIR /COPY <<EOF server.go
package mainimport ("fmt""log""net/http"
)func main() {log.Println("Starting HTTP server...")http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {log.Println("Incoming request")fmt.Fprintf(w, "hello\n")})http.ListenAndServe(":8090", nil)
}
EOFCOPY <<EOF sleep.go
package mainimport ("log""time"
)func main() {for {log.Println("Zzz...")time.Sleep(1 * time.Second)}
}
EOFRUN CGO_ENABLED=0 go build -o server server.go
RUN CGO_ENABLED=0 go build -o sleep sleep.go# ---=== This is the actual testing image, quite minimalistic ===---
FROM scratchCOPY --from=builder /server /server
COPY --from=builder /sleep /sleepCMD ["/server"]

Last but not least:

docker buildx build -t my-registry:5000/my-app .
docker push my-registry:5000/my-app

二、关联基础

docker image 文件系统

一图看尽 Docker 容器文件系统
参考URL: https://zhuanlan.zhihu.com/p/362132467

docker 容器启动就是一个文件系统的启动。在docker中,每一层镜像都具备一些文件。

构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层的修改,增加了一层文件系统。一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层把底层遮住了一样。当你使用的时候,你只会看到一个完全的整体,你不知道里面有几层,也不清楚每一层所做的修改是什么。

从基本的看起,一个典型的Linux文件系统由bootfs和rootfs两部分组成,bootfs(boot file system)主要包含bootloader和kernel,bootloader主要用于引导加载kernel,当kernel被加载到内存中后bootfs会被umount掉。rootfs (root file system)包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。不同的linux发行版(如ubuntu和CentOS )在rootfs这一层会有所区别,体现发行版本的差异性。

但Docker在bootfs自检完毕之后并不会把rootfs的read-only改为read-write,而是利用union mount(UnionFS的一种挂载机制)将image中的其他的layer加载到之前的read-only的rootfs层之上,每一层layer都是rootfs的结构,并且是read-only的。所以,我们是无法修改一个已有镜像里面的layer的!只有当我们创建一个容器,也就是将Docker镜像进行实例化,系统会分配一层空的read-write的rootfs,用于保存我们做的修改。一层layer所保存的修改是增量式的,就像git一样。

综上,image其实就是一个文件系统,它与宿主机的内核一起为程序提供一个虚拟的linux环境。在启动docker container时,依据image,docker会为container构建出一个虚拟的linux环境。

Docker目前支持五种镜像层次的存储driver:aufs、device mapper、btrfs、vfs、overlay。

其中最常用的就是aufs了,但随着linux内核3.18把overlay纳入其中,overlay的地位变得更重目前docker默认的存储类型就是overlay2,docker版本是1.8,如下
在这里插入图片描述
docker默认的存储目录是/var/lib/docker,我们只关心image和overlay2,image:主要存放镜像中layer层的元数据和overlay2:各层的具体信息。

什么是image layer

Dockerfile由多条指令构成,Dockerfile中的每一条指令都会对应于Docker镜像中的一层。

如下Dockerfile

FROM ubuntu:14.04
ADD run.sh /
VOLUME /data
CMD ["./run.sh"]

通过docker build以上Dockerfile的时候,会在Ubuntu:14.04镜像基础上,添加三层独立的镜像,依次对应于三条不同的命令。镜像示意图如下:
在这里插入图片描述
Dockerfile中命令与镜像层一一对应,那么是否意味着docker build完毕之后,镜像的总大小=每一层镜像的大小总和呢?答案是肯定的。依然以上图为例:如果ubuntu:14.04镜像的大小为200MB,而run.sh的大小为5MB,那么以上三层镜像从上到下,每层大小依次为0、0以及5MB,那么最终构建出的镜像大小的确为0+0+5+200=205MB。

Dockerfile VOLUME(数据卷) 指令

有状态容器都有数据持久化需求。Docker 采用 AFUS 分层文件系统时,文件系统的改动都是发生在最上面的容器层。在容器的生命周期内,它是持续的,包括容器在被停止后。但是,当容器被删除后,该数据层也随之被删除了。因此,Docker 采用 volume (卷)的形式来向容器提供持久化存储。

想要了解Docker Volume,首先我们需要知道Docker的文件系统是如何工作的。Docker镜像是由多个文件系统(只读层)叠加而成。当我们启动一个容器的时候,Docker会加载只读镜像层并在其上(译者注:镜像栈顶部)添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏。当删除Docker容器,并通过该镜像重新启动时,之前的更改将会丢失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。

为了能够保存(持久化)数据以及共享容器间的数据,Docker提出了Volume的概念。简单来说,Volume就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。

Volume:即数据卷。

  • Docker Volume命令能让容器从宿主主机中读取文件,或从容器中持久化数据到宿主主机内,让容器与容器产生的数据分离开来,一个容器可以挂载多个不同的目录。
  • Volume的生命周期是独立于容器的生命周期之外的,即使容器删除了,volume(数据卷)也会被保留下来,Docker也不会因为这个volume(数据卷)没有被容器使用而回收。
  • 在容器中,添加或修改这个文件夹里的文件也不会影响容器的联合文件系统。

作用:创建一个匿名数据卷挂载点
格式:

VOLUME ["/data"] 

详解:运行容器时可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保持的数据等

这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化

Volume命令的使用

(1)创建数据卷
命令:docker volume create 自定义名称

root@cka-k8s-master:~# docker volume create myVolume
myVolume
root@cka-k8s-master:~#

每创建一个Volume,Docker默认会在宿主机的/var/lib/docker/volumes/目录下创建一个子目录,默认情况下目录名是一串UUID。
如果指定了名称,则目录名是Volume名称(例如上面的myVolume)。Volume里的数据都存储在这个子目录的_data目录下。
之后我们可以把这个数据卷挂载到一个新的容器中,例如Nginx容器。

(2)查看本地数据卷列表
命令:docker volume ls

root@cka-k8s-master:~# docker volume ls
DRIVER VOLUME NAME
local myVolume
root@cka-k8s-master:~#

(3)打印myVolume数据卷的详细信息
命令:docker volume inspect 一个或多个Volume名称

root@cka-k8s-master:~# docker volume inspect myVolume
[{"CreatedAt": "2022-04-27T10:21:53Z","Driver": "local","Labels": {},"Mountpoint": "/data/docker/volumes/myVolume/_data","Name": "myVolume","Options": {},"Scope": "local"}
]
root@cka-k8s-master:~#
  • 每创建一个Volume,Docker默认会在宿主机的/var/lib/docker/volumes/目录下创建一个子目录,默认情况下目录名是一串UUID。

  • 如果指定了名称,则目录名是Volume名称(例如上面的myVolume)。Volume里的数据都存储在这个子目录的_data目录下。

具名挂载和匿名挂载
(1)匿名挂载
匿名挂载格式:-v /容器内路径或者-v /宿主机路径:/容器内路径
(2)具名挂载
  指令:docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx

注意:这里 -v juming-nginx: 代表直接给定名字,但是没有指定路径
在这里插入图片描述
  如图,查看数据卷一栏增加了刚刚添加的数据卷。

什么是container-diff

官方github: https://github.com/GoogleContainerTools/container-diff

container-diff 是 Google 开源的一个分析和比较容器镜像的工具,可用来分析 Docker 镜像之间的差异。

container-diff 可通过几个不同的标准(角度)来检查镜像,包括:

  • Docker 镜像历史
  • 镜像文件系统
  • Apt 包管理器
  • pip 包管理器
  • npm 包管理器
使用

分析单个Docker镜像

container-diff analyze <image-name>

对比两个Docker镜像

container-diff diff <image1-name> <image2-name>

如果不指定type,默认分析/对比的是镜像大小,即–type=size
可以通过指定type,分析/对比特定维度

container-diff analyze <image-name> --type=<type-name>
container-diff diff <image1-name> <image2-name> --type=<type-name>

type类型支持如下:

  • history:镜像构建历史
  • file:镜像文件
  • size:镜像大小
  • rpm:rpm包管理器
  • pip:pip包管理器
  • apt:apt包管理器
  • node:node包管理器

通过设置--type=file和--filename=/path/file,可以比较比较两个docker镜像中某目录或文件的区别,例如:

container-diff diff nginx:v1 nginx:v2 --type=file --filename=/etc/  

复制代码通过设置-j,可以使用json格式输出结果。
通过设置-w ,可以将结果输入到文件。

三、演示时间

For the experiment itself, I’ll use two terminals simultaneously:
对于实验本身,我将同时使用两个终端:

如下,我们进入到 my-dind 容器中,使用docker ps,在容器中我们看到其他容器- -!这就是容器中的容器!

# Terminal 1 - DinD
$ docker exec -it my-dind sh
$ docker ps<empty># Terminal 2 - host system
$ docker ps
CONTAINER ID  IMAGE           COMMAND                 ...  STATUS         NAMES
d07b66a353b0  my-dind:origin  "dockerd-entrypoint.…"  ...  Up 25 minutes  my-dind
9a6addf796f6  registry:2      "/entrypoint.sh /etc…"  ...  Up 26 minutes  my-registry

探索 docker create 命令

第一个实验——使用 DinD Docker 实例创建一个 my-app 容器,然后看看会创建哪些文件:

在这里插入图片描述
使用两个终端进行实验-DinD 在左边,主机在右边。

# Terminal 1 (DinD)# Create container:
$ docker create --name my-app my-registry:5000/my-app# List existing containers:
$ docker ps -a
CONTAINER ID  IMAGE                    COMMAND    ... STATUS   NAMES
2c23a0da2b19  my-registry:5000/my-app  "/server"      Created  my-app# List running processes:
$ ps auxf
PID   USER     TIME  COMMAND1 root      0:00 docker-init -- dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.61 root      0:00 dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsv70 root      0:21 containerd --config /var/run/docker/containerd/containerd.toml --log-level176 root      0:00 sh232 root      0:00 ps auxf

发现 # 1: docker create 创建了一个容器,但是没有创建任何新的进程!

# Terminal 2 (Host)# Snapshot the DinD container filesystem:
$ docker commit my-dind my-dind:cont-created# Compare the current state with the previous one:
$ container-diff diff --type=file \daemon://my-dind:just-started \daemon://my-dind:cont-created-----File-----These entries have been added to my-dind:just-started:  # <-- looks like a bug in container-diff output
FILE
...
# This group of files seems important
/var/lib/docker/buildkit/cache.db
/var/lib/docker/buildkit/containerdmeta.db
/var/lib/docker/buildkit/content
/var/lib/docker/buildkit/content/ingest
/var/lib/docker/buildkit/executor
/var/lib/docker/buildkit/metadata_v2.db
/var/lib/docker/buildkit/snapshots.db# So... This is where containers live on disk!
/var/lib/docker/containers/<CONTAINER-ID>
/var/lib/docker/containers/<CONTAINER-ID>/checkpoints
/var/lib/docker/containers/<CONTAINER-ID>/config.v2.json
/var/lib/docker/containers/<CONTAINER-ID>/hostconfig.json# And this is where images live
/var/lib/docker/image
...
# Look ma', our `app` image files!
/var/lib/docker/vfs/dir/<LAYER-ID1>
/var/lib/docker/vfs/dir/<LAYER-ID1>/server
/var/lib/docker/vfs/dir/<LAYER-ID2>
/var/lib/docker/vfs/dir/<LAYER-ID2>/server
/var/lib/docker/vfs/dir/<LAYER-ID2>/sleep
...These entries have been deleted from my-dind:just-started: NoneThese entries have been changed between my-dind:just-started and my-dind:cont-created:
FILE
/certs/...

发现 # 2: /var/lib/docker/containers/<container-id> ——这是我们的容器在磁盘存储的文件。

发现 # 3: docker create 似乎与 runc create 非常不同——到目前为止还没有创建任何运行时绑定!

Finding #4: Container logs aren’t a thing at this stage yet. The container-diff output above is abridged, but if you’re performing this exercise while reading the article, try searching for files containing the log word in their name - you won’t find anything.

发现 # 4: 在此阶段,容器日志还找不到。上面的container-diff输出是删减的,但是如果您在阅读文章时执行此练习,请尝试搜索包含其名称的日志单词的文件 - 您找不到任何东西。

探索 docker start 命令

是时候启动 my-app 容器了:

# Terminal 1 (DinD)$ docker start my-app$ docker ps -a
CONTAINER ID  IMAGE                    COMMAND    ...  STATUS         NAMES
435edb948b83  my-registry:5000/my-app  "/server"       Up 21 seconds  my-app$ ps auxf
PID   USER     TIME  COMMAND1 root      0:00 docker-init -- dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsverify --tlscacert /certs/server/ca.pem --tlscert /certs/server/cert.pem --tlskey /certs/server/key.pem60 root      0:00 dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsverify --tlscacert /certs/server/ca.pem --tlscert /certs/server/cert.pem --tlskey /certs/server/key.pem69 root      0:07 containerd --config /var/run/docker/containerd/containerd.toml --log-level info210 root      0:00 sh265 root      0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace moby -id 435edb948b8360ffcbae5452fd6fc0451b5c17daf6940f63db6795c099958357 -address /var/run/docker/containerd/containerd.sock
👉284 root      0:00 /server320 root      0:00 ps auxf

那么,已经创建了哪些文件?

# Terminal 2 (Host)$ docker commit my-dind my-dind:cont-started# Compare the current state with the previous one:
$ container-diff diff --type=file \daemon://my-dind:cont-created \daemon://my-dind:cont-started-----File-----These entries have been added to my-dind:cont-created:  # <-- rather in cont-started...
FILE
...# Here it goes - the OCI runtime bundle!
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/address
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/config.json
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/init.pid
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/log.json
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/options.json
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/rootfs
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/runtime
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/work
...

发现 # 5: OCI runtime bundle 是在容器启动时创建的,而不是在容器创建时创建的。

发现 # 6: bundle 是在临时文件系统上创建的! 我现在很好奇——它总是这样吗?

发现 #7: Container logs finally appeared, and it’s just a plain file on disk (depends on the log driver, though):
最终出现了容器日志,它只是磁盘上的一个普通文件(不过取决于日志驱动程序):

📦 # Terminal 1 (DinD)cat /var/lib/docker/containers/<CONTAINER-ID>/<CONTAINER-ID>-json.log
{"log":"2022/04/26 05:21:59 Starting HTTP server...\n","stream":"stderr","time":"2022-04-26T05:21:59.3588249Z"}

探索 docker stop 命令

那么,当您停止容器时会发生什么? 它的文件会被删除吗?

# Terminal 1 (DinD)$ docker stop my-app$ docker ps -a
CONTAINER ID  IMAGE                    COMMAND    ...  STATUS                    NAMES
435edb948b83  my-registry:5000/my-app  "/server"       Exited (2) 2 seconds ago  my-app$ ps auxf
PID   USER     TIME  COMMAND1 root      0:00 docker-init -- dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsverify --tlscacert /certs/server/ca.pem --tlscert /certs/server/cert.pem --tlskey /certs/server/key.pem60 root      0:00 dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsverify --tlscacert /certs/server/ca.pem --tlscert /certs/server/cert.pem --tlskey /certs/server/key.pem69 root      0:10 containerd --config /var/run/docker/containerd/containerd.toml --log-level info210 root      0:00 sh372 root      0:00 ps auxf

发现 # 8: 停止容器会删除 OCI runtime bundle,但不会删除容器在/var/lib/docker/<container-id>的状态(除非 --rm 在创建步骤中被使用)。所以,重新开始是可能的!

探索 docker exec 命令

让我们重复这个实验,但是这一次试着捕捉当你执行到一个运行的容器中时会发生什么:

# Terminal 1 (DinD)$ docker start my-app# ...jump to the second terminal for a second# Terminal 2 (Host)$ docker commit my-dind my-dind:cont-restarted# ...back to the DinD terminal# Terminal 1 (DinD)
$ docker exec -it my-app /sleep
2022/04/21 19:19:52 Zzz...
2022/04/21 19:19:53 Zzz...
2022/04/21 19:19:54 Zzz...
2022/04/21 19:19:55 Zzz...
2022/04/21 19:19:56 Zzz...# Terminal 3 (also DinD)
$ ps auxf
PID   USER     TIME  COMMAND1 root      0:00 docker-init -- dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsverify --tlscacert /certs/server/ca.pem --tlscert /certs/server/cert.pem --tlskey /certs/server/key.pem60 root      0:00 dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsverify --tlscacert /certs/server/ca.pem --tlscert /certs/server/cert.pem --tlskey /certs/server/key.pem69 root      0:07 containerd --config /var/run/docker/containerd/containerd.toml --log-level info210 root      0:00 sh265 root      0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace moby -id 435edb948b8360ffcbae5452fd6fc0451b5c17daf6940f63db6795c099958357 -address /var/run/docker/containerd/containerd.sock
👉284 root      0:00 /server320 root      0:00 ps auxf
👉363 root      0:00 /sleep

但是在实际执行期间究竟发生了什么?

# Terminal 2 (Host)$ docker commit my-dind my-dind:cont-execed$ container-diff diff --type=file \daemon://my-dind:cont-restarted \daemon://my-dind:cont-execed-----File-----These entries have been added to my-dind:cont-restarted:
FILE
/run/docker/containerd/daemon/io.containerd.runtime.v2.task/moby/<CONTAINER-ID>/<SOME-OTHER-ID>.pidThese entries have been deleted from my-dind:cont-restarted: None
These entries have been changed between my-dind:cont-restarted and my-dind:cont-execed: None

好吧,这是令人惊讶的!我期待着为 exec 会话创建另一个临时(和匿名)容器,因为 exec 不是真正的 OCI 运行时命令,而只是由 Docker 和类似的容器管理器实现的一个方便的高级操作,它重用 OCI 运行时 start 命令。但是实际的实现似乎非常轻量级,并且使用与主容器相同的 OCI runtime bundle。

发现 # 9: docker exec 几乎没有文件系统足迹!

四、总结

好吧,我希望这是一个有趣的练习至少对我来说,现在我明白了为什么一半的容器管理命令看起来像文件管理操作——容器与文件和进程一样重要。


http://chatgpt.dhexx.cn/article/dr6N0OYy.shtml

相关文章

Docker学习1 - Docker

Docker 在部署中的重要性 直接把程序安装或部署在Linux操作系统上面&#xff0c;很容易引发资源冲突程序卸载不干净&#xff0c;导致无法安装或部署新程序每次部署之前要安装很多软件&#xff0c;修改复杂的配置文件无法让服务器硬件资源实现多租户服务增大了在Linux系统上部署…

Docker学习记录-01

Docker 的基本组成 镜像(image): 好比一个模板,tomcat -> run -> tomcat01 (container) 镜像可以创建多个容器 容器(container): 容器可以启动&#xff0c;停止&#xff0c;删除&#xff0c;基本命令 容器就是一个简易的Linux系统 仓库(repository)&#xff1a; 存…

docker学习之Ubuntu系统部署docker

目录 安装环境&#xff1a; 支持安装docker的Ubuntu操作系统版本 卸载旧版本的docker 安装docker所需要的依赖包 添加Docker的官方GPG密钥&#xff1a; 设置docker的镜像仓库 安装docker引擎 测试docker 卸载Docke ​​​​安装完毕。 安装环境&#xff1a; Linux系…

Docker学习2

文章目录 Docker学习Docker镜像是什么特点Docker镜像commit操作补充 Docker容器数据卷是什么能干嘛数据卷容器内添加 数据卷容器 DockerFile解析是什么DockerFile构建过程解析基础知识Docker执行DockerFile的大致流程 DockerFile体系结构&#xff08;保留字指令&#xff09;Doc…

Docker学习自我总结(一)

以下内容皆参考至狂神说docker学习视频 一、初识dockerfile ​ docker镜像创建时需要使用dockerfile&#xff0c;dockerfile相当于一个命令脚本&#xff0c;通过这个脚本可以生成镜像&#xff0c;镜像是一层一层的&#xff0c;脚本一个个的命令&#xff0c;每个命令都是一层&…

Docker 学习笔记

Docker 学习笔记 Docker 安装CentOS 安装 DockerUbuntu 安装 Docker Docker 常用命令 Docker 实操记录Docker 安装mysqlDocker 部署 jupyter notebook Docker 安装 CentOS 安装 Docker 以下是docker官网的安装教程&#xff0c;我只是将命令都提取出来 按下列顺序逐步输入即可…

docker 学习

centos7安装docker 步骤 1、Docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企业版EE。 社区版是免费提供给个人开发者和小型团体使用的,企业版会提供额外的收费服务,比如经过官方测试认证过的基础设施、容器、插件等。 社区版按照stable和edge两种方式发…

docker学习1

1.docker常用管理命令 格式 docker image 【】 ls 列出镜像 bulid 构建镜像利用dockerfile history 查看 inspect 显示一个或多个镜像的详细信息 pull 从镜像仓库拉取镜像 rm 移除一个或多个镜像 push 推送一个镜像到镜像仓库 prune 移除没有被…

docker 学习总结

只要学不死&#xff0c;就往死了学。 docker学习目录 docker概述docker安装docker基本组成 镜像命令容器命令操作命令 docker镜像容器数据卷dockerFiledocker 网络原理IDEA整合dockerdocker composerdocker swarmcI\cd docker概述 痛点&#xff1a;解决跨平台&#xff0c;服…

Docker学习总结

Docker学习总结 一、Docker简介二、Docker安装2.1 安装步骤2.2 卸载Docker2.3 配置阿里云镜像加速 三、Docker常用命令3.1 帮助命令3.2 镜像命令3.3 容器命令3.4 其他常用命令 四、Dockerfile4.1 DockerFile简介4.2 DockerFile体系结构(保留字指令)4.3 案例4.3.1 Base镜像(scra…

Docker学习

理念&#xff1a;一次镜像&#xff0c;处处运行。是基于go语言实现的云开源项目 容器与虚拟机的区别&#xff1a; 虚拟机是一种带环境安装的解决方案&#xff0c;可以在一种操作系统中运行另外一种操作系统。 容器不是模拟一整个操作系统&#xff0c;而是只有软件所需要的库资…

一文带你入门docker

✅作者简介&#xff1a;我是18shou&#xff0c;一名即将秋招的java实习生 &#x1f525;系列专栏&#xff1a;牛客刷题专栏 &#x1f4c3;推荐一款模拟面试、刷题神器&#x1f449; [在线刷题面经模拟面试](在线面试刷题) 目录 安装Docker 卸载旧版本 Docker初装命令 Dock…

超全的Docker学习教程(Linux云计算从入门到精通)

CONTENTS 一、docker简介 1.1 docker相关概念 1.2 docker应用场景 1.3 docker和虚拟机比较 二、初识docker 2.1 安装docker 2.2 初识docker-docker架构 2.3 配置镜像加速器 三、docker命令详解 四、docker容器数据卷 五、docker应用部署 5.1 部署mysql 5.2 部署Tom…

Docker 从入门到精通(新手建议收藏的教程)

今天给大家分享一篇小白也能看懂的Docker入门到精通学习教程&#xff0c;篇幅较长&#xff0c;但内容很干&#xff0c;值得认真看完&#xff01; 目录 一 、容器简介 二、什么是 Docker&#xff1f; 三、安装Docker Docker 从入门到精通&#xff08;新手建议收藏的教程&am…

Docker入门教程(详细)

目录 一、Docker概述 1.1 Docker 为什么出现&#xff1f; 1.2 Dorker历史 1.3 能做什么 虚拟机技术&#xff1a;&#xff08;通过 软件 模拟的具有完整 硬件 系统功能的、运行在一个完全 隔离 环境中的完整 计算机系统&#xff09; 容器化技术&#xff1a;&#xff08;容…

docker入门,这一篇就够了。

Docker入门&#xff0c;这一篇就够了。 Docker容器虚拟化平台。 前言 接触docker很长时间了&#xff0c;但是工作中也没有用到&#xff0c;所以总是学了忘&#xff0c;忘了学。不过这次&#xff0c;我打算跟大家分享一下我的学习历程&#xff0c;也算是我的独特的复习笔记&…

总线板卡(1)——总线接口类型

行业的朋友们是否碰到过这种情况&#xff0c;比如你问某厂家是否有1553B总线或者其他总线板卡时&#xff0c;对方会问你要什么接口的&#xff1f; 你知道厂家说的接口指的是什么吗&#xff1f; 这里的接口一般指板卡的总线接口&#xff0c;比较普遍的有PCI、PCIe、CPCI、PXI等…

6U VPX架构XCKU115(FPGA)+XCZU9EG(MPSOC)+TMS320C6678(DSP)的高速信号处理平台VPX630设计原理图及调试经验分享

板卡概述VPX630 是一款基于6U VPX 总线架构的高速信号处理平台&#xff0c;该平台采用一片Xilinx 的Kintex UltraScale 系列FPGA&#xff08;XCKU115&#xff09;作为主处理器&#xff0c;完成复杂的数据采集、回放以及实时信号处理算法。采用一片带有ARM 内核的高性能嵌入式处…

flexray VPX控制板设计方案详细

后IO板 1设计要求1.1功能要求3U VPX通讯板具有4路CAN&#xff0c;2路 Flex Ray、1路SGMII网口、2路RapidIO2、2路PCIE4、2路IPMI接口 整个处理模块系统框图如下&#xff1a; 图1 系统框图 根据上图&#xff0c;模块可以分为以下几个部分&#xff1a; CAN协议模块&#xff1a…

嵌入式高速串行并行技术_推荐(张锋)

前言 之前想学习一下总线相关的知识&#xff0c;就去图书馆搜&#xff0c;其中&#xff0c;有一本是&#xff1a;《嵌入式高速串行并行技术——基于FPGA实现与应用&#xff08;张锋著&#xff09;》 看了一下前言、目录、自序、以及他本书创作过程中的随笔&#xff08;小编就决…