Docker 简介
Docker介绍
什么是docker
Docker
最初是 dotCloud
公司创始人 Solomon Hykes
在法国期间发起的一个公司内部项目,它是基于 dotCloud
公司多年云服务技术的一次革新。 在 2013 年底,dotCloud
公司决定改名为 Docker。Docker
最初是在 Ubuntu 12.04
上开发实现的;Red Hat
则从 RHEL 6.5
开始对 Docker
进行支持;Google
也在其 PaaS
产品中广泛应用 Docker
。
原理
Docker
使用 Google
公司推出的 Go 语言
进行开发实现,基于 Linux 内核的 cgroup
,namespace
,以及 OverlayFS
类的 Union FS
等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术
。由于 隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器
。它可以独立运行多种进程、多个应用,更加充分地发挥基础设施的作用,同时保持各个独立系统的安全性。最初实现是基于 LXC
,从 0.7 版本以后开始去除 LXC
,转而使用自行开发的 libcontainer
,从 1.11 版本开始,则进一步演进为使用 runC
和 containerd
。
架构
runc
是一个 Linux 命令行工具,用于根据 OCI容器运行时规范 创建和运行容器。containerd
是一个守护程序,它管理容器生命周期,提供了在一个节点上执行容器和管理镜像的最小功能集。
Docker
在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker
技术比虚拟机技术更为轻便、快捷
Docker 和传统虚拟化方式的不同之处
-
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程
-
容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
- 传统虚拟化
- Docker
- 传统虚拟化
总而言之: Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化
docker的好处
作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势
-
更高效的利用系统资源
由于
容器不需要进行硬件虚拟以及运行完整操作系统
等额外开销,Docker
对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用
。 -
更快速的启动时间
传统的虚拟机技术启动应用服务往往需要
数分钟
,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级
的启动时间。大大的节约了开发、测试、部署的时间。 -
一致的运行环境
开发过程中一个常见的问题是
环境一致性问题
。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境
,确保了应用运行环境一致性,从而不会再出现 这段代码在我机器上没问题啊🤣 这类问题。 -
持续交付和部署
对
开发和运维(DevOps)
人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用
Docker
可以通过定制应用镜像
来实现持续集成、持续交付、部署(CI/CD)。开发人员可以通过Dockerfile 来进行镜像构建
,并结合持续集成(Continuous Integration) 系统进行集成测试
,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合持续部署(Continuous Delivery/Deployment)
系统进行自动部署。而且使用
Dockerfile
使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。 -
更轻松的迁移
由于
Docker
确保了执行环境的一致性,使得应用的迁移更加容易。Docker
可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的 -
更轻松的维护和扩展
Docker
使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单Docker
团队同各个开源项目团队一起维护了一大批高质量的官方镜像
,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本 -
对比传统虚拟机特性
特性 容器 虚拟机 启动 秒级 分钟级 硬盘使用 一般为 MB 一般为 GB 性能 接近原生 弱于 系统支持量 单机支持上千个容器 一般几十个
docker 局限
- Docker 本身能够管理单个容器。但随着您开始使用越来越多的容器和容器化应用,并把它们划分成数百个部分,很可能会导致管理和编排变得困难, 这时候就需要
docker swarm
或kubernetes
- Docker 容器与宿主共享内核,也因此埋下了安全漏洞的隐患。 如果攻击者控制了这些子系统,主机也将不保。
- Docker 守护进程也可能成为安全隐患。Docker 守护进程需要根权限,所以我们需要特别留意谁可以访问该进程,以及进程驻留在哪个位置。相比公共区域所用的守护进程(例如 Web 服务器),本地守护进程的受攻击面要小得多
docker 使用
docker 安装
略
镜像查找
docker search
镜像获取
docker pull
镜像列表
docker images
镜像删除
docker rmi
镜像定制
镜像的定制
实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile
。
Dockerfile
是一个文本文件,其内包含了一条条的 指令(Instruction)
,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
例如在一个空白目录中,建立一个文本文件,并命名为 Dockerfile:
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
Dockerfile 语法
略
容器启动
docker run
进入容器
docker exec
容器查看
docker ps
停止/启动/删除容器
docker stop
, docker start
, docker rm
数据管理
数据卷
数据卷
是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性
- 数据卷 可以在容器之间共享和重用
- 对 数据卷 的修改会立马生效
- 对 数据卷 的更新,不会影响镜像
- 数据卷 默认会一直存在,即使容器被删除
注意:
数据卷
的使用,类似于 Linux 下对目录或文件进行mount
,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制)。
创建一个数据卷
$ docker volume create my-vol
查看所有的 数据卷
$ docker volume ls
查看指定 数据卷
的信息
$ docker volume inspect my-vol
[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
启动一个挂载数据卷的容器
在用 docker run
命令的时候,使用 --mount
标记来将 数据卷 挂载到容器里。在一次 docker run
中可以挂载多个 数据卷。
$ docker run -d -P \
--name web \
# -v my-vol:/usr/share/nginx/html \
--mount source=my-vol,target=/usr/share/nginx/html \
nginx:alpine
删除数据卷
$ docker volume rm my-vol
数据卷
是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v
这个命令。
无主的数据卷可能会占据很多空间,要清理请使用以下命令
$ docker volume prune
挂载主机目录
使用 --mount
标记可以指定挂载一个本地主机的目录到容器中去。
$ docker run -d -P \
--name web \
# -v /src/webapp:/usr/share/nginx/html \
--mount type=bind,source=/src/webapp,target=/usr/share/nginx/html \
nginx:alpine
Docker 挂载主机目录的默认权限是 读写
,用户也可以通过增加 readonly 指定为 只读
。
$ docker run -d -P \
--name web \
# -v /src/webapp:/usr/share/nginx/html:ro \
--mount type=bind,source=/src/webapp,target=/usr/share/nginx/html,readonly \
nginx:alpine