docker原理介绍
容器技术
容器技术是轻量级虚拟化技术。利用该技术能够将应用打包发布到不同的容器化服务器上运行
在此过程中,可以减少繁琐的应用环境构建,大大加快从源码到应用上线的过程
容器是一种轻量级应用程序隔离机制,允许内核在其自身的隔离用户空间运行数组进程。
容器具有自己的进程列表、网络堆栈、文件系统和其它资源,但是与主机以及系统上运行的其它容器共享内核
组合实现Linux容器
1. 用于隔离的名称空间 Lniux Namespaces Mount namespaces:挂载点(文件系统名称空间,利用chroot将挂载点当做根,并基于它来实现一个根文件系统) TUS namespaces:主机名与域名 IPC namespaces:信号量、消息队列和共享内存 PID namespaces:进程号 Network namespaces:网络设备、网络栈、端口等 User namespaces:用户和组 2. 用于资源控制的控制组 Control Groups(CGroups) blkio:块设备IO cpu:CPU cpuacct:CPU资源使用报告 cpuset:多处理器平台上的CPU集合 devices:设备访问 freezer:挂起或恢复任务 memory:内存用量及报告 perf_event:对cgroup中的任务进行统一性能测试 net_cls:cgroup中的任务创建的数据报文的类别标识符 3. 用于安全性的SELinux 强制SELinux时,容器进程只能写入到容器文件 容器进程作为svirt_lxc_net_t类型来运行 镜像文件通过svirt_sandbox_file_t类型类标记
核心问题解决
利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。
LXC所实现的隔离性主要是来自内核的命名空间, 其中pid、net、ipc、mnt、uts 等命名空间将容器的进程、网络、消息、文件系统和hostname 隔离开
docker architecture
# The Docker daemon The Docker daemon(dockerd) listens for Docker API requests and manages Docker objects such as images,containers,networks,and volumes.(Docker daemon监听并接收对Docker API的请求,用于管理Docker对象,例如:镜像、容器、网络、卷) # The Docker client The Docker client(docker)is the primary way that many Docker users interact with Docker The Dokcer command uses the Docker API(是众多docker user和docker daemon交互的,也可以使用Docker API进行交互。) # Docker registries A Docker registry stores Docker images(用于存储Docker镜像的仓库) Docker Hub and Docker Cloud are public resistries that anyone can use,and Docker is configured to look for images on Doker Hub by default.(Docker Hub和Docker Cloud是公共的镜像仓库) You can even run your own private registry(用户可以创建私有仓库)
docker功能
一个名为Docker的工具用于创建、控制和管理容器。Dokcer向Linux容器中添加一个API、一种映像格式以及一个发送和共享模型
Docker镜像包含一个应用程序及其所有依赖项
容器启动时,将使用LVM精简配置将该容器的读写层与只读镜像进行组合
Docker镜像可移植,并且可以保存和导出到其它系统和用户
docker组成
# register Docker镜像库,制作好的Docker镜像存储的地方,方便拉取、推送。register能够分层存储,类似于git对代码管理。 启动容器时,docker daemon会试图从本地获取相关的镜像;本地镜像不存在时,将其从Registry中下载该镜像并保存到本地 仓库分类 Sponsor Registry:第三方的的registry,供客户和Docker社区使用。 Mirror Registry:第三方的registery,只让客户使用 Vendor Registry:由发布Docker镜像的供应商提供的registry Private Registry:通过设有防火墙和额外的安全层的私有实体提供的registry Registry 由某个特定的docker镜像的所有迭代版本组成的镜像组合 一个Registry中可以存在多个Repository Repository可以分为“顶层仓库”和“用户仓库” 用户仓库名称格式为“用户名/仓库名” 每个仓库可以包含多个Tag(标签),每个标签对应一个镜像 Index 维护用户账户、镜像的校验以及公共命名空间的信息 相当于为Registry提供一个完成用户认证等功能的检索接口 # image 将APP和Libs打包之后的格式,类似于虚拟机的镜像文件 将项目文件和项目依赖的库文件的二进制文件打包在一起 允许镜像一层一层叠加,叠加层数不能超过128层 镜像术语 REPOSITORY 镜像库域名/镜像名 TAG 镜像版本号 IMAGE ID 镜像ID号 CREATED 创建时间 SIZE 镜像大小 mccadvisor 镜像所有层次 bootfs 用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节约内存资源 rootfs 位于bootfs之上,表现为docker容器的根文件系统; 传统模式中,系统启动之时,内核挂载rootfs时会首先将其挂载为“只读”模式,完整性自检完成后将其重新挂载为读写模式 docker中,rootfs有内核挂载为"只读"模式,而后通过“联合挂载”技术额外挂载一个“可写”层 位于下层的镜像称为父镜像(parent image),最底层的称为基础镜像(base image) 最上层为“可读写”层,其下的均为“只读”层 Aufs advanced multi layered unification filesystem:高级多层统一文件系统 用于为linux文件系统实现“联合挂载” aufs是之前的UnionFS的重新实现,2006年有JunjiroOkajima开发 Docker最初使用autfs作为容器文件系统层,它目前仍作为存储后端之一来支持 aufs的竞争产品是overlayfs,后者自从3.18版本开始被合并到linux内核; docker的分层镜像,除了aufs,docker还支持btrfs,devicemapper和vfs等 在Ubuntu系统下,docker默认使用Ubuntu的aufs;而在CentOS7上,用的是devicemapper: Devicemapper Device Mapper是linux2.6内核中支持逻辑卷管理的通用设备映射机制,它为实现用于存储资源管理的块设备驱动提供了一个高度模块化的内核架构 # container image启动运行后的一种状态
Registry、Image、Container三者关系
docker容器和传统虚拟化技术区别
docker使用
docker安装
1 yum install -y docker
配置docker源
#tee /etc/yum.repos.d/docker.repo << EOF >[dockerrepo] >name=Docker Repository >baseurl=https://yum.dockerproject.org/repo/main/centos/7 >enabled=1 >gpgcheck=1 >gpgkey=https://yum.dockerproject.org/gpg >EOF
时间可能会有点久耐心等待...
运行docker deamon
systemctl start docker
systemctl enable docker
docker镜像获取
# 搜索官方镜像 docker search ubuntu:14.04 # 拉取官方镜像 docker pull docker.io/technopreneural/docker-ubuntu-14.04-mysql:latest
docker命令
# docker帮助命令 docker --help # docker COMMAND 帮助 docker [command] --help # 下面是常用命令 # 查看正在运行docker容器 docker ps # 显示所有docker容器信息 docker ps -a # 查看docker容器信息 docker info # 查看docker容器版本 docker version # 查看某个容器的详细信息,信息量特别大加个管道方便查看 docker inspect [container id] | less # 启动一个容器,并且指定名称、bash、端口映射、网络模式,必须先运行一个容器,才能执行下面操作 docker run --name c1 -p --network bridge 88:80 -it docker.io/holbertonschool/base-ubuntu-1404:latest /bin/bash # 启动容器执行一条命令,完事直接删除容器 docker run --rm docker.io/holbertonschool/base-ubuntu-1404:latest echo "hello world!" # 连接一个正在运行的容器 docker attach [container id or container] # 运行docker容器 docker start [container id] # 重新运行docker容器 docker restart [container id] # 在容器中运行指定命令,it指定命令结果显示的TTY终端,容器必须是运行状态 docker exec -it [container id] [command] [args...] # 进入一个正在运行的容器,exec是额外生成一个/bin/bash环境 docker exec -it [container id] /bin/bash # 停止指定运行的容器 docker stop [container id] # 销毁指定运行的容器 docker destroy [container id] # 删除一个或多个容器 docker rm <container...> # 删除一个正在运行的容器 docker rm -f <container> # 删除所有的container docker rm `docker ps -a -q` docker ps -a -q | xargs docker rm # 查看本地源image文件 docker images # 搜索docker官方镜像库 docker search [ubuntu:14.04] # 查看指定镜像库,可以是私有镜像库 curl -k [registry_url] # 一般镜像库URL路径定义 # 查看有几个镜像 curl -k [registry_url/<versionID>/<_catalog>] # 查看镜像版本号 curl -k [registry_url/<versionID>/<image_name>/tags/list] # 拉取官方镜像 docker pull docker.io/holbertonschool/base-ubuntu-1404 # 删除镜像 docker rmi <镜像名或ID>:latest # 将容器封装为一个镜像 docker commit [container id or container] [node:node1] # 制作镜像 docker build [Dockerfile] # 创建Dockerfile文件 vim Dockerfile # 以哪个镜像为基础镜像,最基础的镜像可以从官方获取 FROM docker.io/holbertonschool/base-ubuntu-1404:latest # 维护信息接收邮箱 MAINTAINER chen qian <1016025625@qq.com> # 环境变量 ENV Interval 60 # 将本地文件拷贝到容器指定路径下 ADD run /home/work/upload/runn # 指定镜像初始运行命令 RUN apt-get install sysstat -y # 指定端口 EXPOSE 8080 # 启动容器时,如果没有指定任何参数,默认使用此运行脚本 ENTRYPOINT ["/home/work/upload/run"] :wq # 进入Dockerfile文件目录 # 生成镜像,并指定TAG docker build -t testing:1.0 ./ # 镜像推送 docker tag testing docker.io/holbertonschool/base-ubuntu-1404:1.1.1 docker push docker.io/holbertonschool/base-ubuntu-1404:1.2.1 # 导出镜像文件,以便于传输 docker save --output=base-ubuntu-1404 docker.io/holbertonschool/base-ubuntu-1404
Docker Data Volume
Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层 如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW)”机制 卷为docker提供了独立于容器的数据管理机制 可以吧“镜像”相像成静态文件,例如“程序”,把卷类比为动态内容,例如“数据”;于是,镜像可以重用,而卷可以共享; 卷实现了“程序(镜像)”和“数据(卷)”分离,以及“程序(镜像)”和“制作镜像的主机”分离,用户制作镜像时无须再考虑镜像运行的容器所在的主机的环境; 关闭并重启容器,其数据不受影响;但删除Docker容器,则其更改将会全部丢失 存在的问题 存储于联合文件系统中,不易于宿主机访问; 荣期间数据共享不便 删除容器其数据会丢失 警觉方案:“卷(volume)” "卷"是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某目录"绑定(关联)" Volume types Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机的位置有所不同; Bind mount volume(绑定挂载卷) Docker managed volume(docker管理的卷) 管理Volume docker run -it --name c5 -v /data centos:latest(docker管理的卷) docker inspec c5显示docker容器的各种详细信息 docker volume ls显示当前系统中有多少个卷
Docker Networking
Docker is concerned with two types of networking single host virtual networks provide container isolation multi host networks provide an overlay where any container on a participating host can have its own routable IP address from any other container in the network Docker安装完成后,会自动创建三个网络,可使用"docker network ls"命令查看 bridge host none 创建容器时,可为docker run命令使用network选项指定要加入的网络 docker network ls docker run -it --name c1 --network bridge wode/centos:iproute ifconfig Bridged containers 桥接式容器一般拥有两个接口:一个换回接口和一个连接至主机上某桥设备的以太网接口 docker daemon启动时默认会创建一个名为docker0的网络桥,并且创建的容器为桥接式容器,其以太网接口桥接至docker0 docker0桥为NAT桥,因此,桥接式容器可通过此桥接口访问外部网络,但防火墙规则阻止了一切从外部网络访问桥接式容器的请求
docker文件路径
/var/lib/docker/* # 查看镜像存储位置 docker daemon --help # 修改镜像文件和镜像仓库存储位置 docker daemon -g [path]
docker部分参数解析
# 本地存储和容器存储的映射 volume = /:/rootfs:ro # 本地端口到容器端口的映射 publish = 8088:8080 # 环境变量刷新周期 env Interval = 60 # 容器运行时名称 name = c1 # 网络运行模式 net = host [bridge(本机通过iptables -t nat -vnL)、none(表示使用封闭式容器)、host(表示使用开放式容器)] # 重启策略 restart = always # 容器使用镜像 maccadvisor:1.1.1 -> image_name : image_tag # ...
docker容器管理
简单批量操作容器
# 将状态是Exit的容器启动 docker start `docker ps -a | grep Exited | awk '{print $1}'` # 将运行的容器关闭 docker stop `docker ps -a | grep Up | awk '{print $1}'`
安装Docker的Python接口
1 pip install docker-py
docker模块使用
# 生成一个容器 create_container(self, image, command=None, hostname=None, user=None, detach=False, stdin_open=False, tty=False, mem_limit=None, ports=None, environment=None, dns=None, volumes=None, volumes_from=None, network_disabled=False, name=None, entrypoint=None, cpu_shares=None, working_dir=None, domainname=None, memswap_limit=None, cpuset=None, host_config=None, mac_address=None, labels=None, volume_driver=None, stop_signal=None, networking_config=None) # 重启容器 restart(self, container, timeout=10) # 启动容器 start(self, container, binds=None, port_bindings=None, lxc_conf=None, publish_all_ports=None, links=None, privileged=None, dns=None, dns_search=None, volumes_from=None, network_mode=None, restart_policy=None, cap_add=None, cap_drop=None, devices=None, extra_hosts=None, read_only=None, pid_mode=None, ipc_mode=None, security_opt=None, ulimits=None) # 查看容器运行数据 stats(self, container, decode=None, stream=True) # 停止容器 stop(self, container, timeout=10) # 展示容器中正在运行的进程 top(self, container, ps_args=None) # 启动容器中所有进程 unpause(self, container) # 更新容器配置 update_container( self, container, blkio_weight=None, cpu_period=None, cpu_quota=None, cpu_shares=None, cpuset_cpus=None, cpuset_mems=None, mem_limit=None, mem_reservation=None, memswap_limit=None, kernel_memory=None) # 阻塞直到容器停止,进入Exit状态 wait(self, container, timeout=None)
code
# -*- coding: utf-8 -*- __author__ = 'CQ' import docker def _container_list_more(self, node_ip, node_port ,container_id): """ 有些性能或监控相关的数据,在官方提供的接口中没有很好的实现 我们需要直接从Docker engine中获取数据,此时就可以使用Docker engine提供的原生Restful接口 :param self: :param node_ip: :param node_port: :param container_id: :return: """ url = ('http://' + node_ip + ":" + node_port + "/containers/" + container_id + "/json") container_more_url = Curl(url) ret_json = container_more_url.get_value() return ret_json if __name__ == "__main__": client_ins = docker.Client(base_url='tcp://127.0.0.1:2357', version='1.20', timeout=10) print(" Create the container ... ") conf = { "Name": "/berserk_heisenberg-1", # 名称要唯一 "HostName": "/berserk_heisenberg-1", "Domainname": "", "User": "", "AttachStdin": True, "AttachStdout": True, "AttachStderr": True, "Tty": True, "OpenStdin": True, "StdinOnce": True, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/bash" ], "Image": "docker.io/holbertonschool/base-ubuntu-1404:latest", "Volumes": None, "WorkingDir": "", "Entrypoint": None, "OnBuild": None, "Labels": {} } container_ret = client_ins.create_container(image=conf['image'], stdin_open=conf['OpenStdin'], tty=conf['Tty'], command=conf['Cmd'], name=conf['Name'], hostname=conf['Hostname'], host_config=conf['HostConfig'] ) client_ins.restart() client_ins.start() client_ins.stop() client_ins.unpause() client_ins.update_container() client_ins.wait()
官方文档:http://docker-py.readthedocs.io/en/stable/
docker与openstack区别