设为首页 收藏本站
查看: 631|回复: 0

[经验分享] docker知识全面讲解

[复制链接]
发表于 2018-5-29 06:14:49 | 显示全部楼层 |阅读模式
  说明:我无法使文档变得有趣,所以我只能尽力让它变得简洁和清晰,虽然你看着内容还是很多,但是只要你一步步的做下去,肯定会对docker有更深的了解。这篇文档主要是说明docker的使用,没有实际例子,下篇文档会以实例为主。
  注:部分图片来自于网络,感谢分享的人。
  志不坚者智不达!!!
1.docker介绍
1.1 虚拟机与容器的对比
DSC0000.png

  上图所示,容器技术相较于VM少了客户机系统这一层;底层用到了linux的LXC的容器技术,所以docker目前只能运行于linux的64位系统之上(能运行32位系统也是做过处理的,降低效率),官方提供了运行于windows上的工具,但是这个工具其实是集成一个微型的virtubox虚拟机,说白了还是得需要linux系统。
1.2  docker组件
DSC0001.png

  Docker之所以火的很快,原因之一就是它的仓库。
  仓库类似于github,很多现成的镜像供各位下载,直接用docker pull redis-server(这个名字是瞎起的)就可以拉下来一个redis服务器的镜像,放到自己的docker里就能用了,不用自己解决依赖、安装redis。好多开源工具都有docker镜像,这就使得用户只需要下载使用就行,完全省去了处理软件依赖、缺少库文件、安装部署等环节。
1.3  docker与OpenStack对比
DSC0002.png

  总的来说docker不如openstack强大,但是docker灵活、简单、占资源更少。
  Docker适合微服务,一般一个docker容器只跑一个进程,连ssh服务都不要开启;像数据库这种大且重要的服务最好别用docker来跑,快慢放一边,万一有个bug就麻烦了。
  用docker来搭建测试环境、开发环境等都可以提高效率,还占用很少物理资源;docker其实就是轻量的虚拟机,虚拟机能干的都交给docker也行,但是要结合业务场景来看。
  拿咱们公司的订单服务来说,业务高峰时订单服务变慢,那可以起20个docker都跑订单服务,但假如起20个虚拟机来跑的话,抛开启动速度不说,启动瞬间可能出现IO风暴,导致磁盘IO特别高,直接影响服务质量。
2. Docker安装和镜像、容器
  首先要说明的是,据传言ubuntu运行docker更快,我没有细研究过,在ubuntu和centos上也都试过docker,没感觉有什么区别(可能是测试的比较浅)。看过一些资料,没觉得docker在ubuntu上有什么优越的,那就更熟悉哪个用哪个吧,所以下面主要以centos为宿主系统进行测试。
2.1 docker安装
2.1.1 centos系统上docker安装
  在centos下,如果有epel源直接yum install docker-io就完成安装了。
DSC0003.png

  /etc/init.d/docker start启动docker。
2.1.2 ubuntu系统上docker安装
  sudo apt-get remove debian-keyringdebian-archive-keyring
  sudo apt-get clean
  sudo apt-get update && sudo apt-get-y install debian-keyring debian-archive-keyring
  wget -qO- https://get.Docker.com/ | sh
  注:如果ubuntu启用了ufw,要配置使其能转发请求,并允许2375端口访问外网。
2.2镜像管理
  前文说过,docker之所以这么火,就是因为它有一个类似于github的dockerhub,上面存放着很多现成的镜像,有官方的和非官方的等等。
  
  dockersearch centos查询centos镜像,
DSC0004.png

  与github类似,直接pull就可以把镜像拉下来,
  
  dockerpull centos
  可能要多pull几次才能成功。
  
DSC0005.png

  下载的centos镜像才170多M,所以很多你认为该有的命令它是没有的,有个心理准备。
  docker search
  搜索镜像
  docker pull
  获取镜像
  docker images
  查看本地已有镜像
  docker rm
  删除镜像
  docker ps
  查看容器
