概述
初次接触docker时候理解那类似一个mysql服务,多个docker虚拟机理解为我们在mysql里面开了多个实例,用一个主进程(引擎)在管理各个实例,各个实例是相互隔离的而已。
更深一点发现可以用google的工具k8s来管理docker集群,让各个实例通过强大的机制实现资源调度汇聚起来。
这篇文章我们先用普通初学者的视角来了解下单机版docker的那些事。
简介
docker是用go语言开发的,想替换现在的虚拟机概念,想用户以后不要用虚拟机了,直接使用docker服务,但是docker不是虚拟机。
我们知道可以在linux上面的某个目录部署一些必须的shell环境,然后用户就可以用chroot命令到那个目录,就像到了一个没有自己的内核的新系统一样。docker就像是chroot的加强版,另外多了些网络之类的组件,让用户可以轻易理解为这个是一个虚拟机。
从上面的描述可以了解docker的特点,启动快、资源占用少、迁移方便,可以认为更高效地利用系统资源,不过docker的宿主机系统推荐是centos7或者Ubuntu。
想在线体验docker可以到这里https://labs.play-with-docker.com/。
2.1 构成
Docker 包括三个基本概念:镜像(Image)容器(Container)仓库(Repository)
镜像
镜像包含操作系统完整的 root 文件系统,可以用chroot切入,由于主打轻量型,所以一般的镜像都是很精简,几兆到百多兆的样子,而且由于镜像是切割来存储的,所以各个镜像之间可以复用一定的存储空间。
注意镜像是静态的,如果实例结束并被清理掉的话,之前在镜像里面留下来的东西就全部没了,除非启动时候有进行额外的挂载或者文件保留的参数。
容器
容器就是我们说的docker实例了,可以认为是个小虚拟机。一般会用
1 –v 物理机路径:容器路径
这样来挂载宿主机的文件或者目录来方便进行文件管理。
仓库
仓库就是存放docker镜像的地方,常用的操作命令:
2 #查找网络上的镜像3 docker serach centos4 #下载镜像5 docker pull centos6 #查看本地镜像,可以查看镜像对应的REPOSITORY7 docker images
进行镜像搜索下载的时候会去https://hub.docker.com这个官方地址,但是我们也可以搭建私有的仓库地址harbor来满足我们的存放需求,有个点就是官网的东西比较规范,比如https://hub.docker.com/r/library/mysql/,可以在上面看到很详细的使用方式或者dockerfile源文件,用来熟悉语法有比较大的帮助。
2.2 命令行
centos7上面的docker主配置文件在启动服务这里:
8 /usr/lib/systemd/system/docker.service9 #配置几项仓库地址和监听的文件或者端口即可:10 ExecStart=/usr/bin/dockerd --registry-mirror=http://docker-mirrors.gz4399.com --insecure-registry=http://hub.gz4399.com --data-root=/data/docker/docker -H unix:///var/run/docker.sock -H 0.0.0.0:5566
然后有个json文件可以进行一些配置:
11 etc/docker/daemon.json 命令行操作常见的还有如下命令:12 #运行本地镜像13 docker run -it [REPOSITORY] bin/bash14 #查看正在运行的实例,可以看到对应实例的CONTAINER ID15 docker ps -a16 #从当前状态保存成一个新的镜像17 docker commit [CONTAINER ID]18 #对镜像进行tag打标签19 docker tag [REPOSITORY] [new tag]20 #启动已退出的镜像21 docker start [CONTAINER ID]22 #查看镜像详细信息23 docker inspect [REPOSITORY/CONTAINER ID]24 #删除已退出的docker实例25 docker rm [CONTAINER ID]26 #删除本地镜像27 docker rmi [REPOSITORY]28 #进入正在进行的实例29 docker exec -it [CONTAINER ID] bin/bash
基本包含了运维层常见的动作了。
小案例
docker精神主打轻量快速部署,把产品和程序在docker虚拟机里面部署好之后,保存为一个镜像或者镜像的编译文件(Dockerfile)就是一个docker成品了,别人要使用就直接导入或者build启动即可,比以前的“一键部署”更智能。下面举几个得益于docker的小例子。
3.1 vulhub渗透
使用Vulhub一键搭建漏洞测试靶场,项目官网:https://vulhub.org
对运维安全人员来说vulhub这个环境特别好用,而且也是docker化一个很好的案例。

