Docke技术应用

一、理论讲解 A、什么是容器 • 容器技术已经成为应用程序封装和交付的核心技术 • 容器技术的核心有以下几个内核技术组成: – CGroups(Control Groups)-资源管理 – NameSpace-进程隔离 – SELinux安全 • 由于是在物理机上实施隔离,启动一个容器,可以像启动一个进程一样

B、什么是Docker • Docker是完整的一套容器管理系统 • Docker提供了一组命令,让用户更加方便直接地使 用容器技术,而丌需要过多关心底层内核技术

C、Docker优点 • 相比于传统的虚拟化技术,容器更加简洁高效 • 传统虚拟机需要给每个VM安装操作系统 • 容器使用的共享公共库和程序

D、Docker的缺点 • 容器的隔离性没有虚拟化强 • 共用Linux内核,安全性有先天缺陷 • SELinux难以驾驭 • 监控容器和容器排错是挑战

F、什么是镜像 • 在Docker中容器是基于镜像启动的 • 镜像是启动容器的核心 • 镜像采用分层设计 • 使用快照的COW技术,确保底层数据打开不丢失 Docker hub镜像仓库 • https://hub.docker.com • Docker官方提供公共镜像的仓库(Registry)

二、部署Dock

安装Docker

rpm -ivh docker-engine-1.12.1-1.el7.centos.x86_64.rpm

rpm -ivh docker-engine-selinux-1.12.1-1.el7.c

三、镜像操作 • 下载镜像(从镜像仓库中下载镜像): #docker pull centos • 上传镜像(上传镜像到仓库): #docker push centos • 导入镜像(通过tar包文件导入镜像): # docker load < xx.tar • 导出镜像(将本地镜像导出为tar文件):# docker save image_name > xx.tar • 启动镜像生成一个容器:# docker run -it centos bash
• 重命名镜像名称:# docker tag centos:latest test:v1

镜像常用命令:

四、容器操作 容器常用命令

使用镜像启动容器 [root@jacob ~]# docker run -it centos bash //启动后容器放在前台运行 [root@jacob~]#docker run -itd centos bash //启动后容器放在后台运行

进入容器的三种方法 方法一: – docker attach 进入容器,exit会导致容器关闭 [root@ms docker]# docker attach fb66c90f5bf9 [root@fb66c90f5bf9 /]# exit Exit

方法二: – docker exec 进入容器时后面必须执行一条命令 退出时不会关闭容器 [root@ms docker]# docker exec -it 01a7e3e5f71b bash [root@01a7e3e5f71b /]# exit exit

方法三: –那么通过容器的ID号进入容器 获取容器的pid号: [root@ms ~]#docker inspect --format "{{.State.Pid}}" fb66c90f5bf9 通过容器的pid号进入容器: [root@ms ~]# nsenter -t 3974 -u -i -n -p 那么通过容器的ID号进入容器可以编写脚本: [root@ms docker]# vim ns.sh #!/bin/bash

Use nsenter to access docker

docker_in(){ NAME_ID=$1 PID=$(docker inspect -f "{{ .State.Pid }}" $NAME_ID) nsenter -t $PID -m -u -i -n -p } docker_in $1

删除容器 删除已经关闭的容器: [root@ms docker]# docker rm 7313aebddfd7 删除正在运行的容器命令 [root@ms docker]# docker rm -f 7313aebddfd7 利用docker做实验时可以加上--rm参数 容器执行完命令后自动删除: [root@ms docker]# docker run --rm centos /bin/echo "hehe" 只列出正在运行容器的ID号 [root@ms docker]# docker ps -a 杀死所有正在运行的容器 [root@ms docker]# docker kill $(docker ps -a -q)