DSC0006.png

  docker images:查看本地有什么镜像,比如有centos,有ubuntu,有redis,有elk。
  docker ps –a: 命令能查看所有运行的、停止的镜像的命令状态,包含容器名称、镜像名、操作命令等。
  docker ps –l: 查看最后一个容器的信息。
  镜像就类似于VCenter里的镜像,容器就类似于一个真实的VMware WorkStation,容器就是通过镜像来创建的。
2.3 启动前台镜像
DSC0007.png

  run的作用:它首先检测有没有对应的镜像名,如果没有就自动pull,如果有就利用这个镜像来启动一个容器;
  -i:进入镜像;
  -t:启动一个tty终端;
  /bin/bash:启动docker容器执行/bin/bash这个进程。
  输入上图命令就会进入一个运行着/bin/bash进程的docker容器,进入后ps aux一下,发现只有一个/bin/bash进程,如下,
DSC0008.png

  在当前容器里执行exit就退出了/bin/bash进程,同时这个docker容器也就停止了。
  重新启动一个已经停止的容器:docker startcontainer-id。
  注:每一个docker容器并不是只能运行一个进程,但最好配置为只运行一个进程,不然还不如用虚拟机呢;既然容器只运行一个进程,那当这个进程结束后,docker容器也就停止了。
  “—name name1”:指定容器名称为name1;
  “-h hostname1”:指定容器主机名为hostname1。
2.4 启动后台镜像
  启动一个后台运行的docker容器(这个进程必须支持后台运行):
DSC0009.png

  如图所示,提示本地没有nginx的docker镜像,所以它先下载nginx镜像然后再运行,然后会在后台启动一个nginx进程,必须把nginx配置为前台模式(daemon off;),不然这个容器启动一下nginx就马上退出了,前文讲过进程结束容器也就退出了。
  正在运行的容器是不能直接用rm删除的,会提示加-f强制删除或者根据容器id来删。
  正确的做法是先停止容器,docker stop container-id,然后再rm删除。目前(2016-09-22)是没法根据什么状态、什么参数来批量删除容器,只能一个个的停止、删除,但是可以通过下述命令变相做到全部删除,
  docker rm `docker ps –a -q`
  -a:列出所有容器。
  -q:只返回容器ID。
2.5容器管理
DSC00010.png

2.6 进入后台容器
  可以用docker attach container-id来进入一个后台容器,但是可能会进不去,直接卡住,不得不用ctrl+c来退出,但是ctrl+c后也就结束了这个容器了;
  网上查着说,进入后台容器后,可以用ctrl+P+Q来退出,但是我试了试退不出来。。。
  用nsenter命令来进入后台容器更合适一点,nsenter是linux自带的命令,可以进入一个命名空间的功能,命令如下:
DSC00011.png

  使用nsenter进入容器后,直接用exit命令退出容器。
  为了之后的操作方便,可以将上面的两条命令放到脚本里,一执行脚本就进入镜像了。
  [root@salt-master docker-scripts]# cat/root/docker-scripts/mynginx.sh
  #!/bin/bash
  CNAME=$1
  CPID=$(docker inspect --format"``.`State`.`Pid`" $CNAME)
  nsenter --target $CPID --mount --uts --ipc--net --pid
  查看到mynginx里的nginx的root目录在“root   /usr/share/nginx/html;”。
  注:可靠资料说nsenter一般适用于docker1.2或者更早的版本,但是我在最新的版本(1.10)用着挺好,所以我一直用着这个;docker exec命令是在docker 1.3中引入的,推荐使用这个。
