软件测试 | 掌握高频 Docker 命令,夯实内功基础
获取更多相关知识

本文为霍格沃兹测试学院学院学员 Docker 实战课程学习笔记,供各位同学参考。公众号搜索:TestingStudio 霍格沃兹的干货都很硬核
在 Dokcer 横空出世之前,应用打包一直是大部分研发团队的痛点。在工作中,面对多种服务,多个服务器,以及多种环境,如果还继续用传统的方式打包部署,会浪费大量时间精力。
Docker 和虚拟机
在 Docker 出现后,它以更高效的利用系统资源、更高效的利用系统资源、一致的运行环境、持续交付和部署、更轻松的迁移、更轻松的维护和拓展,6 大优点迅速火了起来。
Docker 的基础命令,堪称 Docker 的内功,只有把内功修炼好了,我们在 Docker 的学习路上才会更加顺畅,不会导致“走火入魔”。
接下来我将从与虚拟机的对比开始,以实战的方式,带大家更加了解,更会“玩” Docker。

-- 左边为虚拟机,右边为 docker 环境 --
Server
:物理机服务器Host OS
:构建的操作系统Hypervisor
:一种虚拟机软件,装了之后才能虚拟化操作系统Guest OS
:虚拟化的操作系统Bins/Libs
:执行命令、工具App A
:构建的软件Docker Engine
:跳过虚拟化内核的步骤,直接使用宿主机内核
从图片中我们可以清楚的了解到,相比于 Docker,虚拟机更加的臃肿。
虚拟机和容器都需要物理机以及操作系统,但是虚拟机有 Hypervisor 层以及 Guest OS 层。但是 Docker 是没有这两个部分的,只有一层 Docker Engine。
并且每个容器都和宿主机共享计算机的硬件资源以及操作系统。那么由 Hypervisor 带来的资源耗损,在容器这边是不存在的。所以 Docker 与虚拟机对比,是有很强大的优势的,当然,也会有一定的缺点。
优势(省去了虚拟化内核的步骤)
节省资源(CPU、内存)
秒级启动
轻量级方案(同样一台服务器可以启动几百个 docker,但是不能启动几百个虚拟机)
劣势
隔离性、安全性相比虚拟机更弱(比如,如果其中一个容器将内核给"搞坏了",那所有的容器就都无法正常工作了)
某些情况下服务器会挑内核(eg.编译 c++)
Docker 加速器配置
Docker 的作用
而对于测试人员,Docker 又为我们带来了什么样的便利呢?
搭建测试环境
搭建各类基础服务
搭建测试执行环境(自动化测试脚本执行环境)
加速器配置
在刚开始的时候,由于网络的原因,我们在下载的镜像的时候,常常速度是非常慢的。所以如果下载镜像很慢的同学,可以尝试配置国内的加速器加速镜像下载
登录阿里开发者平台:dev.aliyun.com/search.html
点击“创建我的容器镜像”
注册/登录后,进入 Docker 镜像仓库,选中加速器 Tabcr.console.aliyun.com/#/imageList
根据个人需要, 选择运行 Docker 的 OS,按照要求修改 Docker 配置文件。
步骤如下:
修改配置文件 :vim usr/lib/systemd/system/docker.service
添加红色部分到"ExecStart" ExecStart=/usr/bin/dockerd --registry-mirror=<your accelerate address>
保存文件
Docker 实战
好记性不如烂键盘,单单只背下来 Docker 的命令是不够的,还要自己多敲多去练习,才能更熟练、更深刻的掌握 Docker。
用 Docker 搭建 Jenkins 服务
大家一起勤动小手,通过搭建一个 Jenkins 环境,去熟悉 docker 命令哦
(一定要仔细阅读官方镜像的文档)
下载镜像
docker pull jenkins/jenkins

查看已下载的镜像
docker images
我们可以看到刚刚下载的 Jenkins 镜像

那么,其中的每个字段又是什么意思呢?
删除镜像
docker rmi jenkins/IMAGE ID
我们可以看到,Jenkins 镜像已经被成功删除了

下载指定版本的镜像
docker pull jenkins:3.1.x
此时我们可以发现,镜像的 TAG 不再是 latest 而是我们所指定的版本号

将镜像打包成一个 tar 包
docker save jenkins:2.60.3 > myjenkins.tar
图片
将打包的镜像加载出来
docker load < myjenkins.tar

给镜像加 tag 号
docker tag jenkins:latest jenkins:3.6.0
打了 tag 之后,会发现多了一个 3.6.0 tag 版本的镜像,但是 image ID 和原本的保持一致

然后我们删掉这个镜像,发现提示 untagged,且这个镜像被成功删除

给镜像改名称
docker tag jenkins:latest testjenkins
然后我们就可以看到,多了一个叫做 testjenkins 的镜像,但是 image ID 和原本的保持一致

push 镜像到镜像仓库
容器相关命令及使用
容器运行命令参数
容器管理命令参数
接下来我们继续使用 Jenkins 进行一个实战的演练
docker ps 也是我们常用的一个命令,下面是 docker ps 后显示的启动容器信息,其中每个字段都有自己的含义