五、制作自定义镜像 1.1 问题 本案例要求制作自定义镜像: 基于centos镜像使用commit创建新的镜像文件 基于centos镜像使用Dockerfile文件创建一个新的镜像文件 1.2 步骤 实现此案例需要按照如下步骤进行。 步骤一:使用镜像启动容器 1)在该容器基础上修改yum源 1.[root@docker1 docker_images]# docker run -it centos 2.[root@8d07ecd7e345 /]# rm -rf /etc/yum.repos.d/*
3.[root@8d07ecd7e345 /]# vi /etc/yum.repos.d/dvd.repo 4.[dvd] 5.name=dvd 6.baseurl=ftp://192.168.1.254/system 7.enabled=1 8.gpgcheck=0 9.[root@8d07ecd7e345 /]# yum clean all 10.[root@8d07ecd7e345 /]# yum repolist 2)安装测试软件 1.[root@8d07ecd7e345 /]# yum -y install net-tools iproute psmisc vim-enhanced 3)ifconfig查看 1.[root@8d07ecd7e345 /]# ifconfig 2.eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 3. inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0 4. inet6 fe80::42:acff:fe11:3 prefixlen 64 scopeid 0x20<link> 5. ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet) 6. RX packets 2488 bytes 28317945 (27.0 MiB) 7. RX errors 0 dropped 0 overruns 0 frame 0 8. TX packets 1858 bytes 130264 (127.2 KiB) 9. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 10.[root@8d07ecd7e345 /]# exit 11.exit 步骤二:另存为另外一个镜像 1)创建新建镜像 1.[root@docker1 docker_images]# docker start 8d07ecd7e345         2.//可以简写为8d,要保证唯一性 3.8d07ecd7e345 4.[root@docker1 docker_images]# docker commit 8d07ecd7e345 myos:v1 5.sha256:ac3f9c2e8c7e13db183636821783f997890029d687b694f5ce590a473ad82c5f 2)查看新建的镜像,如图-1所示:

图-1 3)验证新建镜像 1.[root@docker1 docker_images]# docker run -it myos:v1 2.[root@497c7b4664bf /]# ifconfig 3.eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 4. inet 172.17.0.6 netmask 255.255.0.0 broadcast 0.0.0.0 5. inet6 fe80::42:acff:fe11:6 prefixlen 64 scopeid 0x20<link> 6. ether 02:42:ac:11:00:06 txqueuelen 0 (Ethernet) 7. RX packets 0 bytes 0 (0.0 B) 8. RX errors 0 dropped 0 overruns 0 frame 0 9. TX packets 7 bytes 578 (578.0 B) 10. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 步骤三:使用Dockerfile文件创建一个新的镜像文件 Dockerfile语法格式: – FROM:基础镜像 – MAINTAINER:镜像创建者信息(说明) – EXPOSE:开放的端口 – ENV:设置环境变量 – ADD:复制文件到镜像 – RUN:制作镜像时执行的命令,可以有多个 – WORKDIR:定义容器默认工作目录 – CMD:容器启动时执行的命令,仅可以有一条CMD 1)创建一个Apache的镜像文件 1.[root@docker1 ~]# mkdir oo 2.[root@docker1 ~]# cd oo 3.[root@docker1 oo]# touch Dockerfile    //Dockerfile文件第一个字母要大写 4.[root@docker1 oo]# cp /etc/yum.repos.d/local.repo ./ 5.[root@docker1 oo]# vi Dockerfile 6.FROM myos:v1 7.RUN yum -y install httpd 8.ENV EnvironmentFile=/etc/sysconfig/httpd 9.WORKDIR /var/www/html/            //定义容器默认工作目录 10.RUN echo "test" > /var/www/html/index.html 11.EXPOSE 80                //设置开放端口号 12.CMD ["/usr/sbin/httpd", "-DFOREGROUND"] 13.[root@docker1 oo]# docker build -t myos:http . 14.[root@docker1 oo]# docker run -d myos:http 15.d9a5402709b26b42cd304c77be442559a5329dc784ec4f6c90e4abac1c88e206 16.[root@docker1 oo]# docker inspect d9 17.[root@docker1 oo]# curl 172.17.0.7 18.test 六:创建私有镜像仓库 2.1 问题 本案例要求创建私有的镜像仓库: Docker主机:192.168.1.20 镜像仓库服务器:192.168.1.10 2.2 步骤 实现此案例需要按照如下步骤进行。 步骤一:自定义私有仓库 1)定义一个私有仓库 1.[root@docker1 oo]# vim /etc/docker/daemon.json    //不写这个文件会报错 2.{ 3."insecure-registries" : ["192.168.1.10:5000"]    //使用私有仓库运行容器 4.} 5.[root@docker1 oo]# systemctl restart docker 6.[root@docker1 oo]# docker run -d -p 5000:5000 registry 7.273be3d1f3280b392cf382f4b74fea53aed58968122eff69fd016f638505ee0e 8.[root@docker1 oo]# curl 192.168.1.10:5000/v2/ 9.{}    //出现括号 10.[root@docker1 oo]# docker tag busybox:latest 192.168.1.10:5000/busybox:latest
11.//打标签 12.[root@docker1 oo]# docker push 192.168.1.10:5000/busybox:latest //上传 13.[root@docker1 oo]# docker tag myos:http 192.168.1.10:5000/myos:http 14.[root@docker1 oo]# docker push 192.168.1.10:5000/myos:http 2)在docker2上面启动 1.[root@docker2 ~]# scp 192.168.1.10:/etc/docker/daemon.json /etc/docker/ 2.[root@docker2 ~]# systemctl restart docker 3.[root@docker2 ~]# docker images 4.[root@docker2 ~]# docker run -it 192.168.1.10:5000/myos:http /bin/bash     5.//直接启动 步骤二:查看私有仓库 1)查看里面有什么镜像 1.[root@docker1 oo]# curl http://192.168.1.10:5000/v2/_catalog 2.{"repositories":["busybox","myos"]} 2)查看里面的镜像标签 1.[root@docker1 oo]# curl http://192.168.1.10:5000/v2/busybox/tags/list 2.{"name":"busybox","tags":["latest"]} 3.[root@docker1 oo]# curl http://192.168.1.10:5000/v2/myos/tags/list 4.{"name":"myos","tags":["http"]} 七、NFS共享存储 3.1 问题 本案例要求创建NFS共享,能映射到容器里: 服务器创建NFS共享存储,共享目录为/content,权限为rw 客户端挂载共享,并将共享目录映射到容器中 3.2 方案 本方案要求需要一台NFS服务器(NFS用真机代替),ip为192.168.1.254,一台客户端docker1主机,ip为192.168.1.10,一台户端docker2主机,ip为192.168.1.20,实现客户端挂载共享,并将共享目录映射到容器中,docker1更新文件时,docker2实现同步更新,方案如图-2所示:

