1,容器和虚拟机
1.1,容器和虚拟机的区别
虚拟机用于为用户提供一个完整的系统镜像,常见的虚拟机有VMware、VitualBox、KVM等。虚拟化技术可以为每个用户分配虚拟化后的CPU、内存和I/O设备等资源,但是了为了能运行程序,除了需要部署应用程序本身及其依赖,还需要安装整个操作系统和驱动。
容器是一种轻量级、可移植的为应用程序提供了隔离的运行空间。每个容器内都包含一个独享的完整用户环境变动不会影响其他容器的运行环境,可以使应用程序在几乎任何地方以相同的方式运行,比如开发人员在自己的笔记本上创建并测试好的容器,无须任何修改就能在生产环境的虚拟机、物理服务器或公有云主机上运行。在技术方面,容器是通过一系列系统级别的机制来实现,比如通过Linux Namespaces进行行空间隔离;通过文件系统的挂载点来决定容器可以访问哪些文件;通过cgroups来确定每个容器可以利用多少资源;容器之间通过共享同一个系统内核来提升内存使用率。
容器是对应用层的抽象,它把应用程序的代码和相关依赖打包在一起执行,多个容器也在同一台物理机上互不影响地独立运行,并且共享操作系统内核,启动非常快,占用空间非常少,一般也就几十兆。而虚拟机是在物理硬件层上的虚拟化,系统管理程序使虚拟机能够运行在同一台物理机上,但是每台虚拟机必须包括一整套操作系统、应用程序和各种依赖库等,启动非常慢,占用空间GB级别。
1.2,容器主要解决的问题
容器有轻量级、可隔离性和可移植性等特性,所以应用程序的容器化使得应用程序具备了超强的可移植性。
在Web1.0时代,信息是单向的,交互只在人与网络之间进行,大多人上网是为了看新闻,因此应用程序相对简单,一般采用LAMP的三层架构,只需要部署到有限的几台物理服务器上。
在如今的Web2.0,甚至Web3.0时代,互联网连接一切,包括连接人与人、人与物、物与物,系统架构较10年前已经变得非常复杂,开发人员通常使用多种服务构建和组装应用,比如分布式消息队列Kafka、分布式缓存Redies、分布式文件系统HDFS或Spring Cloud等。复杂应用系统的相应部署环境也变得非常复杂,可能会部署到不同的环境中,比如开发服务器、测试服务器和生产服务器,服务器也可能是虚拟服务器、私有云或公有云等。
因为存在各种服务和环境,所以开发人员在编写代码时需要考虑不同的运行环境,运维人员则需要为不同的服务和平台进行各种配置,对于他们来说,这些都是艰巨的任务,容器能很好的帮助我们解决让服务在所有的部署环境中顺利运行。
Docker将集装箱思想运用到软件的打包上,为代码提供了一个基于容器的标准化运输系统,可以将任何应用及其依赖打包成一个轻量级、可移植、自包含的容器,可运行在几乎所有操作系统上。
1.3,Docker的优势
Docker在开发方面的优势:每个人的开发环境都不一样,由于在开发过程中会不断地切换项目工程,所以每次都要不断地重复修改和设置开发环境,而Docker可以使这一过程变得自动化,让开发人员更加关注软件质量。比如,开发人员使用Docker后就不需要单独安装和配置数据库,也不需要担心不同版本的语言冲突问题。容器化的应用更容易构建、分享和运行,如果团队有新的同事加入,则也不用再花几个小时向其讲解如何安装软件和进行配置,该同事只需要花几分钟安装Docker就能编译和调试程序了。
Docker在运维方面的优势:Docker使软件的发布更加高效,不管是更新版本,还是修复Bug,都能很快发布完成,并且能瞬间伸缩扩展。Docker能够实现自动化的编译、打包、测试和部署,运维人员不再需要WiKi、README、CleckList文档,因为Docker在开发、测试和生产环境中都使用了相同的镜像,所以更新时不会出现不一致的问题。
Docker在容器和虚拟机方面的优势:Docker使容器和虚拟机结合,使部署和管理应用变得更加灵活。我们可以在虚拟机中启动一个容器,这里的虚拟机并不是由Docker控制的,而是通过现有的虚拟化管理设施来控制的。一旦系统实例启动,就可以通过安装Docker来运行容器并进行其他特殊设置。同时,由于不同的容器运行在不同的虚拟机上容器之间也能有很好的隔离。
1.4,Docker的架构
Docker引擎主要包括三大组件:
- Docker后台服务:是长时间运行在后台的守护进程,是Docker的核心服务,可以通过命令dockerd与它交互。
- REST接口:程序可以通过REST的接口来访问后台服务。
- 交互式命令界面:我们大多数时间都在使用命令行界面与Docker进行交互,例如以docker为开头的所有命令的操作。而命令行界面又是通过调用REST的接口来控制和从操作Docker后台服务。
Docker是C/S结构的架构,客户端通过与后台服务交互,来编译、运行和发布容器。Docker的客户端可以连接到本主机的Docker服务上,也可以连接到远程的Docker服务上。Docker客户端是使用REST接口来与后台服务通信的,它通过使用UNIX Socket连接或者网络接口实现。
(1)Docker后台服务监听REST接口的请求,管理Docker的对象,比如Docker的镜像、容器、网络和磁盘卷。一个Docker后台服务可以和其他Docker后台服务进行通信,从而对他们进行管理。
(2)Docker客户端是我们和Docker后台服务交互的主要工具,在使用docker run命令时,客户端把命令发送到Docker后台服务,再由后台服务执行该命令。Docker客户端可以连接多个后台服务并与它们通信。
(3)Docker仓库是用来存储Docker镜像的,Docker Hub和Docker Cloud是所有人都能够使用的公共的Docker仓库。Docker默认从Docker Hub下载镜像,当然我们也可以自己搭建私有仓库。当我们使用Docker pull或docker run命令时,就会从我们配置的docker仓库下载镜像,当使用docker push命令时,我们的镜像就会被推送到Docker仓库中。
(4)Docker对象包括:镜像、容器、网络、磁盘卷和插件等。我们在使用Docker时就会创建和使用Docker对象。
- 镜像是只读的指令板,用于创建Docker容器。通常一个镜像会继承另一个镜像,然后扩展自定义的指令,比如,我们可以创建一个继承自Ubuntu的镜像,再安装一个Apache Tomcat服务和自己的应用程序,同时修改些配置使我们的程序能运行起来。为了创建自己的镜像,我们可以创建一个Dockerfile文件,通过一些简单的指令来定义如何创建和运行镜像,Dockerfile中的每个指令在镜像中都会创建为一个层,当我们修改Dockerfile文件然后重新编译它时,仅有那些被修改的层才会被重新编译,这就是Docker镜像是轻量级的、体积非常小、速度非常快的原因。
- 容器是镜像运行的一个实例,我们可以使用Docker的API或CLI来创建、运行、停止、移动或者删除容器。我们可以为容器绑定一个或多个网络或挂载一个磁盘卷,也可以通过继承它来创建一个新的镜像。通常一个容器与另一个容器或者它的宿主机都是相对独立和隔离的。在容器停止运行后,它其中的所有改变的状态如果没有保存,则都将会消失。
- Docker服务允许我们在多个Docker后台服务中伸缩扩展容器,这些容器组成了一个拥有多主多从模式的集群。集群中的每一个成员都是一个Docker后台服务,它们之间通过Docker接口通信。它们可以通过Docker服务来定义集群的参数,比如集群中容器的副本个数。在默认情况下,集群的负载是面向所有容器节点的。而对于使用者来说,Docker集群就像一个大实例。
(5)命名空间,Docker使用命名空间为容器提供了良好的隔离性,当我们运行容器时,Docker会为容器创建一组命名空间,每个容器都是一个独立的命名空间,容器仅仅限制与在自己的命名空间中访问权限。Docker使用了Linux的如下命名空间:
- pid命名空间:用来隔离进程的ID空间,使得不同pid命名空间里的进程ID可以重复且相互之间不受影响。
- net命名空间:用于管理网络协议栈的多个实例。
- ipc命名空间:用于管理和访问IPC资源。
- mnt命名空间:用于管理文件系统的挂载点。
- uts命名空间:用于隔离内核和版本信息。
(6)cgoups,Docker采用一种被称为cgroups的技术,实现了不同应用之间的隔离性,让每个应用只能访问属于的资源。cgroups可以确保Docker将可用的硬件资源共享给所有容器,并且可以对容器限制硬件资源,列如可以限制每个容器访问的内存大小。
(7)UnionFS,是Docker在创建层时采用的文件系统。这种文件系统使Docker变得很轻量级并且执行速度很快。Docker可以使用多种类型的UnionFS,比如:AUFS、btrfs、vfs和DeviceMapper。
(8)容器格式,Docker将namespaces、control groups和UnionFS封装成container format,我们将其称为容器。默认的容器类型是libcontainer。在未来,Docker也将支持其他类型的容器,比如BSD Jails或者Solaris Zones。
1.5,Docker的安装
Docker分为两个版本:社区版和企业版。社区版主要提供给开发者或小团队学习和练习,而企业版主要提供给企业级开发和运维团队用于对线上产品的编译、打包和运行,有很高的安全性和扩展性,用户可以申请一个月的免费使用期限。Docker的社区版和企业版都支持Linux、Cloud、Windows和MacOS平台。
2,Docker镜像命令
2.1,Docker简单命令
安装检验:
docker run hello-world
查看Docker版本
docker --version docker version
查看本地镜像:
docker images
查看运行的容器:
docker ps
启动简单的Web服务:以后台模式在80端口启动Nginx容器。
docker run -d -p 80:80 --name webserver nginx
2.2,镜像:查看,搜索,拉取,删除
查看本地镜像
docker iamges [OPTIONS] [REPOSITORY[:TAG]]
参数名及其缩写 默认值 描述 --all, -a false 列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层) --digests false 显示镜像的摘要信息 --filter, -f 显示满足条件的镜像 --format 通过GO语言模板文件展示镜像 --no-trunc false 不截断输出,显示完整的镜像信息 --quiet, -q false 只显示镜像ID (1)列出本地镜像,同 docker image ls:
docker images
(2)通过name列出本地镜像:
docker images java
(3)通过name和tag列出本地镜像:
docker images java:8
- REPOSITORY:镜像所属仓库名称。
- TAG:镜像标签。默认是latest,表示最新。
- IMAGE ID:镜像ID,表示镜像唯一标识。
- CREATED:镜像创建时间。
- SIZE:镜像大小。
搜索镜像:可使用docker search命令搜索存放在Docker Hub中的镜像。
docker search [OPTIONS] docker-name
参数名及其缩写 默认值 描述 --automated false 【废弃】只列出自动构建的镜像 --filter, -f 根据指定条件过滤结果 --limit 25 搜索结果的最大条数 --no-trunc false 不截断输出,显示完整的输出 --stars, -s 0 【废弃】只展示Star不低于该数值的结果
- NAME:镜像仓库名称。
- DESCRIPTION:镜像仓库描述。
- STARS:镜像仓库收藏数,表示该镜像仓库的受欢迎程度,类似于GitHub的Stars。
- OFFICAL:表示是否为官方仓库,该列标记为[OK]的镜像均由各软件的官方项目组创建和维护。
- AUTOMATED:表示是否是自动构建的镜像仓库。
拉取镜像
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
参数名及其缩写 默认值 描述 --all-tags, -a false 在仓库中下载所有指定标记(tagged)的镜像 --disable-content-trust true 跳过镜像的校验 (1)docker pull 命令默认从 Docker Hub仓库中拉去镜像,实际上相当于命令:
docker pull registry.hub.docker.com/williamyeh/java8:latest
即从注册服务器 registry.hub.docker.com 中的 williamyeh/java8 仓库来下载标记为 lastest(最新的)的镜像。如果要从私有镜像仓库拉去镜像,则只要填上自己的仓库地址即可,例如命令:docker pull myregistry.com/williamyeh/java8:lastest。
删除本地镜像
docker rmi [OPTIONS] IMAGE [IMAGE...]
参数名及其缩写 默认值 描述 --force, -f false 强制删除 --no-prune false 不移除该镜像的过程镜像,默认移除 (1)删除 hello-world 镜像:
docker rmi -f hello-world
(2)删除所有未被容器使用的镜像:
docker image prune -a
(3)删除所有停止运行的容器:
docker container prune
(4)删除所有未被 tag 标记和未被容器使用的镜像:
docker image prune
(5)删除 docker 所有资源:
docker system prune
2.3,镜像:保存,加载,构建
保存镜像
docker save [OPTIONS] IMAGE [IMAGE...]
参数名及其缩写 默认值 描述 --output, -o 输出到文件而非标准输出
加载镜像
docker load [OPTIONS]
参数名及其缩写 默认值 描述 --input, -i 从文件加载而非标准输入 --quit, -q false 静默加载
构建镜像
docker build [OPTIONS] PATH | URL | -
参数名及其缩写 默认值 描述 --build-arg 设置镜像创建时的变量 --disable-content-trust true 忽略校验,默认开启 -f 指定要使用的Dockerfile路径 --force-rm 设置镜像过程中删除中间容器 --isolation 使用容器隔离技术 --rm 设置镜像成功后删除中间容器 (1)使用当前目录的 Dockerfile 创建镜像,标签为 runoob/ubuntu:v1
docker build -t runoob/ubuntu:v1 .
(2)使用URL github.com/creack/docker-firefox 的 Dockerfile 创建镜像
docker build github.com/creack/docker-firefox
3,Docker容器命令
3.1,容器:运行,查看,停止,重启
运行容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
参数名及其缩写 默认值 描述 --add-host 添加自定义的host到IP映射(host:ip) --attach, -a 关联到标准输入文件(STDIN)、标准输出文件(STDOUT)或标准出错文件(STDERR) --cpus 设置CPU的个数 --detach, -d false 在后台运行容器并打印容器ID --env, -e 设置环境变量 --env-file 从文件中读取环境变量设置 --expose 暴露一个或多个端口 --help false 打印帮助 --hostname, -h 容器的host name -ip IPv4地址 --kernel-memory 0 内核内存限制 --label, -l 设置容器的元数据 --link 添加连接到另一个容器 --mount 关联文件系统并挂载到容器中 --name 为容器指定一个名称 --net default 为容器设置一个网络连接 --restart no 为一个存在的容器设置重启策略 --rm false 在容器退出后自动移除容器 --ulimit Ulimit选项 --volume, -v 挂载一个磁盘卷 --workdir, -w 在容器内的工作目录 --tty, -t false 分配一个伪终端 --publish, -p 映射一个容器中的端口到主机端口 --publish-all, -P false 所有暴露的端口随机映射到主机端口 --privileged false 为容器添加扩展的特性 (1)运行nginx
doker run -d -p 91:80 nginx
这样就可启动一个Nginx容器。访问https://Docker宿主机IP:91/,会看到Nginx启动界面。需要注意的是,使用docker run命令创建容器时,会先检查本地是否存在指定镜像。如果本地不存在该名称的镜像,Docker会自动从Docker Hub下载镜像并启动一个Docker容器。
查看容器
docker ps [OPTIONS]
参数名及其缩写 默认值 描述 --all, -a false 显示所有的容器,包括未运行的 --filter, -f 根据条件过滤显示的内容 --format 指定返回值的模板文件 --last, -n -1 列出最近创建的n个容器 --latest, -l false 显示最近创建的容器 --no-trunc false 不截断输出 --quiet, -q false 静默模式,只展示容器的ID --size, -s false 显示总文件大小
- CONTAINER_ID:表示容器ID。
- IMAGE:表示镜像名称。
- COMMAND:表示启动容器时运行的命令。
- CREATED:表示容器的创建时间。
- STATUS:表示容器运行的状态。Up表示运行中,Exited表示已停止。
- PORTS:表示容器对外的端口号。
- NAMES:表示容器名称。该名称默认由Docker自动生成,也可使用docker run命令的–name选项自行指定。
停止容器
docker stop [OPTION] CONTAINER [CONAINER...]
参数名及其缩写 默认值 描述 --time, -t 10 强制停止容器前等待的时间,单位是s 强制停止容器
docker kill [OPTIONS] CONTAINER [CONTAINER...]
参数名及其缩写 默认值 描述 --signal, -s KILL 向容器发送一个信号
启动已停止的容器:使用docker run命令即可新建并启动一个容器。对于已停止的容器,可使用docker start命令来启动。
docker start [OPTIONS] CONTAINER [CONTAINER...]
参数名及其缩写 默认值 描述 --attach, -a false 连接STDOUT/STDERR并转发信号 --checkpoint 从该检查点还原 --checkpoint-dir 使用自定义的检查点存储目录 --detach-keys 覆盖断开容器的关键顺序 --interactive, -i false 连接容器的STDIN 重启容器:该命令实际上是先执行了docker stop命令,然后执行了docker start命令。
docker restart [OPTIONS] CONTAINER [CONTAINER...]
参数名及其缩写 默认值 描述 --time, -t 10 关闭容器前等待的时间,单位s
3.2,容器:删除,导出,导入
删除容器
docker rm [OPTIONS] CONTAINER [CONTAINER...]
参数名及其缩写 默认值 描述 --force, -f false 通过SIGKILL信号强制删除正在运行中的容器 --link, -l false 删除容器间的网络连接 --voumes, -v false 删除与容器关联的卷 (1)删除指定容器
docker rm 784fd3b294d7
(2)删除所有容器
docker rm -f $(docker ps -a -q)
导出容器:使用docker export命令可将容器导出成一个压缩包文件。
docker export [OPTIONS] CONTAINER
参数名及其缩写 默认值 描述 --output, -o 将内容写到文件而非标准输出 docker export -o mysql-`date +%Y%m%d`.tar a404c6c174a2 ls mysql-`date +%Y%m%d`.tar mysql-20160711.tar
导入容器:使用docker import命令即可从归档文件导入内容并创建镜像。
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
参数名及其缩写 默认值 描述 --change, -c 将Dockerfile指令应用到创建的镜像 --message -m 为导入的镜像设置提交信息 docker import nginx2.tar nginx