如何删除这个启动的容器呢?是否可以和镜像一样,直接 rm 呢?docker rm myjenkins
从图中我们可以看到,如果直接删除运行中的容器会报错,需要先 stop 然后删除

或者直接docker rm -f myjenkins
我们从图片中可以看出,虽然这个容器是启动的状态,但是使用 docker rm -f 依然可以直接删除

在 docker ps 的时候我们可以看到,PORTS 字段下面显示了两个端口号,这两个端口号是做什么的呢?
其实呀,这两个端口号,是容器故意对外暴露的端口号,我们可以通过端口映射的方式,使容器内部的端口号与宿主机的某个端口号产生链接。这样我们就可以通过端口号,去访问或者操作容器啦

如何指定端口号呢?就是使用 -p 参数
docker run -d --name=myjenkins -p 8080:8080 jenkins/jenkins
将宿主机的 8080 端口指向容器的 8080 端口,这样我们在宿主机的 8080 端口就可以访问到 Jenkins 啦

在启动的过程中,我们可能会碰到各种各样的问题,我们如何定位问题呢?当然是使用查看 log 大法docker log -f myjenkins

Docker 的数据持久化学到这里,可能有同学会有疑虑啦,如果 docker 挂掉,在 docker 内产生的数据应该怎么办呢,这些数据应该如何保存呢接下来,我们要了解的,docker 是如何进行数据持久化的呢?
当我们启动容器时,添加了数据挂载的参数-v 宿主机_path:container_path,docker 就可以通过数据挂载的方式,使容器和宿主机的数据进行同步保存,

接下来我们通过实战的方式,就可以看到 docker 是如何实现这一功能的
启动 Jenkins,要增加-v 挂载卷参数
docker run --name myjenkins -itd -p 8001:8080 -v /home/gaofei/test/jenkins_home:/var/jenkins_home
注意:挂载权限:sudo chown -R 1000:1000 /home/docker/jenkins
使用 docker exec -it myjenkins bash 进入刚启动的 jenkins 容器,并 cat /var/jenkins_home/secrets/initialAdminPassword 这一步是为了找到 jenkins 的启动密码


输入密码,进入 Jenkins 页面创建一个 job。

删掉容器,重新执行之前的命令,重启 Jenkins,进入页面,发现 job 没有因为容器被删而丢失


注意:如果容器无法成功启动,且 log 提示权限问题,则在启动命令中添加-u 0
Docker 容器交互docker exec -it {容器名称} bash
进入容器,exec 的意思是在容器中运行一个命令。如果使用 bash 并且指定了-it 就会打开容器的 shell 交互

docker cp {container:name}:{container_path} {host_path}把宿主机上的一个文件 copy 到容器中
docker cp 1.sh myjenkins:/var/jenkins_home

Docker 的环境变量有一些容器启动时,我们需要给他添加一些初始的参数,比如 mysql,我们需要给他添加一些初始的账号和密码,docker 如何操作这种情况呢?让我们动动小手,演练一下吧
启动 mysql 容器,注意要加-e 传递参数
docker run --name some-mysql -v /home/gaofei/test/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=1qaz9ol. -p 8888:3306 -d mysql:5.5
通过数据库连接工具连接数据库 host 要填写宿主机的 ip 地址,Password 是我们一开始设定的端口号填写映射的宿主机的端口号

在数据库中创建一个表

删掉容器,然后重启
进入刚刚创建的容器内的 mysql 路径下,发现有刚刚添加的表,这个就是容器的数据持久化的功能啦

我们接下来再思考一个问题,因为容器是有隔离性的。如果容器之间互相链接可以用什么方式?
这里就要引入另外一个参数啦 --link,这个参数的作用就是把一台容器的网络信息,注入到另外一台容器中
老方法,我们还是通过 testlink 实战,体验一下这个功能吧
启动 mariadb
启动 tesklink,mariadb 的信息注入到 testlink 容器中
查看日志,可以看到成功连接到 mariadb

一个思考题,如果是三个容器需要连接呢,使用什么样的方式?答案是:--env 因为在 docker 中,--link 就是通过环境变量的方式配置的。
Docker 前后端启动现在很多网站的架构都是前后端分离,在这种情况下,我们应该如何使用 docker 分别启动前端和后端,且能互相通信呢?我们可以使用下面的命令
--net=container:conan:这样创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围。
其他命令
查看 docker 的信息docker info
获取容器/镜像的元数据docker inspect myjenkins
以上,我们通过实战的方式了解了 docker 的概念,熟悉了 docker 的一部分基础命令,看完文章后,就要熟悉练习了哦。下一次,将带大家通过 3 个实战练习 selenium、prometheus+grafana、mysql 的监控,带大家了解 docker 的招式法门,学会之后,我们就可以真正的带入工作,进行实战了。
获取更多相关知识
版权声明: 本文为 InfoQ 作者【测试人】的原创文章。
原文链接:【http://xie.infoq.cn/article/3d6f2699cb5f8f6686388d6c9】。文章转载请联系作者。
评论