图-2 3.3 步骤 实现此案例需要按照如下步骤进行。 步骤一:配置NFS服务器 1.[root@room9pc01 ~]# yum -y install nfs-utils 2.[root@room9pc01 ~]# mkdir /content 3.[root@room9pc01 ~]# vim /etc/exports 4./content *(rw,no_root_squash) 5.[root@room9pc01 ~]# systemctl restart nfs-server.service 6.[root@room9pc01 ~]# systemctl restart nfs-secure.service 7.[root@room9pc01 ~]# exportfs -rv 8.exporting *:/content 9.[root@room9pc01 ~]# chmod 777 /content 10.[root@room9pc01 ~]# echo 11 > /content/index.html 步骤二:配置客户端 1.[root@docker1 oo]# yum -y install nfs-utils 2.[root@docker1 oo]# systemctl restart nfs-server.service 3.[root@docker1 oo]# showmount -e 192.168.1.254 4.Export list for 192.168.1.254: 5./content * 6.[root@docker1 ~]# mkdir /mnt/qq 7.[root@docker1 ~]# mount -t nfs 192.168.1.254:/content /mnt/qq 8.[root@docker1 ~]# ls /mnt/qq 9.index.html 10.[root@docker1 ~]# cat /mnt/qq/index.html 11.11 12.[root@docker1 ~]# docker run -d -p 80:80 -v /mnt/qq:/var/www/html -it myos:http 13.224248f0df5d795457c43c2a7dad0b7e5ec86abdc3f31d577e72f7929f020e01 14.[root@docker1 ~]# curl 192.168.1.10 15.11 16.[root@docker2 ~]# yum -y install nfs-utils 17.[root@docker2 ~]# showmount -e 192.168.1.254 18.Export list for 192.168.1.254: 19./content * 20.[root@docker2 ~]# mkdir /mnt/qq 21.[root@docker2 ~]# mount -t nfs 192.168.1.254:/content /mnt/qq 22.[root@docker2 ~]# docker run -d -p 80:80 -v /mnt/qq:/var/www/html -it 192.168.1.10:5000/myos:http 23.00346dabec2c7a12958da4b7fee6551020249cdcb111ad6a1058352d2838742a 24.[root@docker2 ~]# curl 192.168.1.20 25.11 26.[root@docker1 ~]# touch /mnt/qq/a.sh 27.[root@docker1 ~]# echo 22 > /mnt/qq/index.html 28.[root@docker2 ~]#ls /mnt/qq/ 29.a.sh index.html 30.[root@docker2 ~]# cat /mnt/qq/index.html 31.22 八、创建自定义网桥 4.1 问题 本案例要求: 创建网桥设备docker01 设定网段为172.30.0.0/16 启动nginx容器,nginx容器桥接docker01设备 映射真实机8080端口与容器的80端口 4.2 步骤 实现此案例需要按照如下步骤进行。 步骤一:新建Docker网络模型 1)新建docker1网络模型 1.[root@docker1 ~]# docker network create --subnet=172.30.0.0/16 docker01 2.c9cf26f911ef2dccb1fd1f670a6c51491e72b49133246f6428dd732c44109462 3.[root@docker1 ~]# docker network list 4.NETWORK ID NAME DRIVER SCOPE 5.bc189673f959 bridge bridge local
6.6622752788ea docker01 bridge local
7.53bf43bdd584 host host local
8.ac52d3151ba8 none null local
9.[root@docker1 ~]# ip a s 10.[root@docker1 ~]# docker network inspect docker01 11.[ 12. { 13. "Name": "docker01", 14. "Id": "c9cf26f911ef2dccb1fd1f670a6c51491e72b49133246f6428dd732c44109462", 15. "Scope": "local", 16. "Driver": "bridge", 17. "EnableIPv6": false, 18. "IPAM": { 19. "Driver": "default", 20. "Options": {}, 21. "Config": [ 22. { 23. "Subnet": "172.30.0.0/16" 24. } 25. ] 26. }, 27. "Internal": false, 28. "Containers": {}, 29. "Options": {}, 30. "Labels": {} 31. } 32.] 2)使用自定义网桥启动容器 1.[root@docker1 ~]# docker run --network=docker01 -id nginx 3)端口映射 1.[root@docker1 ~]# docker run -p 8080:80 -id nginx 2.e523b386f9d6194e53d0a5b6b8f5ab4984d062896bab10639e41aef657cb2a53 3.[root@docker1 ~]# curl 192.168.1.10:8080 步骤二:扩展实验 1)新建一个网络模型docker02

  1. [root@docker1 ~]# docker network create --driver bridge docker02
    2.//新建一个 名为docker02的网络模型 3.5496835bd3f53ac220ce3d8be71ce6afc919674711ab3f94e6263b9492c7d2cc 4.[root@docker1 ~]# ifconfig      5.//但是在用ifconfig命令查看的时候,显示的名字并不是docker02,而是br-5496835bd3f5 6.br-5496835bd3f5: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
  2.    inet 172.18.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
    
  3.    ether 02:42:89:6a:a2:72  txqueuelen 0  (Ethernet)
    
  4.    RX packets 8  bytes 496 (496.0 B)
    
  5.    RX errors 0  dropped 0  overruns 0  frame 0
    
  6.    TX packets 8  bytes 496 (496.0 B)
    
  7.    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

