概述
容器是镜像的运行时实例。正如从虚拟机模板上启动 VM 一样,用户也同样可以从单个镜像上启动一个或多个容器。
虚拟机和容器最大的区别是容器更快并且更轻量级——与虚拟机运行在完整的操作系统之上相比,容器会共享其所在主机的操作系统/内核。
下图为使用单个 Docker 镜像启动多个容器的示意图。
启动容器的简便方式是使用:
docker container run 或者
docker run
该命令可以携带很多参数,在其基础的格式docker container run 中,指定了启动所需的镜像以及要运行的应用。
docker container run -it ubuntu /bin/bash则会启动某个 Ubuntu Linux 容器,并运行 Bash Shell 作为其应用。
如果想启动 PowerShell 并运行一个应用,则可以使用命令docker container run -it microsoft- /powershell:nanoserver pwsh.exe。
容器随着其中运行应用的退出而终止。其中 Linux 容器会在 Bash Shell 退出后终止,而 Windows 容器会在 PowerShell 进程终止后退出。
一个简单的验证方法就是启动新的容器,并运行 sleep 命令休眠 10s。容器会启动,然后运行休眠命令,在 10s 后退出。
如果在 Linux 主机(或者在 Linux 容器模式下的 Windows 主机上)运行docker container run alpine:latest sleep 10命令,Shell 会连接到容器 Shell 10s 的时间,然后退出。
可以使用 docker container stop 命令手动停止容器运行,并且使用 docker container start 再次启动该容器。
如果再也不需要该容器,则使用 docker container rm 命令来删除容器。
容器和虚拟机
容器和虚拟机都依赖于宿主机才能运行。宿主机可以是笔记本,是数据中心的物理服务器,也可以是公有云的某个实例。
在下面的示例中,假设宿主机是一台需要运行 4 个业务应用的物理服务器。
在虚拟机模型中,首先要开启物理机并启动 Hypervisor 引导程序。一旦 Hypervisor 启动,就会占有机器上的全部物理资源,如 CPU、RAM、存储和 NIC。
Hypervisor 接下来就会将这些物理资源划分为虚拟资源,并且看起来与真实物理资源完全一致。
然后 Hypervisor 会将这些资源打包进一个叫作虚拟机(VM)的软件结构当中。这样用户就可以使用这些虚拟机,并在其中安装操作系统和应用。
前面提到需要在物理机上运行 4 个应用,所以在 Hypervisor 之上需要创建 4 个虚拟机并安装 4 个操作系统,然后安装 4 个应用。当操作完成后,结构如下图所示。
而容器模型则略有不同。
服务器启动之后,所选择的操作系统会启动。在 Docker 世界中可以选择 Linux,或者内核支持内核中的容器原语的新版本 Windows。
与虚拟机模型相同,OS 也占用了全部硬件资源。在 OS 层之上,需要安装容器引擎(如 Docker)。
容器引擎可以获取系统资源,比如进程树、文件系统以及网络栈,接着将资源分割为安全的互相隔离的资源结构,称之为容器。
每个容器看起来就像一个真实的操作系统,在其内部可以运行应用。按照前面的假设,需要在物理机上运行 4 个应用。
因此,需要划分出 4 个容器并在每个容器中运行一个应用,如下图所示。
从更高层面上来讲,Hypervisor 是硬件虚拟化(Hardware Virtualization)——Hypervisor 将硬件物理资源划分为虚拟资源。
容器是操作系统虚拟化(OS Virtualization)——容器将系统资源划分为虚拟资源。
容器启动
启动容器的一个简单的方式是通过 docker container run 命令。
docker container run -it -d -p 宿主机端口:docker容器内部端口 --name 容器名称 -v 需要挂载地址(用冒号隔开) iamge:tag
参数解析
-it:以交互模式启动。
-d:daemon 后台模式启动。
-p:指定外部端口并映射内部端口。
–name:给容器起一个名字。
-v:配置挂载,可以将容器中的配置进行挂载。
示例
以启动portainer为例:
[root@localhost docker]# docker container run -d -it -p 9000:9000 -v /root/portainer:/data -v /var/run/docker.sock:/var/run/docker.sock --name dev-portainer portainer/portainer
725b12b7baed6d4f4d7e90f40061285767725bcc1522f8cd1e125da1e788b73c
[root@localhost docker]#
容器生命周期
下面来介绍一下容器的生命周期,从创建、运行、休眠,直至销毁的整个过程。
创建
创建上面已经创建好了
运行
停止
[root@localhost docker]# docker container stop dev-portainer
dev-portainer
[root@localhost docker]#
[root@localhost docker]# docker container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost docker]#
发现容器已经停止运行了。
容器启动
[root@localhost docker]# docker container start dev-portainer
dev-portainer
[root@localhost docker]# docker container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
725b12b7baed portainer/portainer "/portainer" 27 minutes ago Up 4 seconds 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp dev-portainer
[root@localhost docker]#
可以看到容器已经正常启动了。
容器删除
[root@localhost docker]# docker container rm -f dev-portainer
dev-portainer
[root@localhost docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost docker]#
总结一下容器的生命周期。可以根据需要多次停止、启动、暂停以及重启容器,并且这些操作执行得很快。
但是容器及其数据是安全的。直至明确删除容器前,容器都不会丢弃其中的数据。就算容器被删除了,如果将容器数据存储在卷中,数据也会被保留下来。
容器常用命令
docker container xxx可以简写成docker xxx,默认情况下docker 后面跟的就是container的命令。
- docker container run
启动新容器的命令。该命令的最简形式接收镜像和命令作为参数。镜像用于创建容器,而命令则是希望容器运行的应用。
docker container run -it ubuntu /bin/bash 命令会在前台启动一个 Ubuntu 容器,并运行 Bash Shell。 - docker container ls
用于列出所有在运行(UP)状态的容器。如果使用-a标记,还可以看到处于停止(Exited)状态的容器。 - docker container exec
用于在运行状态的容器内部再启动一个新进程。该命令在将Docker主机Shell连接到一个运行中容器终端时非常有用。
docker container exec -it bash
命令会在容器内启动一个Bash Shell进程,并连接到该Shell。
为了使该命令生效,用于创建容器的镜像必须帮Bash Shell。 - docker container stop
docker container stop 可以接收容器 ID 以及容器名称作为参数。
此命令会停止运行中的容器,并将状态置为 Exited(0)。
该命令通过发送 SIGTERM 信号给容器内 PID 为 1 的进程达到目的。
如果进程没有在 10s 之内得到清理并停止运行,那么会接着发送 SIGKILL 信号来强制停止该容器。 - docker container start
重启处于停止(Exited)状态的容器。可以在 docker container start 命令中指定容器的名称或者 ID。 - docker container rm
删除停止运行的容器。可以通过容器名称或者 ID 来指定要删除的容器。推荐首先使用 docker container stop 命令停止容器,然后使用 docker container rm 来完成删除。 - docker container inspect
显示容器的配置细节和运行时信息。该命令接收容器名称和容器 ID 作为主要参数。