Docker
- Docker简介
- Docker与Tomcat有什么区别?
- Docker与虚拟机有什么区别?
- Docker的基本组成
- Docker的联合文件系统
- Docker基本命令
- Docker中的几个重要组件
- 一、容器数据卷
- 二、Dockerfile
- 三、Docker网络
- 虚拟机共享网络的三种方式
- Docker共享网络的四种方式
- Docker中建立一个虚拟网络
- Docker应用:建立一个redis集群
- 引用
Docker简介
Docker 是一个开源的应用容器引擎,Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。传统模式中,开发人员只需要对Web应用打包一个jar包放入linux服务器就可以,它可能需要使用很多环境(Redis,Mysql,JDK等等),这些环境会有运维人员进行配置(费时费力)。Docker就是提供一个镜像(我们可以将jar包及其环境一同打包放入Docker仓库),这样我们不管是将项目由Windows部署到Linux,或者其他人员想在他们的机器上运行我们的项目只需下载这个镜像即可。
Docker与Tomcat有什么区别?
- docker 是容器,tomcat是(servlet)jsp应用服务器
- tomcat可以安装在物理机上,虚拟机上,也可以安装在Docker上。所以从这个角度讲,Docker也可以看做是一种超轻量化的虚拟机。
- Docker可以安装在物理机,虚拟机上,但不知道Docker上面是否可以再安装Docker,我觉得理论上应该可以。
- Docker作为超轻量级的平台,可以整体移植,这也是它流行的其中一个原因。
Docker与虚拟机有什么区别?
Docker只包含项目运行的核心镜像(jar包+依赖环境 只有几MB),而虚拟机包含一整个系统(Centos 几十GB);
虚拟机:
我们传统的虚拟机需要模拟整台机器包括硬件,每台虚拟机都需要有自己的操作系统,虚拟机一旦被开启,预分配给他的资源将全部被占用。每一个虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。
Docker:
容器技术是和我们的宿主机共享硬件资源及操作系统可以实现资源的动态分配。
容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行。
Docker容器代替了Hypervisor与虚拟系统,实现进程和资源的隔离
Docker的基本组成
- 镜像:Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。
- 容器:Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。事实上容器就是一个可读可写的镜像文件。
- 仓库:集中存放镜像文件的场所。仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
Docker的联合文件系统
联合文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。
比如对于不同的linux发行版本Debian和BusyBox。他们都拥有两个文件系统分别时BootFs和RootFS。BootFS 主要包含BootLoader 和Kernel, BootLoader主要是引导加载Kernel, 当Boot成功后,Kernel被加载到内存中。RootFS包含的就是典型 Linux 系统中的 /dev、/proc、/bin 等标准目录和文件。他们的BootFS大体一致,RootFS稍有差别,所以他们可以使用联合文件系统共享BootFS。
Linux在启动后,首先将RootFS 置为 Readonly,进行一系列检查后将其切换为Readwrite供用户使用。在Docker中,也是利用该技术,然后利用Union Mount在Readonly的RootFS文件系统之上挂载Readwrite文件系统。并且向上叠加, 使得一组Readonly和一个Readwrite的结构构成一个Container的运行目录、每一个被称作一个文件系统Layer。
如上图所示,两个linux发行版本共用了底层的BootFS,并在上层添加属于自己的独特模块。
所以我们可以看得出联合文件系统的优势:
• 多个Container可以共享父Image存储,节省存储空间;
• 快速部署 – 如果要部署多个Container,Base Image可以避免多次拷贝,实现快速部署。
• 因为多个Container共享Image,提高多个Container中的进程命中缓存内容的几率。
docker中将上层命名为容器层,下层命名为镜像层。对于我们使用pull命令下载的文件都属于镜像层,即我们无法对其进行修改,我们所做的修改操作(run命令)都会成为容器层添加到该层级之上。当我们使用commit命令将我们修改的文件提交时,它就合并为了一个新的镜像层文件。
Docker基本命令
Example:使用docker部署Nginx服务器
---- docker run -d --name hello-nginx -p 8085:80
-v 外部路径(主机):内部路径(容器) --volume-from 容器名 nginx
即我们启动一个名为hello-nginx的服务运行在后台,nginx默认运行在容器内80端口,我们将其映射到外部的8085端口。并且挂载容器路径下的对应文件夹/文件 到 外部路径下的对应文件夹/文件,实现二者的映射,这样,我们通过修改外部文件就可以修改容器内部的配置。最后我们将这个容器的目录与另一个容器相互共享,这样一来两个容器的数据将完全同步。
Docker中的几个重要组件
一、容器数据卷
数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器(二者的数据是同步的),类似于Linux中的mount操作。
- 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效方便;
- 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
- 对数据卷的更新不会影响镜像,解耦了应用和数据;
- 卷会一直存在,直到没有容器使用,可以安全地卸载它。
借由数据卷技术,比如我们在使用Mysql时,我们可以保证其储存的数据不会丢失。
我们通过建立容器时在后面加入-v命令实现挂载
匿名挂载: -v 容器内路径
具名挂载: -v 卷名:容器内路径 docker volume inspect 卷名 查看挂载具体信息
路径挂载: -v 主机路径:容器内路径 这里最好使用全路径避免出错
容器间挂载: --volume-from 容器名
二、Dockerfile
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
DockerImages是通过DockerFile的定义来生成相应的镜像。
DockerContainer是为镜像的运行提供运行环境。
常用Dockerfile关键字:
这里给出一个简单构建Dockerfile的例子:
- 我们建立一个文件夹,里面存放要放入镜像的内容(如readme.txt),镜像构造文件(DockerFile)以及想要放入镜像中的上层镜像文件。
- 编写一个简单Dockerfile
FROM centosMAINTAINER XXX<XXX@gmail.com>COPY readme.txt /usr/local/readme.txt ADD jdk-8u271-linux-x64.tar.gz /usr/local ADD apache-tomcat-8.5.61.tar.gz /usr/localRUN yum -y install vim //由于原centos镜像是阉割版,我们要为其安装自定内容RUN yum -y install net-toolsENV MYPATH /usr/local //定义我们的工作目录WORKDIR $MYPATHENV JAVA_HOME /usr/local/jdk1.8.0_271 //为引入的镜像配置环境变量ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarENV CATALINA_HOME /usr/local/apache-tomcat-8.5.61ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.61ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 //为Tomcat暴露其8080端口CMD /usr/local/apache-tomcat-8.5.61/bin/startup.sh && tail -F /url/local/apache-tomcat-8.5.61/bin/logs/catalina.out && /bin/bash //打开Tomcat并显示日志文件,注意如果不默认开启tomcat服务,则这个镜像没有默认运行的进程,docker run不会生效
- docker build 构建成为一个镜像
docker build -f dockerfile -t 新镜像名:版本号 . -----注意版本号可有可无以及最后要加个点 - docker run 运行镜像
- docker push 发布镜像
docker login ---登录Dockerhub账号(我们也可以通过阿里云容器服务提供的账号,将镜像push到阿里云服务器上)docker tag 原镜像名 dockerhub账户名/镜像名:版本号 ---重新生成一个带账户名和版本号的镜像docker push dockerhub账户名/镜像名:版本号docker logout ---退出当前账号
总结
Dockerfile构建全流程:
三、Docker网络
虚拟机共享网络的三种方式
- Bridged(桥接模式):虚拟系统和宿主机器的关系,就像连接在同一个Hub上的两台电脑。从网络技术上理解相当于在宿主机前端加设了一个虚拟交换机,然后宿主机和所有虚拟机共享这个交换机。
-----如果你想利用VMWare在局域网内新建一个虚拟服务器,为局域网用户提供网络服务,就应该选择桥接模式。 - NAT(网络地址转换模式):虚拟系统借助NAT的功能,通过宿主机所在的网络来访问公网。在这种模式下宿主机成为双网卡主机,同时参与现有的宿主局域网和新建的虚拟局域网,但由于加设了一个虚拟的NAT服务器,使得虚拟局域网内的虚拟机在对外访问时,使用的则是宿主机的IP地址,这样从外部网络来看,只能看到宿主机,完全看不到新建的虚拟局域网。
-----如果你想利用VMWare安装一个新的虚拟系统,在虚拟系统中不用进行任何手工配置就能直接访问互联网,建议你采用NAT模式。 - Host-only(主机模式):从网络技术上讲相当于为宿主机增添了一个虚拟网卡,让宿主机变成一台双网卡主机(宿主网卡+虚拟网卡)。同时在宿主机后端加设一个虚拟交换机,让宿主机和所有虚拟机构成另一个虚拟的局域网。由于具备双网卡,宿主机可同时参与两个局域网(现有的宿主局域网+新建的虚拟局域网),只不过缺省情况下两个局域网不连通。
-----如果你想利用VMWare创建一个与网内其他机器相隔离的虚拟系统,进行某些特殊的网络调试工作,可以选择host-only模式。
Docker共享网络的四种方式
- Host模式:容器使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。并且docker host上已经使用的端口就不能再用了。
- Container模式:指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。两个容器的进程可以通过 lo 网卡设备通信。
- None模式:Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
- Bridge模式:当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。Docker会在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。
Docker中建立一个虚拟网络
-
docker中所有容器默认加入docker0网络,即bridge网络
-
我们通过docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 net_5yw (使用桥接模式,建立了一个192.168.0.0网段,其中包含65536个子网,同时我们将这个网段的路由设置为192.168.0.1,并为这个网络命名为net_5yw)
-
之后,我们就可以通过docker run -d --name tomcatnet02 --net net_5yw 75b0d03def36 (将容器加入指定的网络,这里如果不声明,则会默认加入docker0)
这样做,有助于不同容器集群之间的网络隔离,提高隔离性与安全性,同时,同一网络下,我们可以使用容器名直接相互ping通(docker0还是只可以ping IP,只有自己配置的才可以ping容器名),而无需使用–link进行单独配置。 -
完成后,我们可以使同一网络下的容器相互连接(ping通)。
注:tomcatnet03在docker0(172.17.0.0),存在另一网络net_5yw(192.168.0.0)
docker exec -it tomcatnet03 ping 192.168.0.3 发现无法ping通
如果我们要实现不同网络相互连接,我们可以通过docker network connect net_5yw tomcatnet03
docker exec -it tomcatnet03 ping 192.168.0.3 此时已经可以ping通
此时,tomcatnet03同时存在于docker0与net_5yw中,并同时拥有两个网络下的IP地址。所以可以和两个网络下其他所有的容器通信
Docker应用:建立一个redis集群
- 建立脚本,创建6个redis.conf配置文件
for port in $(seq 1 6);
do
mkdir -p DockerMap/Redis/node-${port}/conf
touch DockerMap/Redis/node-${port}/conf/redis.conf
cat << EOF >DockerMap/Redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.72.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
-
使用建立好的配置文件在docker中开启6个redis-server
docker run -d
-p 6376:6379 -p 16376:16379 --name redis06 //配置其映射端口和名称
-v /home/ostrich5yw/Desktop/DockerMap/Redis/node-6/data:/data //挂载数据库以及配置文件
-v /home/ostrich5yw/Desktop/DockerMap/Redis/node-6/conf/redis.conf:/etc/redis/redis.conf
–net redisCluster --ip 172.72.0.16 redis redis-server /etc/redis/redis.conf //将其加入建立好的网络 -
建立集群
redis-cli --cluster create 172.72.0.11:6379 172.72.0.12:6379 172.72.0.13:6379 172.72.0.14:6379 172.72.0.15:6379 172.72.0.16:6379 --cluster-replicas 1 //末尾参数表示以1的比例划分主从节点
redis-cli -c //集群模式开启客户端
cluster info //查看集群状态
cluster nodes //查看集群节点
引用
本文根据遇见狂神说的Docker视频编写。