14.[root@docker1 ~]# docker network list            //查看显示docker02(查看加粗字样) 15.NETWORK ID NAME DRIVER SCOPE 16.bc189673f959 bridge bridge local
17.5496835bd3f5 docker02 bridge local
18.53bf43bdd584 host host local
19.ac52d3151ba8 none null local 2)若要解决使用ifconfig命令可以看到docker02的问题,可以执行以下几步命令

  1. [root@docker1 ~]# docker network list //查看docker0的NETWORK ID(加粗字样) 2.NETWORK ID NAME DRIVER SCOPE 3.bc189673f959 bridge bridge local
    4.5496835bd3f5 docker02 bridge local
    5.53bf43bdd584 host host local
    6.ac52d3151ba8 none null local
    3)查看16dc92e55023的信息,如图-3所示: 1.[root@docker2 ~]# docker network inspect bc189673f959

图-3 4)查看图片的倒数第六行有"com.docker.network.bridge.name": "docker0"字样 5)把刚刚创建的docker02网桥删掉 1.[root@docker1 ~]# docker network rm docker02 //删除docker02 2.docker02 3.[root@docker1 ~]# docker network create \ 4.docker02 -o com.docker.network.bridge.name=docker02
5.//创建docker02网桥 6.648bd5da03606d5a1a395c098662b5f820b9400c6878e2582a7ce754c8c05a3a 7.[root@docker1 ~]# ifconfig     //ifconfig查看有docker02 8.docker02: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 9. inet 172.18.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 10. ether 02:42:94:27:a0:43 txqueuelen 0 (Ethernet) 11. RX packets 0 bytes 0 (0.0 B) 12. RX errors 0 dropped 0 overruns 0 frame 0 13. TX packets 0 bytes 0 (0.0 B) 14. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 6)若想在创建docker03的时候自定义网段(之前已经创建过docker01和02,这里用docker03),执行以下命令 1.[root@docker1 ~]# docker network create docker03 --subnet=172.30.0.0/16 -o com.docker.network.bridge.name=docker03 2.f003aa1c0fa20c81e4f73c12dcc79262f1f1d67589d7440175ea01dc0be4d03c 3.[root@docker1 ~]# ifconfig //ifconfig查看,显示的是自己定义的网段 4.docker03: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 5. inet 172.30.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 6. ether 02:42:27:9b:95:b3 txqueuelen 0 (Ethernet) 7. RX packets 0 bytes 0 (0.0 B) 8. RX errors 0 dropped 0 overruns 0 frame 0 9. TX packets 0 bytes 0 (0.0 B) 10. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0