3.Docker进入容器和网络访问
DSC00012.png
指定映射最常用的是第一种,直接指定宿主端口:容器端口;
  第二种,假如宿主有多个ip的话,让容器的端口绑定到宿主的固定一个ip的端口上;
  第三种,只绑定宿主ip,端口随机取;
  第四种,它的意思是一条docker run命令可以同时用多次”-p”参数,指定多个端口映射关系,比如,docker run –d –p 99:80 –p 33:443 –name mynginx33 nginx
DSC00013.png

  启动容器时用-P(大写)参数,表示让容器随机对应一个宿主机的端口,如上,容器的80端口对应宿主的32768端口,容器的443对应宿主的32769端口。
  比如我的宿主ip是192.168.0.55,这时候在宿主机的浏览器输入192.168.0.55:32768就可以访问到docker容器里的nginx应用了。
  端口随机映射的好处是:端口不会冲突。难点是,生产中还得用脚本或者其他方式获取到这个随机的端口,由于它是变化的,所以脚本必须得适应这种变化性。
DSC00014.png

  

  用小p来手动指定端口映射,如上所示,将容器的80端口映射到宿主的91端口上,而443没有指定映射关系,所以443不可访问。
4. Docker数据管理
DSC00015.png

4.1 挂载数据卷
  下面开始练习。
4.1.1 将容器目录挂载到宿主的随机目录
  dockerrun -it --name volume-test1 -h centos-01 -v /data centos  ;创建一个名字是volume-test1,以centos系统为基础镜像的容器,它的主机名是centos-01,把这个容器的/data目录挂载到宿主机上。
  重新开一个SecureCRT session,然后输入docker inspect -f``.`Volumes` volume-test1,就会看到下面的:
  map[/data:/var/lib/docker/volumes/a6d633be7da3ca959a45328f9d95f9b7db7c1f7ff9012a51ed85a0bdb7f98b94/_data]
  它相当于是一个字典,把容器的/data映射到宿主的/var/lib/docker/volumes/a6d633be7da3ca959a45328f9d95f9b7db7c1f7ff9012a51ed85a0bdb7f98b94/_data。
  在容器的/data目录下新建一个文件,可以在/var/lib/docker/volumes/a6d633be7da3ca959a45328f9d95f9b7db7c1f7ff9012a51ed85a0bdb7f98b94/_data里看到;
  同样,在宿主的
  /var/lib/docker/volumes/a6d633be7da3ca959a45328f9d95f9b7db7c1f7ff9012a51ed85a0bdb7f98b94/_data里创建一个文件,也能在容器的/data目录下看到。
  这个跟VMware的共享目录一模一样,一对儿目录映射关系
4.1.2 指定容器挂载到宿主的固定目录
  dockerrun -it --name volume-test2 -h centos-02 -v /opt/centos-2:/data centos
  dockerrun -it --name volume-test2 -h centos-02 -v /opt/centos-2:/data:ro centos ,这里的ro是让容器只读不可写。
  
  
  上面用-v参数来建立容器和宿主的磁盘映射关系,其实是违背了docker的“一处部署,到处运行”的原则,上面的方法在Dockerfile(后文会讲到)里是不支持的。
  但是这样指定磁盘映射也有好处,比如收集docker容器里的进程日志,假如在容器里再开一个logstash就不符合docker运行单进程的原则,变得臃肿,所以在所有docker容器里建一个log目录,然后都统一映射到宿主的/opt/docker-log里,然后在宿主起一个logstash进程,通过/opt/docker-log这个目录就能收集到所有docker进程的日志了。
4.2 数据卷容器
  数据卷容器的作用实现了各容器之间的数据共享,容器不论起停都不影响数据共享,如下,
DSC00016.png

  新建的容器volume-test4共享了容器volume-test1的数据卷,所以新创建的volume-test4容器就有/data这个目录,并且这个目录下有刚才创建的文件。
5. 手动构建Docker镜像
  构建镜像的话,现以官方的centos docker镜像为基础镜像来创建容器,进入容器后一顿yum或者一顿make,这样镜像就完成了一半了,再提交就行了。
  下面实例构建一个nginx的容器。
  ①  docker pull centos
  ②  docker run –it –namenginx-man-construct centos
  ③  在centos容器里,安装编译安装nginx所需的依赖包,