使用起来很简单,先下载,然后使用docker-compose这个编排工具会根据对应的docker-compose.yml自动生成整个环境,然后启动即可。
3.2共同开发
当团队多个开发人员在一台机器上进行开发的时候,多少会有些变量端口冲突之类的,比如在开发php过程中,同一个域名测试环境hosts的IP不一样,这样就造成互相混淆,如果用docker启动多个php实例就可以好地解决这个问题,这样比每个人都申请一个openstack虚拟机更便捷。
由于是开发环境,需求也是一直在变化,但是针对一个启动好的实例进行修改的话会很麻烦,所以我们在启动docker实例时候尽量把参数都带齐,比如需要改挂载的目录、hosts和ip互联信息等,临时解决些需求倒是可以通过进入实例进行操作或者在宿主机用iptables进行网络手动管理,但是稳定之后都需要重新提交好镜像以备下次复用。
3.3小游戏
像这个网易的小游戏镜像
下载网络上公开的镜像,一般含有Dockerfile文件比如
30 git clone git@github.com:bingohuang/play-docker-images.git31 #进入stage-01文件夹,然后进行编译32 docker build .33 #编译完之后会生成docker镜像,然后把镜像重命名:34 docker tag d3cdbaf2ef11 game135 #然后就可以启动,直接是一个游戏已经启动好了:36 docker run -it -p 1989:80 game1
不需要关心细节,产品直接出来了。

虽然小的不能再小的游戏了,但是这个就是docker实例的一个缩影(免搭建运维)。
3.4零碎应用
很多应用可以直接在docker官网pull下载下来直接启动即可,比如grafana这个监控平台、redmine等常见的企业应用,就像在iPhone上面直接在AppStore点击安装就安装好可以使用了。同时现在github上面很多开源软件也加了docker的支持,比如在根目录提供了Dockerfile这个文件供开发者自己编译对应的docker镜像,也保持了开源自定义的特性。
3.5安装特殊软件
这里说的小命令是指那种yum安装不到的或者不想去源码编译的东西,docker为这种情况又提供了很大的便捷性。
比如python3,需要用到python3命令,但是没法直接安装,这个时候可以直接docker pull python:3.4-alpine3.7下载,如果是测试脚本的话再直接-v进行目录挂载即可。

说python3可能很少人用到,但是在手游时代应该很多人用过apktool.jar这个apk的编译工具,默认centos6上在编译时候会提示GLIBC_2.14 not found,也就是需要重新安装新版本的glibc,但是glibc是比较底层的东西,能不动就不要去动,很折腾,这个时候可以用docker安装个java镜像就快速解决了,而且包含到了GLIBC_2.18版本。

不过因为单独集成了glibc等多个库,这个java镜像比较大。
下载镜像时候默认是下载latest版本,如果下载其余版本可以先到这个https://hub.docker.com/_/java/ 官网查看对应镜像的tag,然后指定下载即可。
3.6测试多版本
如果需要测试某个软件多版本的问题也很好做,比如redis和php的各个版本差异测试。还有各种各样的Ubuntu版本也可以直接在centos上面直接pull下载下来启动,偶尔碰到需求需要在不同版本测试东西的时候,这个是很快的方案。docker官网提供的基础镜像都是很精简,一个系统下载下来才一百兆左右。
不只是应用的多版本,如果是lib库的多版本也可以用docker做好各个依赖的相互隔离,就像上面说的glibc库问题。
使用问题
4.1时间问题
官方镜像基本上都默认是 UTC 时区。docker实例里面的系统时间和物理机是一样的,而且无法修改,最多只可以修改时区,通常为了解决时区问题,要在创建(运行)容器的时候加上(例如中国上海时区)
37 -e TZ=Asia/Shanghai
或者挂载宿主机的 " etc/localtime" 文件来保持时区一致,时间无法直接修改,但是可以用libfaketime这个库来欺骗修改下时间。
库地址: https://github.com/wolfcw/libfaketime/
简单编译之后,把libfaketime.so.1文件复制到docker实例,然后运行以下命令:
38 export LD_PRELOAD=/libfaketime.so.1 FAKETIME="+100"
即可达到和真实时间偏差快100秒的效果。
4.2IP网络问题
docker实例默认使用的是私有的网段,需要访问里面服务时候通过映射端口出来,但是如果想让实例使用物理IP,比如我们办公网想当做虚拟机来使用,就可以用macvlan网络来实现。
39 docker network create -d macvlan --subnet=172.16.0.0/19 --gateway=172.16.0.1 -o parent=eth0 gitlab-net 40 --subnet: 指定网段(宿主机) 41 --gateway: 指定网关(宿主机) 42 parent: 注定父网卡(宿主机)
接下来创建容器指定网络即可
43 docker run --net=gitlab-net --ip=172.16.0.170 -dt --name test centos:7
--net 指定使用的网络,--ip 用于指定网段内 IP;启动后只需要在容器内启动程序测试即可,注意centos6上面的不支持指定IP。
针对网络这块,如果集群同默认那样直接用nat的方式应用到线上,必然是个大问题,因为我们现在openstack的云平台就碰到了包量的问题,现在是用sr-iov技术来临时解决。
4.3私有仓库
针对私有仓库的管理可以使用vmware提供的harbor来做,安装也是很docker化,下载源码之后利用docker-compose编排工具进行全自动化编排,因为里面包含各个需要互联的docker实例,所以需要docker-compose.yml这个配置文件来进行编排自动化管理。
需要可以在内部团队共享镜像的当然得用私有仓库,虽然harbor有基本的功能,但是用起来感觉还是有些薄弱。界面如下:

命令行用起来的话需要下载harbor客户端才方便,可以下载python版本的harborclient,安装好之后配置HARBOR_URL、HARBOR_USERNAME、HARBOR_PASSWORD变量即可进行常规的镜像仓库搜索操作。
harbor命令如果有No module named 'requests.packages.urllib3'报错可以通过执行pip install requests urllib3 --force –upgrade升级python库修复。
4.4图形化管理
docker提供了很多api,所以有很多个图形化的东西来管理,但是简单易用的web界面暂时是推荐用portainer。

支持常见的一些操作和性能监控。而且支持本地或者远程docker管理,只需要docker在启动时候添加端口监听就可以了。
比如可以在这个web里面创建数据卷、网络、然后对各个docker实例进行操作和查看详细信息,比较强大。
这里有个有趣的现象,一些常见的docker工具本身也是个docker镜像,比如这个portainer和之前的harbor仓库,是不需要进行特殊的搭建配置,直接pull搜索下载下来启动就可以了,虽然有些便捷,不需要解决额外的依赖(傻瓜化),如果按照传统IT人员的思路,估计会有点懵。
4.5安全
docker的安全性相对openstack来说要弱一些,因为和宿主机共用的内核,所以宿主机的内核提权漏洞是可以在docker实例里面测试并进行逃逸影响到宿主机,不单是内核漏洞,普通的docker实例互通的安全隐患也会比vmware之类的大一些。
资源限制这块,docker也可以做,但是默认没做,默认是尽量使用宿主机的资源,所以可以df看到磁盘大小是宿主机的磁盘之类的,也可能某个实例占用大额的cpu和内存让其余的实例感觉到卡顿。事实上可以通过cpuset、memory和dm.basesize等参数来进行调控。
还一个就是宿主机的iptables内容得注意不可以随意修改,会影响到docker的网络通讯,如果不小心覆盖了docker生成的规则之后怎么恢复也暂时没有很好的办法。
小结
如果对docker有点茫然的话,建议先当作轻量型的虚拟机来练练手,有瓶颈了再进行高级利用,一个docker实例代表一个进程,进程退出实例就结束了,甚至还需要跑一个tail的空命令来保持容器的运行状态,这种思想估计还需要一点时间去适应。虽然有时候docker能帮上忙,到线上大肆铺开的话最起码要先把Kubernetes集群和各种后台化做好,把各种坑踩好。
虽然docker比较新颖,也有大厂家在推动,但给现有的运行环境再加个运行环境容易出问题的地方也增多了。我们大部分环境还是跑在现在比较自动化的web管理阶段,弹性资源管理和交付已经比较成熟,还一个就是我们对虚拟机的资源配额粒度需求并不大,优先保证业务的稳定性,并不打算为了使用docker而使用,毕竟重新做一整套发布流程也是个大工程。虽然centos7和python3已经出来很多年了,但还在centos6上用python2做开发的运维哥们也表示“服”。
近期文章
END
全中国只有不到1% 的人关注了运维军团
你是个有眼光的人!
(由于交流群人数已超100人,需要进群的小伙伴可以添加运维小编的微信:)

如果你喜欢我们的文章,请转发到朋友圈










