docker学习笔记6
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了docker学习笔记6相关的知识,希望对你有一定的参考价值。
VIII docker
目录
虚拟化: 41
docker:
介绍;
镜像管理;
容器管理;
网络访问;
数据管理;
镜像构建;
私有仓库;
核心技术;
生产实践;
生态圈;
一、概念:
Docker is the world’s leading software containerization platform.(build,ship,run)
docker is an open platform for building,shipping and running distributed applications. it gives programmers,development teams and operations engineers the common toolbox they need to take advantage of the distributed and networked nature of modern applications.
Docker 是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的运行效率,降低了云计算资源供应的成本,使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松;无论是应用开发者、运维人员、还是其他信息技术从业人员,都有必要认识和掌握Docker,以在有限的时间内做更多有意义的事;
docker用go语言编写,http2.0,在linux x86_64环境下运行,LXC;
LXC,Linux Container,可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性,相当于C++中的NameSpace,容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求,与传统虚拟化技术相比,它的优势在于:与宿主机使用同一个内核,性能损耗小;不需要指令级模拟;不需要即时(Just-in-time)编译;容器可以在CPU核心的本地运行指令,不需要任何专门的解释机制;避免了准虚拟化和系统调用替换中的复杂性;轻量级隔离,在隔离的同时还提供共享机制,以实现容器与宿主机的资源共享;
Linux Container是一种轻量级的虚拟化的手段;
Linux Container提供了在单一可控主机节点上支持多个相互隔离的server container同时执行的机制,Linux Container有点像chroot,提供了一个拥有自己进程和网络空间的虚拟环境,但又有别于虚拟机,因为lxc是一种操作系统层次上的资源的虚拟化;
Sourceforge上有LXC这个开源项目,LXC项目本身只是一个为用户提供一个用户空间的工具集,用来使用和管理LXC容器,LXC真正的实现则是靠Linux内核的相关特性,LXC项目只是对此做了整合,基于容器的虚拟化技术起源于所谓的资源容器和安全容器;
LXC在资源管理方面依赖于Linux内核的cgroups子系统,cgroups子系统是Linux内核提供的一个基于进程组的资源管理的框架,可以为特定的进程组限定可以使用的资源,LXC在隔离控制方面依赖于Linux内核的namespace特性,具体而言就是在clone时加入相应的flag(NEWNS NEWPID等等);
# lxc-checkconfig,该命令用于判断linux内核是否支持LXC;
containers VS VMs:
VMs(each virtual machine includes the application,the necessary binaries and libraries and an entire guest operating system, all of which may be tens of GBs in size.);
containers(containers include the application and all of its dependencies,but share the kernel with other containers. they run as an isolated process in userspace on the host operating system. they are also not tied to any specific infrastructure, docker containers run on any computer,on any infrastructure and in any cloud.);
虚拟化技术已经改变了现代计算方式,它能够提升系统资源使用效率、消除应用程序和底层硬件之间的依赖关系,同时加强负载的可以移植性和安全性,但是hypervisor和虚拟机只是部署虚拟负载的方式之一,作为一种能够替代传统虚拟化技术的解决方案,容器虚拟化技术凭借其高效性和可靠性得到了快速发展,它能够提供新的特性,并且帮助数据中心专家解决新的顾虑,容器和虚拟机之间的主要区别在于虚拟化层的位置和操作系统资源的使用方式:
虚拟机依赖于hypervisor,其通常被安装在“裸金属”系统硬件之上,这导致hypervisor在某些方面被认为是一种操作系统,一旦 hypervisor安装完成,就可以从系统可用计算资源当中分配虚拟机实例了,每台虚拟机都能够获得唯一的操作系统和负载(应用程序);通常,第一台虚拟机都将会被用来运行系统管理程序,比如Microsoft System Center,而之后的虚拟机可能包含其他企业负载,比如数据库、ERP、CRM、邮件服务器、媒体服务器、web服务器或者其他业务应用;虚拟机之间是完全隔离的,没有任何一台虚拟机知道(或者依赖)相同系统当中的另外一台虚拟机的存在,恶意软件、应用程序崩溃和其他问题只能影响一台虚拟机,虚拟机从一个虚拟系统被移动到另外一个当中,而不用考虑系统硬件和操作系统等因素; 而容器环境的工作方式则有所不同,对于容器环境来说,需要首先安装主机操作系统,之后将容器层(比如LXC或libcontainer)安装在主机操作系统(通常是Linux变种)之上,在安装完容器层之后,就可以从系统可用计算资源当中分配容器实例了,并且企业应用可以被部署在容器当中,但是,每个容器化应用都会共享相同的操作系统(单个主机操作系统);相比于虚拟机,容器拥有更高的资源使用效率,因为它并不需要为每个应用分配单独的操作系统,实例规模更小、创建和迁移速度也更快,这意味相比于虚拟机,单个操作系统能够承载更多的容器,云提供商十分热衷于容器技术,因为在相同的硬件设备当中,可以部署数量更多的容器实例,然而,单个操作系统有可能引起影响所有相关实例的单点事故,比如,恶意软件或者主机操作系统崩溃可能禁用或者影响所有容器,此外,容器易于迁移,但是只能被迁移到具有兼容操作系统内核的其他服务器当中,这样会无形中减少迁移选择;
从实际应用的角度来说,容器和虚拟机可以在同一个数据中心当中共存,因此这两种技术被认为是互补的,为现代应用程序架构师和数据中心管理员添加了可用工具集,通过不同的方式为应用负载提供支持;
docker组成:docker client、docker server;
docker的整个生命周期(docer组件):image镜像、container容器、repository仓库;
注:
运行中的镜像称为容器;
docker的image可与openstack的image比对,一个image就是一个完整的OS,docker的image是只读的,启动container时在read only的image之上加了一层writable层;
container可与kvm的VM比对,docker使用container运行应用,各container也是隔离的,kvm是用VM运行应用;
repository是集中存放image文件的地方,可与openstack的glance比对,可将docker的repository理解为github(dockerhub)、git-pull(docker-pull);
docker改变了产品交付的方式,很多开源软件都有docker镜像(早期很多开源软件有VM镜像),下载下来直接运行,省去了复杂的部署;不要把docker容器当作VM镜像来管理,不建议启用ssh;docker更适合跑微服务;
docker的所有文件在/var/lib/docker/下,containers/存放容器,graph/存放镜像;
docker资源隔离,使用LXC,具体是kernel中的namespace(pid;net;ipc;mnt;uts;user);
docker资源限制,cgroups(control groups)是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如:cpu,memory,IO等等)的机制,最初由google的工程师提出,后来被整合进Linux内核,Cgroups也是LXC为实现虚拟化所使用的资源管理手段,可以说没有cgroups就没有LXC;
docker VS openstack:
类别 | docker(PAAS) | openstack(IAAS) |
部署难度 | 非常简单 | 组件多,部署复杂 |
启动速度 | s级 | min级 |
执行性能 | 和物理系统几乎一致 | VM会占用一些资源(占系统资源的6-8%) |
镜像体积 | MB级 | GB级 |
管理效率 | 管理简单 | 组件相互依赖,管理复杂 |
隔离性 | 隔离性高 | 彻底隔离 |
可管理性 | 单进程,不建议启动sshd | 完整的系统管理 |
网络连接 | 比较弱 | 借助neutron可灵活组件各类网络架构 |
docker使用场景:
simplifying configuration;
developer productivity;
server consolidation;
multi tenancy;
code pipeline management;
app isolation;
debugging capabilities;
rapid deployment;
注:
面对产品;
面对开发;
面对测试(多版本测试);
面对运维;
面对自动化(扩容);
面对微服务;
面对大规模的分布式架构(微信红包);
二、操作:
[root@test6 ~]# uname -rm
2.6.32-431.el6.x86_64 x86_64
[root@test6 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.5 (Santiago)
[root@test6 ~]# yum update #(#yum -y install kernel*,Docker requires a 64-bit OS and version 3.10 or higher of the Linux kernel.若在centos7或rhel7上安装要求内核版本至少为3.10以上)
[root@test6 ~]# yum -y install docker-io
……
Installed:
docker-io.x86_64 0:1.7.1-2.el6
Dependency Installed:
libcgroup.x86_64 0:0.40.rc1-18.el6_8 lua-alt-getopt.noarch 0:0.7.0-1.el6 lua-filesystem.x86_64 0:1.4.2-1.el6
lua-lxc.x86_64 0:1.0.9-1.el6 lxc.x86_64 0:1.0.9-1.el6 lxc-libs.x86_64 0:1.0.9-1.el6
Complete!
[root@test6 ~]# /etc/init.d/docker start
Starting cgconfig service: [ OK ]
Starting docker: [ OK ]
[root@test6 ~]# /etc/init.d/docker restart
Stopping docker: [FAILED]
Starting docker: [ OK ]
[root@test6 ~]# ps aux | grep docker
root 42806 0.1 1.5 227004 15948 pts/0 Sl 20:19 0:00 /usr/bin/docker -d
root 42875 0.0 0.0 103316 840 pts/0 S+ 20:22 0:00 grep docker
#docker -v #(-v, --versinotallow=false,Print version information and quit)
#docker version #(Show the Docker version information,查看docker的版本号,包括客户端、服务端、依赖的Go等)
#docker info #(Display system-wide information,查看系统(docker)层面信息,包括管理的images, containers数等)
# docker search [OPTIONS] TERM(Search for an image on the Docker Hub搜索镜像)
# docker pull [OPTIONS] NAME[:TAG|@DIGEST](Pull an image or a repository from a Docker registry server,获取镜像)
# docker images [OPTIONS] [REPOSITORY](List images查看镜像;
-a, --all=false,Show all images (default hides intermediate images)列出所有images包含历史隐藏的)
# docker rmi [OPTIONS] IMAGE [IMAGE...](Remove one or more images删除镜像)
# docker run [OPTIONS] IMAGE [COMMAND] [ARG...](Run a command in a new container,#docker run --help;
-h, --hostname=,Container host name;
--name=,Assign a name to the container;
-i, --interactive=false,Keep STDIN open even if not attached;
-t, --tty=false,Allocate a pseudo-TTY;
-d, --detach=false,Run container in background and print container ID;
--restart=no,Restart policy to apply when a container exits;
-P, --publish-all=false,Publish all exposed ports to random ports,随机映射;
-p, --publish=[],Publish a containers port(s) to the host,映射HOST端口到容器,方便外部访问容器内服务,host_port可以省略,省略表示把container_port映射到一个动态端口;
-v, --volume=[],Bind mount a volume;
--volumes-from=[],Mount volumes from the specified container(s);
-c, --cpu-shares=0,CPU shares (relative weight),CPU份额控制,--cpu-shares的值不能保证可以获得1个vcpu或者多少GHz的CPU资源,仅仅只是一个弹性的加权值,默认情况下,每个docker容器的cpu份额都是1024,单独一个容器的份额是没有意义的,只有在同时运行多个容器时,容器的cpu加权的效果才能体现出来,例如,两个容器A、B的cpu份额分别为1000和500,在cpu进行时间片分配的时候,容器A比容器B多一倍的机会获得CPU的时间片,但分配的结果取决于当时主机和其他容器的运行状态,实际上也无法保证容器A一定能获得CPU时间片,比如容器A的进程一直是空闲的,那么容器B是可以获取比容器A更多的CPU时间片的,极端情况下,比如说主机上只运行了一个容器,即使它的cpu份额只有50,它也可以独占整个主机的cpu资源,cgroups只在容器分配的资源紧缺时,也就是说在需要对容器使用的资源进行限制时,才会生效,因此,无法单纯根据某个容器的cpu份额来确定有多少cpu资源分配给它,资源分配结果取决于同时运行的其他容器的cpu分配和容器中进程运行情况;
--cpuset-cpus=,CPUs in which to allow execution (0-3, 0,1);
--cpuset-mems=,MEMs in which to allow execution (0-3, 0,1),对多核CPU的服务器,docker还可以控制容器运行限定使用哪些cpu内核和内存节点,即使用--cpuset-cpus和--cpuset-mems参数,对具有NUMA架构(具有多CPU、多内存节点)的服务器尤其有用,可以对需要高性能计算的容器进行性能最优的配置,如果服务器只有一个内存节点,则--cpuset-mems的配置基本上不会有明显效果;
-m, --memory=,Memory limit,设置容器使用的最大内存上限,默认单位为byte,可以使用KGM等单位,默认情况下,除了-m(--memory)指定的内存大小以外,docker还为容器分配了同样大小的swap分区,也就是说,上面的命令创建出的容器实际上最多可以使用256MB内存,而不是128MB内存,如果需要自定义swap分区大小,则可以通过联合使用--memory-swap参数来实现控制;
--entrypoint=,Overwrite the default ENTRYPOINT of the image;
--link=[],Add link to another container;
--rm=false,Automatically remove the container when it exits);
注(-P随机映射;-p指定映射):
-P #(随机映射)
-p hostPort:containerPort
-p ip:hostPort:containerPort #(多IP时使用指定的IP)
-p ip::containerPort #(多IP时使用指定的IP)
-p hostPort:containerPort -p hostPort:containerPort
#docker ps [OPTIONS](List containers;
-a, --all=false,Show all containers (default shows just running);
-l, --latest=false,Show the latest created container, include non-running;
-q, --quiet=false,Only display numeric IDs,仅列出正在运行的容器的CONTAINER ID)
#docker port [OPTIONS] CONTAINER [PRIVATE_PORT[/PROTO]](Lookup the public-facing port that is NAT-ed to PRIVATE_PORT,查看本地哪个Port映射到container的指定port,用#docker ps也可看到)
例:
#docker port CONTAINER_ID CONTAINER_PORT
注:端口映射是docker比较重要的一个功能,原因在于我们每次运行容器的时候容器的IP地址不能指定而是在桥接网卡的地址范围内随机生成的,宿主机的IP地址是固定的,我们可以将容器的端口的映射到宿主机器上的一个端口,免去每次访问容器中的某个服务时都要查看容器的IP的地址,对于一个运行的容器,可以使用docker port加上容器中需要映射的端口和容器的ID来查看该端口号在宿主机器上的映射端口;
#docker start|stop|restart [OPTIONS] CONTAINER [CONTAINER...](Start a stopped container;Stop a running container;Restart a running container)
#docker stats [OPTIONS] CONTAINER [CONTAINER...](Display a stream of a containers resource usage statistics,查看指定容器资源使用状态信息)
#docker rm [OPTIONS] CONTAINER [CONTAINER...](Remove one or more containers)
#docker rm `docker ps -a -q` #(同#docker ps -a -q | xargs docker rm,删除所有容器)
#docker exec [OPTIONS] CONTAINER COMMAND [ARG...](Run a command in a running container,进入正在运行的容器)
[root@test6 ~]# which nsenter(此命令在util-Linux包里,使用此命令可访问指定进程的namespace)
/usr/bin/nsenter
#man nsenter
-t, --target pid,Specify a target process to get contexts from.;
-m, --mount[=file],Enter the mount namespace.If no file is specified, enter the mount namespace of the target process. If file is specified, enter the mount namespace specified by file.;
-u, --uts[=file],Enter the UTS namespace. If no file is specified, enter the UTS namespace of the target process. If file is specified, enter the UTS namespace specified by file.;
-i, --ipc[=file],Enter the IPC namespace. If no file is specified, enter the IPC namespace of the target process. If file is specified, enter the IPC namespace specified by file.;
-n, --net[=file],Enter the network namespace. If no file is specified, enter the network namespace of the target process. If file is specified, enter the network namespace specified by file.;
-p, --pid[=file],Enter the PID namespace. If no file is specified, enter the PID namespace of the target process. If file is specified, enter the PID namespace specified by file.)
#docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...](Return low-level information on a container or image;
-f, --format=,Format the output using the given go template)
生产中进入容器的方法:
方一:
#docker inspect --format " .State.Pid " nginx_test1 #(获取容器pid)
#nsenter --target <PID> --mount --uts --ipc --net --pid
方二:
https://github.com/yeasy/docker_practice/archive/v0.8.tar.gz
https://github.com/yeasy/docker_practice/blob/master/_local/.bashrc_docker(复制此文件的代码到/root/.bashrc里)
[root@test6 ~]# echo "[ -f ~/.bashrc_docker ] && . ~/.bashrc_docker" >> ~/.bashrc; source ~/.bashrc
#docker-pid CONTAINER_ID
#docker-ip CONTAINER_ID
#docker-enter CONTAINER_ID COMMAND
将运行中的容器生成新的镜像:
#docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]](Create a new image from a containers changes;
-m, --message=,Commit message)
持久化容器:
#docker export [OPTIONS] CONTAINER(Stream the contents of a container as a tar archive;
-o, --output=,Write to a file, instead of STDOUT)
例:
#docker export CONTAINER_ID > /tmp/export.tar
#cat /tmp/export.tar | docker import - export:lastest #(导入持久化容器)
持久化镜像:
#docker save [OPTIONS] IMAGE [IMAGE...](Save an image to a tar archive;
-o, --output=,Write to an file, instead of STDOUT)
例:
#docker save IMAGE_ID > /tmp/save.tar
#docker load < /tmp/save.tar #(导入持久化镜像)
给image打tag:
#docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG](Tag an image into a repository)
例:
#docker tag CONTAINER_ID load:tag
注:export&import与save&load的区别:
导出后再导入(export&import)的容器会丢失所有的历史,而保存后再加载(save-load)的镜像没有丢失历史和层(layer),这意味着使用导出后再导入的方式,你将无法回滚到之前的层(layer),同时,使用保存后再加载的方式持久化整个镜像,就可以做到层回滚,(可以执行docker tag 来回滚之前的层);
#docker build [OPTIONS] PATH | URL | -(Build an image from a Dockerfile;
-t, --tag=,Repository name (and optionally a tag) for the image;
#docker logs [OPTIONS] CONTAINER(Fetch the logs of a container,查看docker实例运行日志)
[root@test6 ~]# docker -v
Docker version 1.7.1, build 786b29d/1.7.1
[root@test6 ~]# docker version
Client version: 1.7.1
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 786b29d/1.7.1
OS/Arch (client): linux/amd64
Server version: 1.7.1
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 786b29d/1.7.1
OS/Arch (server): linux/amd64
[root@test6 ~]# docker info
Containers: 2
Images: 4
Storage Driver: devicemapper
Pool Name: docker-8:2-807654-pool
Pool Blocksize: 65.54 kB
Backing Filesystem: extfs
Data file: /dev/loop0
Metadata file: /dev/loop1
Data Space Used: 580.1 MB
Data Space Total: 107.4 GB
Data Space Available: 5.508 GB
Metadata Space Used: 1.044 MB
Metadata Space Total: 2.147 GB
Metadata Space Available: 2.146 GB
Udev Sync Supported: true
Deferred Removal Enabled: false
docker 学习笔记