[root@962aee9a1846 /]# yum -y install wget gcc gcc-c++openssl-devel make
  ④  进入/usr/local/src,下载pcre,解压pcre(不用安装,一会安装nginx时指定pcre的解压目录即可)
  ⑤  建立nginx的运行用户,useradd -s /sbin/nologin -M www;
  ⑥  下载nginx的tar包,wget http://nginx.org/download/nginx-1.10.1.tar.gz,解压进入nginx目录,./configure--prefix=/usr/local/nginx-1.10 --user=www --group=www --with-http_ssl_module--with-http_stub_status_module --with-pcre=/usr/local/src/pcre-8.39 &&make && make install。
  ⑦  设置nginx开机自启动,将/usr/local/nginx/sbin/nginx加到/etc/rc.local里(这是一个坑,后面会讲到),但是这样加在平常的系统(物理机或虚拟机)里是可以自启动的,但是在容器里不行,前面说过,必须让进程运行在前台,不然容器仅仅执行一个…./nginx的启动命令就以为结束任务了,然后就退出容器了,所以要让nginx在前台运行,修改nginx.conf,在顶部加一条“daemon off;”即可。
DSC00017.png

  ⑧  yum clean all。然后退出容器,exit
  ⑨  提交镜像,
DSC00018.png

  做完上面的步骤就创建并提交完docker镜像了,下面我们执行镜像,
  docker run -d -p 92:80zhangshanci/my-nginx:v1 ,执行了这条命令,用docker ps –l查看容器状态是退出的,这是怎么回事呢?不是说设置了开机自启并且daemon off就可以了嘛,其实是把“/usr/local/nginx/sbin/nginx”加到/etc/rc.local后也不会自启动nginx,需要手动启动。我们进入镜像删除/etc/rc.local的“/usr/local/nginx/sbin/nginx”,docker run –it zhangshanci/my-nginx:v1;然后退出镜像,重新commit一次,dockercommit -m 'create www user' 6df7168a3eda zhangshanci/my-nginx:v3,然后docker run–d –p 92:80 zhangshanci/my-nginx:v3 /usr/local/nginx-1.10/sbin/nginx,再docker ps –l就发现容器没有退出。
  注1:修改镜像后要重新commit;构建镜像也可以添加自启动命令或者参数,后面的构建Dockerfile会讲到。
6. 由Dockerfile构建 Docker镜像
  由Dockerfile自动构建镜像,其实就是把手动构建的命令逐行写入一个“脚本”里,只不过这个脚本有自己的语法。
  现把上面手动创建nginx镜像的结果写成dockerfile形式,你会发现超级简单。
DSC00019.png

  这里是创建Dockerfile时会用到的语法,下面进行实际创建。
  ①  mkdir -p /opt/docker-file/nginx&& cd /opt/docker-file/nginx
  ②  vim Dockerfile   (开头字母必须大写),内容见下:
  # This is my first Dockerfile
  # version 1.0
  # Author: shanci zhang
  #Base images
  FROM centos
  #MAINTAINER
  MAINTAINER zhangci
  #ADD使用这个命令拷贝文件或目录(压缩包会自动解压);必须把文件拷贝到Dockerfile同目录下
  ADD pcre-8.39.tar.gz /usr/local/src
  ADD nginx-1.10.1.tar.gz /usr/local/src
  #RUN
  RUN yum install -y wget gcc gcc-c++ makeopenssl-devel
  RUN useradd -s /sbin/nologin -M www
  #WORKDIR 相当于cd,切换到目录
  WORKDIR /usr/local/src/nginx-1.10.1
  RUN ./configure--prefix=/usr/local/nginx-1.10 --user=www --group=www --with-http_ssl_module--with-http_stb_module --with-pcre=/usr/local/pcre-8.39http_stb_module--with-pcre=/usr/local/pcre-8.39 && make && make install
  RUN echo "daemon off;" >>/usr/local/nginx-1.10/conf/nginx.conf
  ENV PATH /usr/local/nginx-1.10/sbin:$PATH
  #对外开放80端口
  EXPOSE 80
  #容器启动时自动执行“nginx”命令
  CMD ["nginx"]
  ③  pcre-8.39.tar.gz和nginx-1.10.1.tar.gz拷贝到与Dockerfile的同级目录下。
  ④  构建镜像,docker build -t nginx-dockerfile:v1 /opt/docker-file/nginx/ (-t后面跟的是镜像名字,最后的路径是Dockerfile的路径)
  ⑤   DSC00020.png 无需commit就能查到这个镜像了。
