Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
Docker是PaaS提供商dotCloud开源的一个基于LXC的高级容器引擎,源代码托管在Github上,它基于Google公司推出的go语言并遵从Apache2.0协议开源。
Docker自2013年以来非常火热,无论是从github上的代码活跃度,还是Redhat在RHEL6.5中集成对Docker的支持,就连Google的Compute Engine也支持docker在其之上运行。
Docker项目的目标是实现轻量级的操作系统虚拟化解决方案。Docker的基础是Linux容器(LXC)等技术。(背景)云计算兴起后,服务器硬件扩展非常便利,软件服务部署成为了瓶颈,docker趁势而兴。
容器的启动可以在秒级实现,比传统的虚拟机方式要快得多。
对系统资源的利用率很高,一台主机上可以同时运行数千个Docker容器。
docker的出现,让开发/测试/线上的环境部署,成为便利一条龙。
对开发和运维(devop)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。Docker可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。Docker容器很轻很快,容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。
Docker容器的运行不需要额外的hypervisor支持,它是内核级的虚拟化,因此可以实现更高的性能和效率。
Docker容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
使用Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。
特性 |
容器 |
虚拟机 |
启动 |
秒级 |
分钟级 |
硬盘使用 |
一般为 MB |
一般为 GB |
性能 |
接近原生 |
弱于 |
系统支持量 |
单机支持上千个容器 |
一般几十个 |
Docker使用C/S结构,即客户端/服务器体系结构。 Docker客户端与Docker服务器进行交互,Docker服务端负责构建、运行和分发Docker镜像。Docker客户端和服务端可以运行在一台机器上,也可以通过RESTful、stock或网络接口与远程Docker服务端进行通信。
Host就是主机载体,也就是docker安装的位置。就好比java类的继承关系一样:image2 extents image1 然后Container c = new image2此时c容器中,有image1的文件。
Docker镜像就是一个只读的模板。Docker镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
镜像(Image)就是一堆只读层(read-only layer)的统一视角,也许这个定义有些难以理解,下面的这张图能够帮助读者理解镜像的定义。
从左边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker 内部的实现细节,并且能够在主机的文件系统上访问到。统一文件系统 (union file system) 技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。我们可以在图片的右边看到这个视角的形式。
例如:一个镜像可以包含一个完整的ubuntu操作系统环境,里面仅安装了Apache或用户需要的其它应用程序。
镜像可以用来创建Docker容器。Docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。
Docker利用容器来运行应用。容器(container)的定义和镜像(image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。由于容器的定义并没有提及是否要运行容器,所以实际上,容器=镜像+读写层。
容器是从镜像创建的运行实例,它可以被启动、开始、停止、删除;每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为:公开仓库Public和私有仓库Private两种形式。
最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括 Docker Pool 等,可以提供大陆用户更稳定快速的访问。当然,用户也可以在本地网络内创建一个私有仓库。
当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。
Docker支持CentOS6及以后的版本。
对于CentOS6,可以使用 EPEL 库安装Docker,命令如下:
$ sudo yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm
$ sudo yum install docker-io
CentOS7系统 CentOS-Extras 库中已带Docker,可以直接安装:
yum install docker ##默认安装的不是最新版本
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce
docker version
docker info
service docker start
chkconfig docker on
docker run hello-world ##进入docker世界
1)查询安装过的包
yum list installed | grep docker
docker-engine.x86_64 17.03.0.ce-1.el7.centos @dockerrepo
2)删除安装的软件包
yum -y remove docker-engine.x86_64
3)删除镜像/容器等
rm -rf /var/lib/docker
vim /etc/docker/daemon.json
添加国内镜像地址:
{ "registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com"] }
重启docker daemon:
systemctl daemon-reload
systemctl restart docker
1)关闭selinux,可以通过命令getenforce查看状态,不关闭会导致很多软件不兼容
2)docker为什么安装那么快,是因为docker-ce.repo文件添加了系统缓存中
可以通过命令:
yum clean all && yum makecache fast # 来添加
1)run/create[镜像名]:创建一个新的容器并运行一个命令
例如:创建centos镜像
docker run -it --name cent centos:latest /bin/bash
docker run -it --name cent2 centos:latest /bin/bash
2)start/stop/restart[容器名]:启动/停止/重启一个容器
docker stop cent
docker start cent
docker restart cent
3)kill [容器名]: 直接杀掉容器,不给进程响应时间
查看已安装的镜像:docker ps
例如:docker kill cent2
4)rm[容器名]:删除已经停止的容器
5)pause/unpause[容器名]:暂停/恢复容器中的进程
例如:docker pause cent2
1)ps:查看容器列表(默认查看正在运行的容器,-a查看所有容器)
2)inspect[容器名]:查看容器配置元数据
3)exec -it [容器名] /bin/bash:进入容器环境中交互操作
命令:docker exec -it cent /bin/bash
4)logs --since="2019-12-06" -f --tail=10 [容器名]:查看容器日志
命令:docker logs --since="2019-12-06" -f --tail=10
5)cp path1 [容器名]:path 容器与主机之间的数据拷贝
6)export -o test.tar [容器名] / docker export [容器名]>test.tar : 文件系统作为一个tar归档文件
7)import test.tar [镜像名:版本号]:导入归档文件,成为一个镜像
docker images|rmi|tag|build|history|save|load]
1)images:列出本地镜像列表
命令:docker images
2)rmi [镜像名:版本]:删除镜像
3)tag [镜像名:版本] [仓库]/[镜像名:版本]:标记本地镜像,将其归入某一仓库
4)build -t [镜像名:版本] [path]:Dockerfile 创建镜像
5)history [镜像名:版本]: 查看指定镜像的创建历史
命令:docker history centos
6)save -o xxx.tar [镜像名:版本] / save [镜像名:版本]>xxx.tar : 将镜像保存成 tar 归档文件
7)load --input xx.tar / docker load 示例: 创建Tomcat容器:-p绑定镜像端口与宿主机的端口 docker run -d --name tomcat -p 8080:8080 tomcat 容器转镜像命令: docker commit -a “hankin” -m “mvc” tomcat tomcat:mvc 例:docker history hello-world 显示镜像hello-world分三层,其中两个空层 镜像存放在imagedb里,一般在image/overlay2/imagedb/content/sha256下: ll /var/lib/docker/image/overlay2/imagedb/content/sha256/ 注意:前12位即为镜像的ID 打开一个镜像文件查看其内容: 其中,history数组内,标识了镜像的历史记录(与history命令内容对应) rootfs的diff_ids中,对应了依赖使用中镜像层文件(history命令中size大于0的层) 层文件在layerdb里: 命令:ll /var/lib/docker/image/overlay2/layerdb/sha256 镜像层文件内结构:size占用大小,tar-split.json.gz镜像层文件包 一个镜像就是一层层的layer层文件,盖楼而成,上层文件叠于下层文件上,若上层文件有与下层文件重复的,则覆盖掉下层文件重复的部分,如下图: 初始挂载时读写层为空。 当需要修改镜像内的某个文件时,只对处于最上方的读写层进行了变动,不复写下层已有文件系统的内容,已有文件在只读层中的原始版本仍然存在,但会被读写层中的新版本文件所隐藏,当docker commit这个修改过的容器文件系统为一个新的镜像时,保存的内容仅为最上层读写文件系统中被更新过的文件。 联合挂载是用于将多个镜像层的文件系统挂载到一个挂载点来实现一个统一文件系统视图的途径,是下层存储驱动(aufs、overlay等) 实现分层合并的方式。 这个过程就好比发射火箭,kernel就像是火箭的助推器(启动引导程序),当火箭点火成功一段时间后就会抛掉助推器进入下一个阶段,这里kernel引动启动成功就会自动脱落删除。 执行命令: docker run -it --name cent centos:latest /bin/bash docker run -it --name centos centos /bin/bash(前台进程) exit退出也关闭容器 Ctrl+P+Q退出不关闭容器 docker stop cent docker run -dti --name cent2 centos // d:后台运行,it交互shell进程 -dti的作用就是保持一个前台进程,容器就不会退出,就相当于java的main方法执行完以后,对应的java进程结束,前台进程结束,容器也就结束了。 例如:docker run -d --name nginx nginx docker exec -it cent2/bin/bash [root@localhost local]# docker exec -it cent /bin/bash [root@bcf1eaa28805 /]# 查看容器的元数据:docker inspect cent2 docker run -d -p 8080:80 --name nginx nginx:latest docker run -dit -v /root/hankin_dir/:/pdir --name cent centos docker cp anaconda-ks.cfg cent:/var
3、镜像与容器原理及用法探究
3.1、history命令查看镜像层
3.2、查看镜像文件
cat 0f3e07c0138fbe05abcb7a9cc7d63d9bd4c980c3f61fea5efa32e7c4217ef4da
{
"architecture": "amd64",
"config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
"Cmd": ["/bin/bash"],
"ArgsEscaped": true,
"Image": "sha256:c0bda62fdbad65a3c6a1843d293a3a47d8233115cc6d384e3cb07c53580a2b43",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20190927",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"container": "711572e3c0c1ac06d5c13c4e668ec170b8ad8786b5f0949f884a5f7fd350d856",
"container_config": {
"Hostname": "711572e3c0c1",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
"Cmd": ["/bin/sh", "-c", "#(nop) ", "CMD [\"/bin/bash\"]"],
"ArgsEscaped": true,
"Image": "sha256:c0bda62fdbad65a3c6a1843d293a3a47d8233115cc6d384e3cb07c53580a2b43",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20190927",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"created": "2019-10-01T23:19:57.105928163Z",
"docker_version": "18.06.1-ce",
"history": [{
"created": "2019-10-01T23:19:56.428311529Z",
"created_by": "/bin/sh -c #(nop) ADD file:d6fdacc1972df524a795bd36cf75dd355faefbe9a69d88d1fff95599e2eeed4c in / "
}, {
"created": "2019-10-01T23:19:56.938655663Z",
"created_by": "/bin/sh -c #(nop) LABEL org.label-schema.schema-version=1.0 org.label-schema.name=CentOS Base Image org.label-schema.vendor=CentOS org.label-schema.license=GPLv2 org.label-schema.build-date=20190927",
"empty_layer": true
}, {
"created": "2019-10-01T23:19:57.105928163Z",
"created_by": "/bin/sh -c #(nop) CMD [\"/bin/bash\"]",
"empty_layer": true
}],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": ["sha256:9e607bb861a7d58bece26dd2c02874beedd6a097c1b6eca5255d5eb0d2236983"]
}
}
3.3、查看镜像层文件
3.4、镜像与容器总结
4、容器创建详解
4.1、交互式创建容器并进入:
4.2、后台启动容器:
4.3、进入已运行的容器:
4.4、绑定容器端口到主机:
4.5、挂载主机文件目录到容器内:
4.6、复制主机文件到容器内: