图片是活动容器的不可变快照。容器是某个镜像的运行(或停止)实例。
从名为“ubuntu”的基础镜像开始。让我们在 ubuntu 镜像中交互式地运行 bash 并创建一个文件。我们将使用 -i
和 -t
标志来给我们一个交互式的 bash shell。
$ docker run -i -t ubuntu /bin/bash
root@48cff2e9be75:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@48cff2e9be75:/# cat > foo
This is a really important file!!!!
root@48cff2e9be75:/# exit
退出并重新启动镜像时,请不要指望文件会保留下来。你重新开始的状态与之前一样,而不是从你离开的地方继续。
$ docker run -i -t ubuntu /bin/bash
root@abf181be4379:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@abf181be4379:/# exit
但是,容器现在不再运行,但它有状态并且可以保存(提交)到镜像中。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abf181be4379 ubuntu:14.04 /bin/bash 17 seconds ago Exited (0) 12 seconds ago elegant_ardinghelli
48cff2e9be75 ubuntu:14.04 /bin/bash About a minute ago Exited (0) 50 seconds ago determined_pare
...
$ docker commit 48cff2e9be75 ubuntu-foo
d0e4ae9a911d0243e95556e229c8e0873b623eeed4c7816268db090dfdd149c2
$ docker run ubuntu-foo /bin/cat foo
This is a really important file!!!!
docker images
。您应该能够看到新的ubuntu-foo
镜像以及我们开始使用的标准ubuntu
镜像。镜像是一组有序的根文件系统更改和相应的执行参数,用于在容器运行时使用。镜像是只读的。
容器是镜像的一个活动(或非活动,如果已退出)的有状态实例化。
Create a Dockerfile with the following contents:
FROM httpd:2.4
Install Apache server
sudo docker build -t my-apache2 .
Run the image
sudo docker run -it --rm --name my-running-app my-apache2
List Docker images
sudo docker images
List the running Docker containers
docker ps
List all containers
docker ps -a
List latest created containers
docker ps -l
一张镜像基本上是一个不可变的模板,用于创建容器。通过考虑将镜像转换为容器时发生的情况,更容易理解镜像和容器之间的区别。
Docker引擎将在镜像顶部添加一个读写文件系统,然后初始化各种设置。这些设置包括网络选项(IP、端口等)、名称、ID以及任何资源限制(CPU、内存)。如果Docker引擎被要求运行容器,它还会在其中初始化一个进程。容器可以停止和重新启动,在这种情况下,它将保留所有设置和文件系统更改(但将失去内存中的任何内容,并且所有进程将重新启动)。因此,停止或退出的容器与镜像不同。
DockerFile --(构建)--> Docker镜像 --(运行)--> Docker容器
DockerFile 是您或开发人员编写的用于执行某些操作(例如,安装软件)的代码。
Docker镜像 是您构建DockerFile时获取的内容。
Docker容器 是您运行Docker镜像时获取的内容。
我们可以通过拉取Docker Hub上的镜像来获得Docker镜像,然后运行它以获取容器。
Images:用于运行容器的文件系统和元数据。可以将其视为包含运行应用程序所需的所有依赖项和执行该应用程序的默认设置的应用程序打包格式。元数据包括运行命令的默认值、环境变量、标签和健康检查命令。
Containers:隔离应用程序的实例。容器需要镜像来定义其初始状态,并使用来自镜像的只读文件系统以及容器特定的读写文件系统。正在运行的容器是一个围绕运行进程的封装,为该进程提供文件系统、网络和PID等名称空间。
当您执行docker run
命令时,在命令行上提供一个镜像以及任何配置,Docker会根据该镜像定义和提供的配置返回一个容器。
References:对于Docker引擎来说,镜像只是一个图像ID。这是一个唯一的不可变哈希。对图像进行更改会导致创建新的图像ID。但是,您可以有一个或多个引用指向一个图像ID,类似于符号链接。这些引用可以更新以指向新的图像ID。请注意,当您创建一个容器时,Docker将在容器创建时解析该引用,因此您无法更新正在运行的容器的图像。相反,您需要创建一个新的镜像,并基于该新镜像创建一个新的容器。
Layers:更深入地了解一下,您有文件系统层。Docker使用分层文件系统组装镜像。每个层都是对文件系统的只读更改集,并且该层由唯一的哈希表示。使用这些只读层,多个图像可以扩展另一个图像,只需存储或通过网络传输这些图像之间的差异即可。当运行Docker容器时,它会接收一个特定于容器的读写文件系统层,该层对于该容器是唯一的,并且所有图像层都与该容器使用联合文件系统组装。读取通过每个层进行处理,直到找到文件、找到删除或在底层未找到文件为止。写入将从镜像只读层复制到特定于容器的读写层。删除将记录为对特定于容器的读写层的更改。构建镜像的常见步骤是在基于先前镜像文件系统状态的临时容器中运行命令,并将生成的容器特定层保存为新镜像中的层。
docker images
命令查看已安装的镜像以及docker ps
命令查看正在运行的镜像。当你输入docker run
命令时,它会使用镜像并创建一个带有运行进程的容器。我倾向于使用以下命令:
最后,镜像有自己的ID集合,容器也有自己的ID集合 - 它们不重叠。docker run -ti
<image>:<tag>
bash
容器是基于镜像的。在Docker运行命令中需要传递一个镜像。
例如:
BusyBox 镜像
http://i.stack.imgur.com/eK9dC.png
这里我们指定了一个名为 busybox
的镜像。Docker本地没有这个镜像,会从公共注册表中拉取。
注册表是Docker镜像目录,Docker客户端可以与之通信并从其中下载镜像。一旦镜像被拉取,Docker就会启动一个容器并执行echo hello world命令。
官方的区别在于容器是最后一个可写层,而下面的层只能读取,它们属于您的图像。直观的区别在于,Docker实例是由您的Docker守护程序虚拟化的实例,并且运行您的图像,在您的内核的隔离部分中操作(此过程对您隐藏)。然而,图像是静态的,不会运行,它只是一堆层(静态文件)。如果我们将这种范式与面向对象编程联系起来,图像就是您的类定义,而Docker实例则是驻留在内存中的类生成对象。
我编写了一篇教程来加强您的Docker知识直觉:
http://javagoogleappspot.blogspot.com/2018/07/docker-basics.html
docker exec -t -i 48cff2e9be75 /bin/bash
命令可以回到容器中。 - Faccion