7.  Docker核心原理-资源隔离和限制
  目前通过加参数可以做到cpu和内存的资源限制,但centos6还无法限制磁盘,centos7可以限制磁盘配额。
7.1 压测实验cpu和内存的限制
  通过压力测试来实验限制cpu资源;在linux下使用压测工具:stress。
  有epel源(epel6可以,epel7好像不行stress)的情况下,yum install -y stress即可完成安装。需要在容器里安装压测工具,目的是压测容器而不是压测宿主机。
  我们先写一个Dockerfile来创建一个镜像:
  vim /opt/docker-file/stress-container/Dockerfile
  FROM centos
  ADD epel-6.repo /etc/yum.repos.d/
  RUN yum -y install stress && yumclean all
  ENTRYPOINT ["stress"]
  注:ENTRYPOINT ["stress"]这一行表示启动容器后,容器立刻执行stress命令并接收参数;在有这个参数的情况下,docker run -it --rm stress1 --cpu 4 这条进入容器的命令相当于docker run -it --rm stress1  stress --cpu 4,加上一个ENTRYPOINT就省去了每次启动容器都加这个命令了。
  把epel-6.repo下载到/opt/docker-file/stress-container目录下,然后,docker build-t stress /opt/docker-file/stress-container。
  docker run –help可以查看dockerrun可以添加的参数,
DSC00021.png

7.2 cpu限制配额
  -c参数:指定该容器占用宿主机cpu的权重,也可以叫配额,默认是有1024个配额,也就是满配额。
  比如宿主机只有一个容器,同时该容器的配额是1024,那么启动这个容器时就可以占用宿主机的100%的cpu;宿主机同样只有一个容器,该容器的配额是512(-c 512),那么启动这个容器最多只能占用宿主机的50%的cpu。
  比如有两个容器,他俩的cpu配额都是1024,那么启动这两个容器时就会各占50%的cpu。
  比如有两个容器,A容器的cpu配额是1024,B容器的cpu配额是512,那么启动这两个容器时A容器占用66%的cpu,B容器占用33%的cpu。
  实际测验:
  docker run -it --rm stress1 --cpu 1,这样就启动了一个装有stress压测工具的容器。
  --rm是说容器结束后自动删除容器,--cpu 1是说占用一个cpu核心来执行stress的压测实验。
  运行上面的命令后,在宿主机用top查看cpu情况,发现宿主机的cpu被这个容器占用了25%,因为我的宿主机是4核的。
  结束上面的容器,然后docker run -it --rm stress1 --cpu 4,运行这个命令后,发现宿主机出来了四个stress进程,每个都占用25%,一共占用了100%的宿主机cpu。
  注1:这里的宿主机是相对于docker来说的宿主机,这个宿主机也可能是物理机或者虚拟机。
  注2:安装stress压测工具的目的是让容器把它所能利用的cpu资源跑满,看看能占宿主机的百分之多少;stress这个工具会一直做运算,直到cpu跑满。
  也可以通过—cpuset-cpus指定使用哪个cpu来运行容器,docker run –it –cpuset-cpus=0 stress,用第一个cpu来运行容器stress。
