Docker
什么是Docker?
Docker 最初是 dotCloud
公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud
公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。Docker
项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI)。
Docker 使用 Google
公司推出的 Go 语言 进行开发实现,基于 Linux
内核的 cgroup,namespace,以及 AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。
runc
是一个 Linux 命令行工具,用于根据 OCI容器运行时规范 创建和运行容器。
containerd
是一个守护程序,它管理容器生命周期,提供了在一个节点上执行容器和管理镜像的最小功能集。
Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker
技术比虚拟机技术更为轻便、快捷。
为什么使用Docker?
作为一种新兴的虚拟化方式,Docker
跟传统的虚拟化方式相比具有众多的优势。
- 更高效的利用系统资源
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker
对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
- 更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker
容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
- 运行环境一致
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker
的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
- 持续交付和部署
使用 Docker
可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。
而且使用 Dockerfile
使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
- 更轻松的迁移和扩展
Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
对比传统虚拟机总结
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为 MB | 一般为 GB |
性能 | 接近原生 | 弱于 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
Docker 包括三个基本概念
- 镜像(
Image
) - 容器(
Container
) - 仓库(
Repository
)
镜像:对于 Linux 而言,内核启动后,会挂载 root
文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root
文件系统。比如官方镜像 ubuntu:18.04
就包含了完整的一套 Ubuntu 18.04 最小系统的 root
文件系统。
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
容器:镜像(Image
)和容器(Container
)的关系,就像是面向对象程序设计中的 类
和 实例
一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层。
容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。
仓库:镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个 仓库(Repository
);每个仓库可以包含多个 标签(Tag
);每个标签对应一个镜像。
Docker Registry 公开服务
Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。常见的服务加速器:阿里云加速器、DaoCloud加速器
私有Docker Registry
Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。在 私有仓库 一节中,会有进一步的搭建私有 Registry 服务的讲解。
开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 Docker
命令,不影响使用。
Docker的安装
在Linux的Centos7系统中已经带有Docker,可以直接安装
yum install docker
安装之后启动Docker服务,并让它随系统启动自动加载
service docker start chkconfig docker on
获取镜像
docker pull ubuntu:12.04
阿里云的镜像加速器
1.登录:https://dev.aliyun.com/search.html
编辑配置文件输入命令
vi /etc/docker/daemon.json
将下面的这段代码复制到配置文件中,然后保存退出
{ "registry-mirrors": ["https://tj3411jq.mirror.aliyuncs.com"] }
执行两条命令,生效
sudo systemctl daemon-reload sudo systemctl restart docker
列出本地的镜像
docker images
REPOSITORY:来自于那个仓库
TAG:版本信息
IMAGE ID:ID号,(唯一)
启动容器
启动容器的方式有两种:一种是基于镜像新建一个容器并启动,另外一个是将终止状态重新启动。
docker run ubuntu:16.04 /bin/echo ‘hello Docker‘
启动一个bash终端,允许用户进行交互
docker run -t -i ubuntu:16.04 /bin/bash
退出容器但不退出:
Ctrl+p+q
在容器中exit退出容器并且退出容器
1 Exit
解析:
-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,
-i 则让容器的标准输入保持打开。在交互模式下,用户可以通过所创建的终端来输入命令,
当使用docker run来创建容器时,Docker在后台运行的标准操作
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层刻度写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中
- 从抵制池配置一个IP地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
查看容器
查看当前运行的docker容器
docker ps -a
status 为up表示容器正在,exited是容器退出状态
停止容器.
docker stop fervent_cray
fervent_cray 是容器的NAMES启动容器
docker start fervent_cray
删除容器
删除容器,要在容器停止的情况下删除
docker rm rongqi id1 容器 rd2 容器 id2
强制删除
docker rm -f 容器id1 容器id2 容器id2
强制删除所有容器
docker rm -f $(docker ps -aq)
进入容器
使用nsenter
依次执行命令
wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz tar -xzvf util-linux-2.24.tar.gz cd util-linux-2.24/ ./configure --without-ncurses make nsenter sudo cp nsenter /usr/local/bin
上面的执行完毕之后再看。
docker inspect 来查看该容器的详细信息
查询该信息下的pid的值
docker inspect -f {{.State.Pid}} af2426a893cc
进入docker 容器
nsenter --target 9999 --mount --uts --ipc --net --pid
导出容器
如果要导出本地某个容器,可以使用 docker export 命令,可以使用 docker import 从容器快照文件中再导入为镜像
docker export 63c64616c309 > ubuntu.tar
导入容器
cat ubuntu.tar | docker import - ubuntu:16.04
Docker 中的网络功能
Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。
通过ifconfig查看docker0的网络设备,docker守护进程就是通过docker0为docker的容器提供网络连接的各种服务。
Linux虚拟网桥的特点:
- 可以设置IP地址
- 相当于拥有一个隐藏的虚拟网卡
docker的地址划分:
- IP:172.17.42.1 子网掩码: 255.255.0.0
- MAC: 02:42:ac:11:00:00 到 02:42:ac:11:ff:ff
- 总共提供65534个地址
需要查看网桥,需要linux的网桥管理程序,或者直接通过ifconfig也能看到docker0
运行一个Docker容器,在容器中查看它的网络设备,Docker的Ubuntu镜像安装的容器并没有ifconfig的命令和ping的命令,可以通过这样的操作安装
在进入容器后,分别执行下面的命令
apt-get update apt install net-tools # ifconfig apt install iputils-ping # ping
接着就可以使用ifconfig和ping的方式来查看
外部访问容器
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。使用 docker ps 可以看到,本地主机的 49155 被映射到了容器的 5000 端口。此时访问本机的 49155 端口即可访问容器内 web 应用提供的界面。
下载nginx镜像
docker pull nginx
启动容器nginx(使用大写的P的方式)
docker run -d -P docker.io/nginx 可以通过浏览器访问这个nginx 地址栏输入:虚拟机IP地址+端口的方式可以访问 同样可以使用小写的p的方式指定端口,例如,将6666端口映射到nginx的80端口上 在浏览器的路径同样输入IP地址+端口(6666)的形式输出 备注:同样其他的也可以使用这种方式访问,映射接口。(tomcat。。。。) Docker建立私有的registry 我们知道可以使用hub.docker.com作为我们公共或者私有的registry。但由于服务器在国外的原因,网速会非常的慢。所以我们在利用docker开发构建容器服务时,我们希望能够建立自己的私有registry,上传镜像值我们的私有registry中心,然后在其他物理机上部署的时候,可以快速的pull,然后实现大规模的分发以及部署,提高效率。 拉取registry docker pull registry:2.6.0配置daemon.json
vim /etc/docker/daemon.json
在文件中添加,注意配置自己的IP地址,端口号统一5000
{ "insecure-registries":["172.15.73.108:5000"] }
的配置
重启docker执行命令systemctl restart docker启动registry容器
docker run -d --name registry -p 5000:5000 --restart=always -v /opt/registry/:/var/lib/registry/ registry:2.6.0
上传到私有镜像的镜像到时是默认存放在容器的/var/lib/registry/,为了防止删除registry,上传的镜像也被删除,所以启用一个volume,将上传的镜像持久化保存在我们物理机上,这里保存位置是/opt/registry/
测试是否启动容器成功curl http://172.15.73.108:5000/v2/_catalog
如果成功会输出
{"repositories":[]}可以给我们刚才新加的镜像修改一个tag
docker tag zh_nginx 172.15.73.108:5000/zh_nginx进行push到建立私有registry
docker push 172.15.73.108:5000/zh_nginx
在通过命令查看
curl http://172.15.73.108:5000/v2/_catalog
这个时候就可以查看出输出
{"repositories":["zh_nginx"]}