Docker 技术

来源:互联网 发布:全国十大网络品牌 编辑:程序博客网 时间:2024/06/07 07:17


github:https://github.com/docker/docker
实现用户空间隔离的技术:名称空间(NameSpace),CGroup(控制组)
什么是NameSpace::简单的理解就是,每一个虚拟的用户空间可以基于名称空间实现进程pid号、用户名等相同的机制,且每一个虚拟的用户空间相互不受干扰
什么是CGroup:控制资源使用率的机制
Docker由GO语言研发,遵守Apache开源协议
Docker由C/S架构实现,客户端称为:docker client服务端称为:docker server

(一) Docker 入门

1:对于IAAS而言,实现节点的虚拟化,每一个节点都有自己的内核空间用户空间,内核空间不易被污染,隔离性较好
2:对于容器级技术而言,实现用户空间的虚拟化,硬件之上始终是一个内核空间,而用户空间可以虚拟为多份。缺点:内核空间容易被污染,隔离性能较差
3:对于虚拟化虚拟机而言,实现特定编程语言的运行环境,提供代码运行的虚拟空间。例如:JVM(Java 虚拟机)

  • NameSpace名称空间实现用户空间隔离
1:network namespace
实现隔离网络协议栈、端口号等
2:user namespace
实现用户和用户组隔离
3:IPC namespace
实现进程间通信的隔离
4pid namespace
实现进程号隔离
5:mount namespace
实现挂载隔离
6:UTS namespace
实现主机名和域名隔离
  • CGroup控制组实现用户空间隔离
CGroup用户组实现对资源的使用率隔离
  • 归纳总结
1:那么到底什么是容器技术?
容器技术 = namespace + Linux的CGroup机制
2:namespace隔离出多个用户空间
3:Linux的CGroup机制为每一个用户空间的分配资源空间
例如:分配多少CPU资源,分配多少内存资源,分配多少I/O资源
  • CGroup的子系统
/sys/fs/cgroup目录介绍
1:blkio
控制访问块设备的i/o资源
2:cpu
控制CPU资源的使用率
3:cpuacct
审计CPU使用时长
4:cpuset
控制CPU的核心数配比、控制内存物理资源空间的配比(可以理解为分配了一条内存条)
5:memory
控制内存资源的使用率
6:devices
控制任务对设备的访问权限
7:freezer
控制挂起或激活某个任务
8:net_cls
控制网络i/o资源对不同的用户空间的分配
9:perf_event
控制性能事件的分配机制
10:hugetlb
控制大内存页面进行控制
  • Docker文件系统AUFS(advanced multi-layered unification filesystem):
Docker容器是建立在Aufs基础上的,Aufs是一种Union FS, 简单来说就是支持将不同的目录挂载到同一个虚拟文件系统下,并实现一种layer的概念。Aufs将挂载到同一虚拟文件系统下的多个目录分别设置成read-onlyread-write以及whiteout-able权限,对read-only目录只能读,而写操作只能实施在read-write目录中。重点在于,写操作是在read-only上的一种增量操作,不影响read-only目录。当挂载目录的时候要严格按照各目录之间的这种增量关系,将被增量操作的目录优先于在它基础上增量操作的目录挂载,待所有目录挂载结束了,继续挂载一个read-write目录,如此便形成了一种层次结构。
docker强依赖于AUFS,因为每一种应用程序都需要特定的运行环境,包括rootfs、以及程序运行的库文件、配置文件

(二) Docker 概念、简要应用

1:registry:类似综合仓库,用于保存docker image、layer information
2:repository:一般基于操作系统发行版本分类
3:index:管理registry的检索,例如docker search ubantu 就会先检索index
4:graph:管理本地docker的本地镜像的元数据

Alt text


  • Docker技术实现原理

Alt text

Alt text

Alt text

docker可以将开发开发人员写的源代码以及源代码所依赖的运行环境,包括文件系统、各种库文件打包,成为一个单个镜像文件。这个文件所在的空间可以看做是一个用户空间,此用户空间只需要在特定的且支持容器技术的OS之上运行即可,因此可以实现应用的快速发布
docker容器运行环境一般是基于docker的云环境,容器运行在哪个物理节点由调度器所实现的调度算法决定。docker容器的生命周期由容器的启动或删除决定,因此,容器内运行的应用程序或应用程序所依赖的文件系统一般来至于外部存储系统,与OpenStack类似,满足容器可以按需启动,按需关闭,数据也能够持久化(由卷实现)。

(三) Docker 安装

docker的镜像文件作用就是:提供container运行的文件系统层级关系(基于AUFS实现),所依赖的库文件、已经配置文件等等。

  • 安装docker
