作为软件开发者,平常最痛恨的应该就是环境配置问题了吧。比如说,我要在一台新电脑(新环境)上安装tomcat跑一个javaweb应用,因为tomcat是java代码编写的,所以首先我要安装一个java运行时环境(JRE),配置JAVA_HOME,然后才能安装tomcat开始跑javaweb。还有,如果我要学习一门新的语言go、或新的中间件RabbitMQ、可能花费在安装这些环境的时间就让你想放弃了。
而作为运维人员,平时肯定也为部署新环境折腾得焦头烂额,一下子要为好几台新机器配置运行环境,每台机器上执行相同操作,十分机械化。
知道了平时开发中的痛点,那是否有一种工具,能让我快速安装tomcat而不用去理会环境问题。能让我把go、RabbitMQ整个环境下载下来,不需任何配置,我就能在这个环境中直接运行go代码。能让我配置了一台机器后,原样复制一份,发到其他机器直接运行,不用再做配置就可以得到相同的环境?是有这种工具的,它就是虚拟化容器技术,而docker,就是这门技术中的佼佼者。
1. 什么是docker
docker是一门虚拟化容器技术,其设计理念是"build once, run anywhere"(一次构建,到处运行),听起来,是不是跟java的"wirte once, run anywhere"(一次编写,到处运行)很像?那么,什么是虚拟化容器技术呢?docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器,程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。正如开篇第一张图docker的标志一样,docker就是这条鲸鱼,其上驮着的集装箱,就是一个个互相隔离的容器,你可以随时往上添加集装箱,不会影响到原有集装箱里的内容。
2. docker和虚拟机的区别
docker 和传统虚拟化方式的不同之处,传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,共享宿主机的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
[图片上传失败...(image-926fd8-1572257136481)]
3. 安装docker
docker可以在各个操作系统上安装,过程很简单,安装教程请看这里:https://www.runoob.com/docker/windows-docker-install.html。
docker在windows上安装是一件麻烦事,但不想在vm虚拟机中的linux上安装因为懒得开,所以还是在windows上安装了,windows上有两种安装方法:
- docker toolbox:这个安装包适用于所有windows版本(windows xp的当我没说),包括win7, win8, win10家庭版。我就是安装的这个版本
- docker for windows:这个版本适合win10专业版,因为win10专业版带有Hyper-v虚拟化功能,安装前需要开启该功能,具体看上面的安装链接。
3.1. 安装docker toolbox遇到的问题
这是安装docker toolbox遇到的卡在下载boot2docker.iso的问题,安装docker其他版本的这节可以忽略不看。
docker toolbox安装完成后,会有如下三个图标,
[图片上传失败...(image-6ed3d3-1572257136481)]
启动docker需要点击Docker Quickstart,其会查找指定目录下的boot2docker.iso(一个轻量级的linux虚拟机)文件,并根据该文件创建一个名为default的linux虚拟机,初次点击时找不到该文件,会从github下载,但docker下载速度相当慢,等了个把小时都无法完成。提示如下:
Running pre-create checks...
(default) No default Boot2Docker ISO found locally, downloading the latest release...
(default) Latest release for github.com/boot2docker/boot2docker is v1.12.1
(default) Downloading C:\Users\huang\machine\cache\boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v1.12.1/boot2docker.iso...
解决方案是:使用浏览器(或者迅雷)到boot2docker的主页下载最新版boot2docker.iso,地址:(https://github.com/boot2docker/boot2docker/releases),如下图:
下载完成后断开网络,将下载好的boot2docker.iso放到提示的位置,我这里是:
C:\Users\huang\machine\cache\
目录。记住要断开网络,重新点击Docker Quickstart图标启动docker即可,启动完成即可连接网络,开始学习docker了。
3.2. boot2docker
对boot2docker感兴趣的可以看看其github的介绍,boot2docker是一个轻量级的、用于运行docker容器的linux系统,完全在内存中运行,大小只有45m左右,启动迅速。所以在windows中运行docker,其原理是使用启动了一个linux虚拟机,该虚拟机中安装了docker,点击Docker Quickstart后,我们可以看到控制台的输出,该虚拟主机名为default,默认的ip是192.168.99.100。再从github中的介绍可以看到,该虚拟机有docker用户,密码为tcuser。因此,我们可以从secureCRT或者git bash中使用ssh登录到该机器,在上面使用docker命令。当然你可以在default虚拟机中安装vim等工具,但是由于其是内存操作系统,重启后这些新安装的工具都会消失。
远程登录命令:
ssh docker@192.168.99.100
# 密码
tcuser
3.3. docker阿里云镜像加速
这一节可以暂时不看,等你觉得docker下载太慢时,可以看我的另一篇文章,配置镜像加速,地址为:https://www.jianshu.com/p/aff1a4a471de
4. docker架构
这里我想先从docker的架构图和几个重要的概念说起,最后再说具体的命令,这样方便大家知道每一条命令的意思和执行过程。看完这篇文章后 ,推荐一个docker教程,不长,链接在文章最下方的参考资料。
[图片上传失败...(image-ccd01f-1572257136481)]
如上图,docker采用的是C/S架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。客户端和服务器可以运行在同一个Host上,客户端也可以通过socket或者REST API与远程的服务器通信。对照上图,涉及到的概念如下:
- Client:docker客户端,最常见的客户端就是docker命令,如docker build、docker pull、docker run等,通过这些命令我们可以方便的在host上构建和运行容器。
- Daemon:docker deamon是服务器组件,以linux后台服务的方式运行。docker daemon运行在宿主机docker host上,负责创建、运行、监控容器,构建、存储镜像。
- image:镜像,可将镜像看成只读模板,通过它可以创建docker容器。正如Java中了.class文件,通过.class可以创建出类的实例。镜像是层叠的,最底层就是linux内核,每添加一个文件或者操作都会在原来的基础上叠加一层,如JDK环境叠加在linux内核之上,tomcat又叠加在JDK环境之上,此时如果你的docker中已有JDK镜像的话,就只需下载tomcat这层即可。因为镜像是只读的、共享的。
- container:容器,docker容器就是docker镜像的运行实例。
- registry:registry是存放docker镜像的仓库,我们可以将自己的镜像推到远程,或者从远程下载镜像到本地运行,正如github。docker官方有一个docker hub,我们可以从上面下载官方的镜像。如,下载一个官方的tomcat镜像,直接运行该镜像即可启动tomcat,不需任何配置。
综上,结合上图,整个docker架构交互流程为:启动docker,docker以守护进程的方式运行在linux主机上(docker toolbox下为boot2docker虚拟出来的linux上),我们发送docker命令给到docker daemon执行,docker可以从docker hub中拉取所需要的image,再根据image创建出container。
5. 实战
知道了上面docker架构的交互流程了,我这里以运行一个tomcat容器为例,一步步介绍常用的命令:
-
docker images
:列出当前docker中有哪些镜像,如果是第一次执行,当然就没有镜像了。 -
docker search tomcat
:在docker hub中搜索tomcat镜像。当然你可以在浏览器中访问docker hub,地址为:(https://hub.docker.com/),就像访问maven的远程仓库一样,可以搜索你需要的内容。
-
docker pull tomcat
:拉取最新版的tomcat镜像到本地,下载完成后再使用docker images就能看到感下载的镜像了。 -
docker run --name mytomcat -p 8080:8080 -d tomcat
:根据tomcat镜像运行出一个tomcat实例,执行两遍就有两个实例了(注意改端口),--name表示为这个实例命名,-p 8080:8080表示将本地的8080端口绑定到容器中的8080端口,才能使用localhost:8080(docker toolbox是192.168.99.100:8080)访问到tomcat端口。-d表示后台运行。 -
docker run --name mytomcat03 -p 8082:8080 -it tomcat /bin/bash
:-it以交互、附加模式启动并进入容器后执行/bin/bash命令,不以后台运行,进入容器后执行exit命令后,会退出容器,此时使用docker ps -a命令查看会显示为exit状态。 -
ctrl+p+q
:退出但是后台运行,如上一个命令,执行exit退出后容器就会退出,此时若不想容器退出,可按这一组快捷键。 -
docker ps -a
:显示所有容器状态,docker ps只显示运行中的容器,-a表示显示所有容器,包括已退出的容器。这时就能看到刚刚启动的tomcat了。 -
docker logs -f mytomcat
:查看刚刚启动的tomcat打出来的日志,-f表示跟踪滚动日志打印。 -
docker exec -it mytomcat /bin/bash
:exec表示执行命令,命令最后需要带将要执行的命令,如/bin/bash,-it表示以交互、附加模式启动返回一个终端,/bin/bash表示进入容器后首先执行的命令。这条命令执行后就登录到了容器内部,该容器中就是tomcat应用。就像使用ssh登录到容器内部一样。这时候你可以修改容器内部的配置文件,当然,生产环境不建议这么做,而是使用配置文件外部挂载的方式。 -
docker stop mytomcat
:停止mytomcat实例,不会删除容器内的东西。 -
docker start -i mytomcat
:启动已停止的mytomcat实例,如果启动前修改了容器内的配置文件,此时重新启动会重新加载该配置,如果该配置文件是linux宿主机级别的,如/etc/profile文件,则不会加载,因为容器是共享宿主机的配置的。-i表示启动并进入交互命令界面。 -
docker rm mytomcat
:删除已停止的mytomcat实例 -
docker run --name mytomcat02 -p8081:8080 -e JAVA_HOME=/path/to/java/home -v /host/path/file:/container/path/file -d tomcat
:-e表示设置环境变量JAVA_HOME,进入到容器中,使用echo $JAVA_HOME可以看到该环境变量的值。-v表示挂载宿主机的/host/path/file到容器中的/container/path/file,修改宿主机的文件时,容器中的文件也会修改。如果使用的是docker toolbox,则宿主机挂在的文件需要在当前用户目录下,即c:\user\yourname下才行,否则不会报错但无法挂载成功,当时被这个问题坑了一个下午。 -
docker cp /host/path/file mytomcat02:/container/path/file
:复制宿主机文件到容器中,可以用于当修改了容器配置文件后,配置文件错误导致无法启动时,复制配置文件到宿主机修改配置,然后重新复制回容器即可。 -
docker inspect mytomcat
:查看容器信息,包括容器ip等信息。
6. 构建docker镜像
假如我们下载了tomcat镜像并启动了容器实例,并在tomcat容器中修改了配置文件。这时,我们可以把配置文件也一起打包做成镜像,发到另外的机器直接执行,就不用再单独对每一台机器配置了。docker提供了两种方式来构建镜像,如下:
- docker commit:通过容器构建
- docker build:通过dockerfile文件构建
dockerfile文件方式构建需要编写dockerfile,也只有几个命令,不难,请自行查阅资料。此处讲下docker commit命令。
docker commit mytomcat huangzb/tomcat
:将当前的mytomcat容器提交为镜像,镜像名为huangzb/tomcat
7. 容器的网络结构
熟悉docker的网络结构是相当重要的,因为这样我们就可以做集群啦。废话不多说,那就直入主题吧。
docker的网络使用了linux网络中的bridge(网桥)和veth(virtual ethernet虚拟以太网)虚拟设备。
- bridge:网络桥接器,简称网桥,普通的网桥只有两个接口,连接两个网络,工作在二层(数据链路层),只要有mac地址就能转发数据包。而linux得虚拟bridge有多个接口,并且能配置ip,更像一个路由器。安装完docker后,在宿主机中使用ifconfig命令,可以看到网络配置中出现了docker0网络。docker0就是docker设置的linux虚拟网桥。
- veth:virtual ethernet是linux中的虚拟网络设备,其像一条两端有网卡的线,可以将两个设备连接起来分别配置ip地址。
[图片上传失败...(image-b672e-1572257136481)]
因此,在我windows下docker toolbox中的网络如下图。
[图片上传失败...(image-3f9661-1572257136481)]
7.1. 容器间互联
由上,docker中新建的容器默认都使用了docker0网桥连接了起来,所有默认的,docker创建的所有容器都在一个网络中,互相可以访问。
以上。有兴趣的同学可以学习下面的参考资料。