7.3 内存限制配额
  上面用-c和—cpuset-cpus来指定cpu配额和使用哪个cpu,下面来限制内存使用。
  docker run -it -m 128m --rm stress1 --cpu 8 --io 4 --vm 2--vm-bytes 500M --timeout 10s ,“-m 128m”设置stress1这个容器最大可使用宿主机128M内存,压测工具stress指定的500M的内存测试,所以随着压力增大,容器使用宿主机的内存一旦超过了128M就会触发异常并退出。
8. Docker核心原理-网络和Registry
  Docker容器默认使用桥接模式。
8.1 桥接模式
DSC00022.png

DSC00023.png

  目前起着四个容器,对应四个桥接网络,如下图,
  启动docker后会创建一个虚拟网桥(用brctl show命令查看),每启动一个容器都会创建一个桥接接口,
DSC00024.png

DSC00025.png

  宿主机和容器之间通过iptables实现端口的转换、容器上网,如下,
DSC00026.png

8.2 HOST模式
  每个docker容器可以选择不同的网络模式。
DSC00027.png

  host模式是容器不使用network啊、namespace什么的,直接和宿主机使用同一个网络堆栈,
  这样的话容器起一个80端口,宿主机就起一个80端口,容器起一个655端口,宿主机就起一个655端口,缺点的话容器与宿主机的ip范围、端口范围等统统一样;优点就是方便,假如容器的端口与宿主机没冲突,那就可以用。
9. 配置私有仓库push 和 pull
9.1 下载并运行仓库
  docker pull registry
  docker run –d –p 5005:5000 registry。registry的默认运行端口是5000,如果本机5000端口被占用了,可以指定一个别的端口。
9.2 找一个已有镜像打tag
  docker tag zhangshanci/my-nginx:v3192.168.0.55:5005/test/nginx:v1 ,
  “zhangshanci/my-nginx:v3”是镜像的名称,“192.168.0.55:5005/test/nginx:v1”是要存到仓库里的名称。
9.3 push镜像
  高版本的docker在push时要求有ssl数字证书,官网有三种解决办法:
  ①  购买一个ssl证书,在所有docker容器前端配置一个nginx做反向代理;
  ②  将下图红圈里的参数加到/etc/sysconfig/docker的启动参数里;
  ③  自己制作一个证书,不过还是得加参数,不如方法二方便还。
DSC00028.png

  修改/etc/sysconfig/docker文件,添加启动参数:
DSC00029.png

  注:这个参数也必须添加到要pull的机器上。
9.4 改完/etc/sysconfig/docker后重启docker、启动registry
DSC00030.png

  重新push镜像:
DSC00031.png

  这样push上去后,别的机器可以再pull拉下来,但是必须指定仓库的名称,如果不指定仓库名称,默认是从docker hub上pull镜像。
9.5 其他机器上pull刚才的镜像
  在192.168.0.30上,这是centos7略有不同。
  安装:yum install docker-io(有epel源前提下)
  启动:systemctl start docker
9.5.1 修改/etc/sysconfig/docker,添加一个启动参数
DSC00032.png

9.5.2 pull镜像
DSC00033.png

  这是一个装有nginx的镜像,以它为镜像启动一个容器,
  docker run -it -p :80 30ff66a25ec4/usr/local/nginx-1.10/sbin/nginx
  这样iptables –t nat –L -n就能看到本地有一个端口与容器的80端口对应,打开浏览器,输入ip:port就可以访问到容器里的nginx了。
  

  结语:看文档本来就是一个不生动、很无聊的事,所以能坚持练习到这里,说明你很厉害哈哈。
  志不坚者智不达!!!
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-482308-1-1.html 上篇帖子: docker 容器中时间的设置(跟系统同步) 下篇帖子: docker网络访问
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表