yum install -y docker
  • 启动docker
systemctl start docker
  • 获取docker使用帮助
docker --help
  • 获取centos 镜像
1:查看
docker search centos
2:获取
docker pull centos
  • 获取busybox镜像
1:查看
docker search busybox
2:获取
docker pull busybox
  • 查看本地镜像
[root@7 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/busybox latest 54511612f1c4 4 weeks ago 1.129 MB
  • 运行镜像文件,启动一个虚拟用户空间也就是虚拟container
1:使用docker run命令运行一个镜像文件
2:docker run命令的使用格式
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
3:运行centos镜像文件,运行/bin/bash命令
docker run -it -h uplooking centos:latest /bin/bash(kill的时候不会删除容器,-h 指定容器的主机名)
docker run -it --rm centos:latest /bin/bash(kill的时候会删除容器,以及删除volume)
①:登入到centos容器,先安装net-tools,会发现有IP,且网络连接模型为NAT模型
②:在宿主机上,执行ifconfig命令,可以看到多了一个docker0的NAT桥,和一个vethbf0e0dd的虚拟网卡设备,可以使用 brctl show 命令查看
③:删除或停止一个container
docker kill containerID号(docker ps 可以查看到每一个container的ID号)
注意:但是此容器并没有删除,而是停止了,可以使用docker ps -a命令看到容器依然存在。可以使用docker rm containerID号删除
4:查看docker运行的容器
docker ps
  • Docker常用命令介绍
容器生命周期管理 — docker [run|start|stop|restart|kill|rm|pause|unpause]
容器运行系统参数 — docker [ps|inspect|top|attach|events|logs|wait|export|port]
容器rootfs管理 — docker [commit|cp|diff]
镜像仓库管理 — docker [login|pull|push|search]
本地镜像管理 — docker [images|rmi|tag|build|history|save|import]
运行环境参数 — docker [info|version]
1:列出机器上的镜像
docker images
2:在docker中搜索可用镜像
docker search centos
3:从docker registry 中下拉镜像或repository
# 拉取最新版本的centos镜像
docker pull centos
# 拉取指定版本的centos镜像
docker pull centos:centos6
4:从image启动一个container,-m 指明最大的内存使用率,--cpuset-cpus 指明只能使用哪些CPU
docker run -it -m 64MB --cpuset-cpus 0 centos:latest /bin/bash
5:删除或停止一个container
docker kill 72ce30263126
docker rm 72ce30263126
6:将一个container固化为一个新的image,其中0e9a810a29a5为容器的id号,此时容器正在运行
docker commit 0e9a810a29a5 helllo:yhy
7:登入dockerhub(需要先注册https://hub.docker.com)
docker login
8:推送一个镜像或repository到registry
docker tag centos yhyblog/centos:7.2 (必须先给镜像打标签,在推送)
docker push yhyblog/centos (再推送)
docker tag helllo:yhy yhyblog/centos:hello (使用带版本号的镜像,给远端仓库先打标签)
docker push yhyblog/centos:hello (再推送)
用docker pull
把镜像下载到本机时用docker pull yhyblog/centos:hello (一定要加上tag:hello)
9:删除本地docker镜像
docker rmi 镜像ID
例如:docker rmi 4b90b5603d01
10:启动容器
①:创建一个新容器,且启动,-d表示后台运行,--name给容器取名,
docker run -d hub.c.163.com/public/lamp:latest
docker stop 9ef19b288a4c(也可以使用容器的名字停止容器)
②:启动一个停止的容器
docker start 9ef19b288a4c
11:连接到这个正在运行的终端
docker attach 9ef19b288a4c
12:在容器外查看容器输出的信息
docker logs 9ef19b288a4c
13:查看容器状态信息,uplooking-home为容器的名称
docker stats uplooking-home
14:查看容器的详细信息,-f 指明获取这个键对应的值,Name是一个键
docker inspect -f {{.Name}} uplooking
13:Docker 容器支持的网络模型
①:bridge 模型(其实这是NAT模型,因为bridge0是nat桥)
②:host 模型(使用宿主机的网络名称空间)
③:container 模型(类似与隔离模型)
④:none 模型(不配置网络)
  • 使用docker国内镜像解决方案
1:蜂巢镜像
https://c.163yun.com/hub#/m/library/
例如: docker pull hub.c.163.com/library/nginx:1.8
再次执行docker images命令,发现仓库已经发生变化
2:使用daocloud加速器
登入http://www.daocloud.io/进行注册登录,在网页最底部,选择镜像加速器,复制脚本命令配置镜像仓库。执行脚本完毕之后,查看/etc/docker/daemon.json配置文件,此时镜像已经修改。最后重启docker服务, 如果重启不了,修改/etc/docker/daemon.json配置文件为如下,让加速器生效
{"registry-mirrors": ["http://e58c0511.m.daocloud.io"],"live-restore": true}
再次pull镜像发现速度很快
3:使用阿里云Docker加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://6l4jtr4w.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
  • 配置docker的私有仓库(新启动一个虚拟机,IP:192.168.43.11)在生成环境中一般使用Nginx作为反向代理,Nginx监听于TCP/5000端口,且Nginx 必须使用SSL加密,基于basic认证
1:安装docker-registry包
yum install -y docker-distribution
2:启动docker-distribution,默认监听于TCP/5000端口
systemctl start docker-distribution.service
3:在192.168.43.10的docker-server节点上,编辑/etc/docker/daemon.json配置文件添加:
{
"insecure-registries":["192.168.43.11:5000"]
}
4:重启docker服务
systemctl restart docker.service
5:给本地镜像添加tag标签,且推送至私有仓库
docker tag docker.io/busybox:latest 192.168.43.11:5000/busybox:yhy
docker push 192.168.43.11:5000/busybox:yhy
(可在接收端/var/lib/registry/docker/registry/v2/repositories/centos/_layers目录下查看)
6:把本地的192.168.43.11:5000/busybox镜像删除,再从192.168.43.11:5000pull镜像
   docker pull 192.168.43.11:5000/centos:7.3
  • Docker的volume机制实现容器数据的持久性存储
1:可以启动一个容器的时候,临时指定挂载的volume,这个volume会自动创建,无需在宿主机上事先创建
docker run -it -v /busybox busybox:latest
登入到busybox之后,拷贝一个文件到/busybox目录
2:此hostname文件,会保存至宿主机的文件系统之上
/var/lib/docker/volumes/2a314e657c31dc06fce266d475588b528b384e296df9dd4d7a0effb2245b7a71/_data/hostname
3:先退出busybox容器,且删除此busybox容器
docker rm 7b2feeb0bb4f
4:指定宿主机volume所在路径,再次创建且启动一个新的virtualbox容器,会发现/busybox目录中的hostname文件依然存在
docker run -it -v /var/lib/docker/volumes/2a314e657c31dc06fce266d475588b528b384e296df9dd4d7a0effb2245b7a71/_data/:/busybox busybox:latest

(四) Docker 进阶(第二天内容) (推荐文章:http://blog.csdn.net/yarntime/article/details/51258824)

使用容器启动一个httpd服务的时候,必须让服务运行于前台,如果运行于后台,那么容器会自动退出,而容器必须运行于后台,那么命令是这么写:docker run -d --name uplooking --rm --net bridge -p 192.168.43.100:80:80 busybox:latest httpd -f
也可以启动httpd服务的时候,实现持久性存储,使用volume功能存储html源码,命令如下:docker run -d --name uplooking-home --net bridge -p 192.168.43.100:80:80 -v /var/lib/docker/volumes/37eafc1de4689a19136e926195bf526a943e6d159a078b042338b58a41470f43/_data/:/web busybox:latest httpd -f -h /web

  • Docker 容器的网络模型介绍 
    • 如果想要指定container连接的桥设备,使用docker daemon -b 桥设备名称 --bip 指定网桥的IP地址
  • ①:none 模型
只有一个接口:loopback
在这种模式下,容器有独立的网络栈,但不包含任何网络配置,只具有lo这个loopback网卡用于进程通信。也就是说,none模式为容器做了最少的网络设置,但是俗话说得好“少即是多”,在没有网络配置的情况下,通过第三方工具或者手工的方式,开发这任意定制容器的网络,提供了最高的灵活性
docker run -it --name uplooking --rm --net none busybox:latest /bin/sh
  • ②:bridge 模型(NAT模型)

Alt text

1:有两个接口:loopback、以太网接口eth0
2bridge模式是docker默认的,也是开发者最常使用的网络模式。在这种模式下,docker为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,实现容器之间、容器与宿主机之间的网络栈隔离。同时,通过宿主机上的docker0(自带DHCP服务,可以给容器分配IP地址、网关、DNS服务器地址)网桥,容器可以与宿主机乃至外界进行网络通信。
3:启动bridge网络模型的container命令如下:(--net bridge是默认的,连接的桥为docker0网桥)
docker run -it --name test --net bridge -h uplooking --rm busybox:latest /bin/sh
4:此时启动的container是NAT网络模型,可以使用iptables -t nat -vnL 查看此时的SNAT规则。但是NAT网络模型的container无法被外部网络看到,也就是说,外部网络无法访问此NAT网络模型的container,因此解决的方案有以下几种:
第一种:使用端口转发,此方案将container内部的一个固定端口绑定到宿主机的一个随机端口之上,那么外部网络中的主机可以通过这个随机端口访问到此container,使用-p 选择指明端口,下面的命令是将80端口转发出去,且在busybox的container中启动httpd服务
docker run -it --name uplooking -p 80 --net bridge -h uplooking --rm busybox:latest /bin/sh
mkdir /web (在container中创建httpd的站点目录 /web)
echo "<h1>hello 1</h1>" > /web/index.html (创建首页文件)
httpd -f -h /web (启动httpd进程,且指明站点目录为/web目录,-f指明httpd运行在前台,-h指明站点目录)
在宿主机中,使用命令 docker port uplooking 可以查到container的80端口映射到了宿主机的32768端口,因此在外部网络的192.168.43.11主机上发起container的web请求访问
curl http://192.168.43.10:32768
第二种:使用端口隐射的方式,此方案将container内部的一个固定端口绑定到宿主机的一个固定端口之上,那么外部网络中的主机可以通过宿主机的固定端口访问到此container,下面的命令是将container的80端口映射到宿主机的80端口,且在busybox的container中启动httpd服务
docker run -it --name uplooking -p 80:80 --net bridge -h uplooking --rm busybox:latest /bin/sh
mkdir /web (在container中创建httpd的站点目录 /web)
echo "<h1>hello 2</h1>" > /web/index.html (创建首页文件)
httpd -h /web (启动httpd进程,且指明站点目录为/web目录)
在宿主机中,使用命令 docker port uplooking 可以查到container的80端口映射到了宿主机的80端口,因此在外部网络的192.168.43.11主机上发起container的web请求访问
curl http://192.168.43.10
第三种:将端口绑定到特定IP的随机端口(其他操作类似)
docker run -it --name uplooking -p 192.168.43.100::80 --net bridge -h uplooking --rm busybox:latest /bin/sh
第四种:将端口绑定到特定IP的固定端口(其他操作类似)
docker run -it --name uplooking -p 192.168.43.100:80:80 --net bridge -h uplooking --rm busybox:latest /bin/sh
第五种:转发所有的端口,且暴露特定的端口,使用选项 -P 和 --expose
docker run -it --name uplooking -P --expose 80 --expose 8000 --expose 443 --net bridge -h uplooking --rm busybox:latest /bin/sh
  • ③:container 模型

Alt text

container网络模型启动的容器,可以与其他已经启动的容器共享网络名称空间(network namespace)
启动容器的命令如下:--net 指明使用的网络模型为container模型,与哪个启动的容器共享网络,这里启动了一个容器名为uplooking的容器,因此,此名为home的容器与uplooking的容器将共同使用一个网络名称空间
docker run -it --name home --net container:uplooking --rm busybox:latest /bin/sh
  • ④:host 模型

Alt text

host 网络模型启动的容器,使用的是宿主机的网络名称空间
docker run -it --name home --net host --rm busybox:latest /bin/sh

(五) Docker 强化(Dockerfile)

①:什么是Dockerfile:Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应启动的container中的一条命令。Docker程序将这些Dockerfile指令翻译真正的Linux命令。Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile。Docker程序将读取Dockerfile,根据指令生成用户自定义的image。相比image这种黑盒子,Dockerfile这种显而易见的脚本更容易被使用者接受,它明确的表明image是怎么产生的。有了Dockerfile,当我们需要定制自己额外的需求时,只需要基于原有的image在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦
②:Dockerfile指令要求的格式:Dockerfile的指令是忽略大小写的,建议使用大写,使用 # 作为注释,每一行只支持一条指令,每条指令可以携带多个参数。
③:Dockerfile指令的分类:Dockerfile的指令根据作用可以分为两种,构建指令设置指令构建指令用于构建image,其指定的操作不会在运行image的容器上执行设置指令用于设置image的属性,其指定的操作将在运行image的容器中执行

  • 举例说明:创建一个/root/httpd.dockerfile(直接使用vim命令创建就好)
# make in uplooking yhy
# FROM指明基于什么镜像进行创建Dockerfile,image可以是官方远程仓库中的,也可以位于本地仓库
FROM busybox:latest
# MAINTAINER指定镜像的提供者
MAINTAINER yhy@uplooking
# COPY指明拷贝的文件,将当前目录中的index.html文件拷贝到镜像中,路径为/app/www/index.html(需要在当前的httpd.dockerfile文件所在目录创建一个index.html文件)
COPY index.html /app/www/index.html
# EXPOSE指明暴露出来的端口
EXPOSE 80/tcp
# CMD指明运行的命令,这里使用列表的形式,使得httpd运行的pid号为1,那么就可以在宿主机中使用docker stop停止此dockerfile创建的image运行的container
CMD ["httpd", "-f", "-h", "/app/www"]
  • 使用docker build创建镜像(docker build - -help 可以查看使用的帮助)
1:首先创建一个docker的工作目录
echo "<h1>hello opsdev</h1>" > /root/index.html
2:在使用docker build基于dockerfile创建image,这里的-f指定dockerfile的路径,-t指明生成的镜像文件的repository为busybox,tag为httpdserver,且/root/指定生成dockerfile的工作目录
docker build -f /root/httpd.dockerfile -t busybox:httpdserver /root/
  • 使用docker images查看新生成的镜像文件
[root@7 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox httpdserver 2ed44ddaf698 7 seconds ago 1.129 MB
docker.io/centos latest 196e0ce0c9fb 4 weeks ago 196.6 MB
docker.io/busybox latest 54511612f1c4 5 weeks ago 1.129 MB
  • 使用新生成的镜像启动一个container
# 这里的-P指明暴露dockerfile中指定暴露的端口
docker run -d --name httpd_server -P busybox:httpdserver
  • 查看端口映射,请求页面
[root@7 ~]# docker port httpd_server
80/tcp -> 0.0.0.0:32768
curl 127.0.0.1:32768
  • 基于Centos的镜像创建一个httpd的镜像
①:创建一个生成httpd镜像的工作目录
mkdir -p /docker/httpd
②:切入到/docker/httpd
cd /docker/httpd
③:创建一个dockerfile文件
vi httpd.dockerfile(内容如下)
----
FROM centos:latest
MAINTAINER yhy@uplooking
# 可以使用CMD将yum仓库指向阿里云的仓库
# CMD ["wget", "-O", "/etc/yum.repos.d/CentOS-Base.repo", "http://mirrors.aliyun.com/repo/Centos-7.repo"]
# 这RUN指令是在image中安装服务,由于安装过后的安装包以及头文件会保存到文件系统上,因此可以执行yum clean all 来清除
RUN yum repolist && yum install -y httpd php php-mysql php-mbstring && yum clean all && echo "<?php phpinfo(); ?>" > /var/www/html/index.php
# 暴露端口
EXPOSE 80/tcp
# 启动httpd服务
CMD ["/usr/sbin/httpd", "-f", "/etc/httpd/conf/httpd.conf", "-DFOREGROUND"]
----
④:创建镜像文件
docker build -f /docker/httpd/httpd.dockerfile -t centos:httpd2.4 /docker/httpd
⑤:运行生成的镜像文件
docker run -d --name httpd -P centos:httpd2.4
docker run -d --name httpd -p 80:80 centos:httpd2.4
  • 扩展(写清楚步骤和过程)
1:创建一个基于Centos的httpd镜像,php以模块方式嵌入httpd,站点目录为/app/www,且站点目录的源码文件存储在宿主机文件系统上的volume之上,要求以www用户的身份运行,且暴露80端口,volume提供WordPress源码
2:创建一个基于Centos的Mariadb的容器镜像
3:分别启动这两个镜像,实现外网主机可以访问到WordPress的安装界面。
  • 如果上述题目实现不了,可以将Mariadb安装在宿主机,同时在宿主机上提供一个volume的挂载点/data/,在/data/目录放入WordPress源码,那么运行container容器如下命令
docker run -d --name httpd1 -p 80:80 -v /data/:/var/www/html centos:httpd2.4
详细步骤:
1、同上,利用centos生成httpd镜像,只需把配置文件改成RUN yum repolist && yum install -y httpd php php-mysql php-mbstring && yum clean all即可,查看生成的镜像
2、安装数据库,创建wp数据库,并对wp@“172.17.%。%”授权(此网段为容器内IP),密码为123456
3、创建/data目录,上传wordpress源码包,放在/data目录下并解压,删除压缩包及其他无关文件,进入wordpress,用mv ./* ../将当前目录下所有文件移到上级目录,返回上级目录,将WordPress目录删掉,并将Wp-simple-config.php重
命名为wp-config.php,进入wp-config.php文件,对wp授权写入,此处的IP地址应写物理机IP地址,最后重启数据库
4、运行镜像并将/data目录挂载到/app/www/html目录下,docker run -d --name httpd -p 80:80 -v /data/:/var/www/html centos:httpd2.4 
5、 docker port httpd查看端口,然后再web服务器上访问物理机IP+端口,即可看到WordPress安装界面
原创粉丝点击