Docker教程(一)- 运行Docker镜像、容器隔离
- 运行你的第一个容器
- Docker 镜像
- 运行 Docker 容器
- 容器隔离
通过这个教程,你会运行一个
容器
,了解这个
容器
是怎样工作的,并理解
Docker Engine
是怎样执行以及怎样隔离每个不同的容器。
这个教程包含以下基本概念:
- Docker 引擎
- 容器和镜像
- Image Registries 和 Docker 商店(即 Docker Hub)
- 容器隔离
运行你的第一个容器
首先,程序员的最爱:“Hello, world”。运行以下指令:
docker container run hello-world
你会得到:
注意:如果第一次执行上面的命令的时候,提示“Unable to find image
locally”的话,是正常的,不要方,再执行一次就好了(重现不了,这里就不放图了)。
在你输入上面的指令的时候,首先Docker会尝试在你的本地仓库寻找一个叫hello-world
的镜像,因为你之前并没有下载过这个镜像,所以Docker在本地找不到,然后Docker就会去到默认的Docker Registry
(即http://store.docker.com)去寻找。找到以后,pull下来,并新建一个容器来运行这个hello-world
镜像(latest
指的是镜像的版本号tag,如果不指定,默认就是latest
)。
Docker 镜像
现在开始我们需要运行一个 Alpine Linux
的容器(Alpine Linux
是一个轻量的 Linux 发行版)。首先,执行以下命令以下载镜像:
sudo docker image pull alpine
Pull 完之后,检查一下本地仓库看是否已经下载成功:
sudo docker image ls
运行 Docker 容器
镜像下载成功后,开始运行这个容器:
sudo docker container run alpine ls -l
这行命令的意思是,以 alpine
这个镜像,新建并运行一个容器,并在这个容器中,执行 ls -l
这个命令。
现在尝试一下再执行以下命令:
sudo docker container run alpine echo "hello from alpine"
这个命令非常简单,这里就不作解释了。值得关注的是,执行完这个命令后,检查一下当前我们创建了哪些容器:
sudo docker container ls -a
记得要加 -a
选项,否则已经关闭了的容器是不会显示的。
如图可知,我们刚才执行 ls
和执行 echo
是分别创建了两个不同的容器的,而不是新建一个容器,并在这个容器里面执行两条命令。
在这个过程中,你会感受到对比起虚拟机,Docker的运行速度要快得多。这是因为Docker省略了许多虚拟机必须要执行的步骤,例如仿真硬件栈、启动操作系统等。
OK,刚才的例子,我们尝试了新建一个apline
容器,然后执行一行命令。根据上面那种做法,这个容器在执行完这个命令之后就会退出,那我能不能让它持续接收并执行我的命令呢?也许你会想到我们可以执行一个sh
:
sudo docker container run alpine /bin/sh
执行完这行命令后,你会发现什么都没有发生,这是因为当容器执行完/bin/sh
这个命令后,便直接关闭了,并没有给你与它交互的机会。正确的做法是加上 -i
和 -t
两个选项。
sudo docker container run -it alpine /bin/sh
现在你就能看见我们进入了容器的交互模式,并可以不断向容器发送指令。上面指令的-i
表示保持标准输入刘(stdin)对容器开放,-t
表示为容器分配一个虚拟的tty。
现在,不要关闭这个终端,新建另外一个终端,执行下面的命令:
sudo docker container ls -a
你会发现,这里有两个执行/bin/sh
命令的容器,其中一个的状态是Exited
,这个是上面我们没有加-i
和 -t
两个选项时创建的容器。而加-i
和 -t
两个选项所创建的容器,现在还在另外一个终端运行着,所以这个容器的状态是UP
。
容器隔离
如上面所说,尽管两个容器都是使用alpine
来创建的,但是这两个容器是相互独立的,意味着它们拥有不同的文件系统,而且运行在不同的命名空间。默认地,容器之间是不能进行交互的。
先不要关闭上面那个交互式的容器,现在尝试再开一个终端,再次输入下面的命令,再新建一个交互式的容器,然后新建一个文件:
sudo docker container run -it alpine /bin/sh
OK, 现在我们看一下这两个容器的根目录,
两个容器的根目录是一致的,因为他们都是刚用alpine
镜像新建的容器,并未作出任何修改。现在,在其中一个容器的根目录下,新建一个文件叫hello.txt
touch hello.txt
然后在看一下这两个容器根目录下的文件
可见,hello.txt
只存在于执行新建文件指令的那个容器(即下图中的左二的那个alpine
容器),并不会影响使用相同镜像所创建的其他容器。