docker快速入门_docker 容器写代码


![在这里插入图片描述](https://img-blog.csdnimg.cn/0eabd2d93591444bb5d21a6d118efca9.png)


重启docker服务



systemctl restart docker


![在这里插入图片描述](https://img-blog.csdnimg.cn/438f7f239f8845969e9102d766b5eed5.png)


查看docker服务状态



systemctl status docker


开机启动docker服务



systemctl enable docker


![在这里插入图片描述](https://img-blog.csdnimg.cn/deb6f97e040840c2b3e12576aa23f4bf.png)


### 2.2、docker 镜像相关命令


查看docker全部命令



docker


![在这里插入图片描述](https://img-blog.csdnimg.cn/9ec65bca1efd47999f7433ad4c105636.png)


你会发现docker的命令基本都是docker打头  
 查看镜像(对于本地):查看本地是否有要搜索的镜像



docker images


![在这里插入图片描述](https://img-blog.csdnimg.cn/a9491159104540df84e5306d6d1cf250.png)


在什么都没安装的情况下:我们会发现docker为我们提供了一个helo-world的镜像。  
 我们来看一下它的属性:  
 REPOSITORY:装有软件及其它所需要的文件系统  
 TAG:版本号  
 IMAGE\_ID:镜像ID  
 CREATED:什么时候创建的  
 SIZE:大小  
 我们还可以在命令后加-q,查找仓库全部的image\_id  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e396f4334ffd4b5294eb815a1ee0d7fd.png)


搜索镜像(由于需要去本地或者远程仓库查找,所以需要网络)



docker search xxx


比方我找redis的镜像  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f8489d6727b04bffb7330228c95ed736.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


同样的,我们来看一下表头属性:  
 NAME:镜像名  
 DESCRIPTION:简介  
 STARS:类似github的欢迎数  
 OFFICIAL:是否为官方认证  
 AUTOMATED:是否自动构建的  
 拉取镜像  
 `docker pull xxxx(: xx)` 冒号后为版本号,不加则默认latest.


![在这里插入图片描述](https://img-blog.csdnimg.cn/b26a2298c8594352aa770361a1cfdf7c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5a347e0b9a4d4b919c7a5f33e6e3c26a.png)


可是有时我想要具体使用某个版本的docker,但又不知道docker仓库到底有没有我要的具体版本的镜像,怎么办呢?  
 我们可以去hub.docker.com去查找


![在这里插入图片描述](https://img-blog.csdnimg.cn/04e7eddbbdc142d3b85d07d70ec52e0b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d2b91b02071c40be8fb0125dcfa2fbee.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


点进去,我们可以看到它所支持的tags.然后找到适合自己的版本拉取下来就行了  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/66a971d1e1eb4fc49232a01a2e0aa8f0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


ps:一个镜像可以有多个版本名,比方这里的6.2.5,6.2,6你可以理解为就是redis 6.2  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ab9e71f0ea734193bad2ff9643b17713.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


比方我现在下载一个redis5.0  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5cf3f926e1524ee7ab192f80a40cc132.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/baba37b779d44583b8b83c4b1c472a4e.png)


删除镜像  
 `docker rmi (IMAGE ID)`:括号参数为镜像ID  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f2eb66d289574a5ba502638663cf9402.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


你会发现我并没有把全部的镜像ID输入,只输入了前3位,那么此时docker会匹配你的镜像id前3位为这个的镜像,将其全部删掉。  
 当然你也可以通过docker rmi REPOSITORY:TAG删除相应版本的镜像也是可以的。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c28a44ffefac41d3add954ffbc464516.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


同linux,你可以在后面加上-f表示强制删除。  
 那么我们是否可以一次性删除全部的镜像呢,是可以的。  
 我们既然删除的参数是镜像id,那么我将全部的镜像id作为参数传进去就好了啊  
 `docker rmi $(docker images -q)`就可以了。


### 2.3、docker容器相关命令


查看容器  
 `docker ps`:查看所有当前正在运行的容器,如果是通过-i创建的,那么已经因exit退出而关闭的容器不会显示出来。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7ee51c4b044a4797be47778950eb77d5.png)


`docker ps -a`:查看所有的容器,包括已经exit的容器。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ba24fde5a8b7405e88fd8f20ecefd634.png)


`docker ps -aq`:查看所有的容器id,包括已经exit的容器。


创建容器



docker run -it(d) --name=xx REPOSITORY:TAG /bin/bash
-i


表示容器交互式操作,保持容器运行。通常与 -t 同时使用。加入it这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭。  
 `-t`表示给容器赋予伪终端,能够实施一些命令  
 `-d`:以守护(后台)模式运行容器。创建一个容器在后台运行,需要使用docker exec 进入容器。退出后,容器不会关闭。  
 `-it` 创建的容器一般称为交互式容器,-id 创建的容器一般称为守护式容器  
 `--name`表示给容器起名字,可以用等号,也可以用空格。  
 REPOSITORY:TAG指定对应版本号的镜像  
 `/bin/bash`:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。  
 为确保测试能够正常进行  
 我提前下载了一个redis 5.0  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/56c1ddeeef0140af8e15b744438b5531.png)


我们通过 `docker run -it --name=redis5 redis:5.0 /bin/bash`测试一下  
 我们发现我们就已经进入了我们创建的容器中,且是一个redis的伪终端。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/cec8706a523c4d91b0f3ca04d2772cf9.png)


我们可以用exit退出终端,我们发现我们又回到我们的linux上了。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/fad861755cb34f7e860bb5ae4e9f462f.png)


我们刚刚通过参数-it创建了终端式的,现在我们通过-id参数创建一个后端运行的容器。



docker run -id --name=redis2 redis:5.0


![在这里插入图片描述](https://img-blog.csdnimg.cn/86cc7dad45364617b4efeacaf4c4ae1d.png)


我们发现我们并没有进入终端,而是给了一个很长的id,我们可以**用命令进入这个容器**。



docker exec -it redis2 /bin/bash


![在这里插入图片描述](https://img-blog.csdnimg.cn/5810de0288e648318c31979b56bcfaad.png)


进入容器



docker exec 参数 容器名or容器id /bin/bash


`-i`:分配一个伪终端  
 `-t`:表示给容器赋予伪终端,能够实施一些命令  
 `-d`:分离模式: 在后台运行  
 **ps:docker exec 进入容器后通过exit退出,容器不会停止!**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d7a5b28785e94ddaabc4660d5fcb845d.png)


停止及启动容器



docker stop 容器名or容器id


![在这里插入图片描述](https://img-blog.csdnimg.cn/34d024bd44c64a6ea8a7e8a0b98ab623.png)


那么有停止容器就有启动容器



docker start 容器名or容器id


![在这里插入图片描述](https://img-blog.csdnimg.cn/66bac5b6cf5342c0931393707b887a6c.png)


删除容器



docker rm 容器名or容器id


![在这里插入图片描述](https://img-blog.csdnimg.cn/e369e5a9af58467a9bf6e1ed4a110e53.png)


ps:一般情况下,你不能关闭一个已经启动的容器


当然,你可以通过`rm后加-f`强制删除这个启动的容器  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6d56018d77f44cd0ab5d47bb0c2e2b24.png)


那同删除所有镜像一样,你也可以将命令作为参数传给docker rm,  
 那删除全部容器的命令就是



docker rm $(docker ps -aq)


![在这里插入图片描述](https://img-blog.csdnimg.cn/509ba578a8ff4dc29da749f516809671.png)


查看容器信息



docker inspect 容器名or容器id


![在这里插入图片描述](https://img-blog.csdnimg.cn/7b9ab430565e48d7a7eab501184739ed.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


同样的,你可以通过docker inspect $(docker ps -aq)查看所有容器信息


## 三、docker数据卷


我们先来看下第一个问题:比方我现在有一个通过mysql5.7镜像创建的容器,假设我在这个容器创建了数据库,并往里面加入了数据,这时候容器挂了,里面的数据还在吗?  
 答案:当然不在了,容器都没了,数据又没存在额外的地方。那岂不是容器非常的不安全。  
 那想想如果我的容器能够和外部交换文件的话,岂不就可以解决上述困难了:  
 比方我的一个web项目放到tomcat的容器去运行,比方我将mysql容器的数据文件拿出来等等。  
 可惜,外部机器和容器之间网络并不互通。这一点我们目前也做不到。但外部机器可以和宿主机互通。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e2f97585052a40e5b7426b5ace974502.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


那容器和容器之间能交互数据吗,其实这些问题引出我们的主角—数据卷


### 3.1、数据卷概念


1、数据卷是宿主机中的一个目录或文件,当然单独的宿主机文件并不是数据卷,需要将数据卷的目录和容器的目录挂载绑定起来,那么此时的宿主机目录才可称之为数据卷。  
 2、当容器目录和数据卷目录绑定后,双方的修改会立即同步  
 3、一个数据卷可以被多个容器同时挂载  
 4、一个容器也可以被挂载多个数据卷  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ac29347ebd824aa191c13ea3a2fcf88c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


数据卷的作用  
 1、容器数据持久化  
 2、外部机器和容器间接通信  
 3、容器之间数据交换


### 3.2、配置数据卷


* 创建启动容器时,使用 –v 参数 设置数据卷 docker run … –v 宿主机目录(文件):容器内目录(文件)


…  
 ps:


1. 目录必须是绝对路径
2. 如果目录不存在,会自动创建
3. 可以挂载多个数据卷  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/50e7097e53ec40b1b7a0327f64c4e2fc.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


我们现在演示一下,为了更加清晰,我已经提前删除了全部容器。然后安装了centos7的镜像  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/99480882daca40b98cafffd83ca2faef.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


我们通过`docker run -id -v /root/docker/data:/root/data --name=mycentos centos:7 /bin/bash`创建centos7的容器并且进行挂载,将宿主机的/root/docker/data(没有会创建)挂载到我们容器的/root/data下,然后创建容器。  
 接着我们docker exec进入容器,然后我们进入root的目录下ll可以看到我们创建的/data目录。同样的我们在宿主机的root目录下可以看到我们创建的/docker/data目录


![在这里插入图片描述](https://img-blog.csdnimg.cn/8e9270f264ad4d2ea835a652a9d06ad5.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


接着我们来演示一下数据卷的作用  
 我们进入容器的/data目录,touch一个txt文件。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/4077b68a8ae444da965c98dd8925d980.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


这个时候看下宿主机的data下,发现这个文件同样被同步进去了。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/4abc35b209434610b3a12e6cd21961a2.png)


同样的,我们对文件进行的数据操作,也会被同步  
 我们执行`echo mbw > mbw.txt`  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c21431993a1745b6a1f966c393d9bf17.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_18,color_FFFFFF,t_70,g_se,x_16)


回到宿主机这里再看看  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7bc5116032af40d2bc8b2d051f7da99f.png)


然后现在我们模拟下假设容器挂掉了或者已经删了,宿主机的数据还有吗?  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/70a9322eac6a472f8bea73197a073ff1.png)


然后回到宿主机,我们发现数据还在  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e42f4584068d45789cecfa3d00e22387.png)


这个时候我们如果再次创建一个docker,然后通过



docker run -id -v ~/docker:/root/data --name=mycentos centos:7 /bin/bash


创建一个容器,并且挂载我们已经存在的数据文件。  
 我们看看新的容器是否同步已有的数据呢  
 我们可以很清楚的看到,内容完全同步了进去,即/root/docker下的所有数据挂载到容器的/root/data中。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7685387c5e244b4087ddad517506648b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


当然,我们的容器创建时可以挂载多个数据卷



docker run -id
-v /root/docker/data1:/root/data1
-v /root/docker/data2:/root/data2
–name=centos1 centos:7 /bin/bash


我们可以看到这样就挂载了两个数据卷  
 且在容器和宿主机都可以看到


![在这里插入图片描述](https://img-blog.csdnimg.cn/0cef80fe0a4940048bacc64a9ee485c0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)![在这里插入图片描述](https://img-blog.csdnimg.cn/b2d8a6a3e8dd4a3b8edf9db144736c23.png)


我们还可以实现两个容器同时挂载同一个数据卷,我们以宿主机的/root/docker为数据卷,  
 然后实现两个容器的数据交互:  
 我们创建两个容器,同时挂载/root/docker目录  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c5d9c401fce44805b21487d087c402d3.png)


然后我们在centos3创建文件  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7281b5b13a404dce9d1c5b6a434216c4.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3d3fb9d62974425fb0d7d1d320d56249.png)


这个时候进入centos2和宿主机看看文件是否被创建:发现均同步了  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20c621b61ceb49028bb0d1ac46d934e6.png)


![在这里插入图片描述](https://img-blog.csdnimg.cn/c703aac5bb254787ad455fb7b596bc6a.png)


### 3.3、数据卷容器


多容器进行数据交换  
 第一种办法就是我们刚才做的一样多个容器挂载同一个数据卷,但是这样操作就比较麻烦。  
 第二种就是通过数据卷容器  
 我们可以创建一个数据卷容器c3,这个c3和其他容器c1,c2没什么区别,但是c3挂载了一个数据卷,那么如果让c1,c2挂载这个数据卷容器,就简介挂在了数据卷。这也同时意味着c1,c2,c3都可以和数据进行交互 ,即使c3挂了,c1,c2仍然可以继续和数据卷进行数据交互。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/a0c8c2daeb534a2eafe5670dd5d0e01e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


那么我们就来创建数据卷。  
 首先将c1,c2,c3,c4全部给删了  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/159c14373d9a453d9e7b7de1f3722b5d.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后创建启动c3数据卷容器,这个其实和之前的创建容器一样



docker run –it --name=c3 –v /root/docker/data:/volume centos:7 /bin/bash


然后创建c1,c2并挂载c3数据卷容器,我们使用 –-volumes-from 参数 设置数据卷



docker run -id --name=c1 --volumes-from c3 centos:7
docker run -id --name=c2 --volumes-from c3 centos:7


然后我们进入c2,看看有没有/volume这个文件夹:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/1adfac3b6bed47d69fcb67c3ec76907e.png)


这个时候我创建一个文件,然后退出c2进入c1,c3  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f7d5e2b0af9140a196268f3e43d12751.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/dca7f08bc81d45b99086242d64fcabd4.png)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e91ac2a38b414f8a9f0a3b898e9bc2c8.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


发现同样同步成功。  
 假设我现在将c3删了,然后我在宿主机增加一个文件,这个时候回到c2,看看数据有没有同步:  
 证明就算数据卷容器没有了,我的c1,c2也已经简介挂载了宿主机的数据卷,且可以同步进行数据交互。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2a713ca4c6124fd9a23ad1366175dfdb.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


## 四、docker的应用


### 4.1、docker部署mysql


在Docker容器中部署MySQL,并通过外部mysql客户端操作MySQL Server。  
 实现步骤其实很简单,而且基本其他的都很相似,比起我们当时在linux自己安装要简单很多。  
 实现步骤:  
 1、搜索mysql镜像  
 2、拉取mysql镜像  
 3、创建容器  
 4、操作容器中的mysql


但是有一个问题,我们之前讲过,外部机器和容器之间网络是不通的,那么我们怎么让外部的mysql客户端连接上我们的mysql呢?  
 容器内的网络服务和外部机器不能直接通信  
 外部机器和宿主机可以直接通信  
 宿主机和容器可以直接通信  
 当容器中的网络服务需要被外部机器访问时,可以将容器中提供服务的端口映射到宿主机的端口上。外部机器访问宿主机的该端口,从而间接访问容器的服务。  
 这种操作称为:端口映射。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/feb0c4ed04044dd7b0ef19b3bf5a38d6.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


那我们现在就开始实操:  
 访问 MySQL 镜像库地址:<https://hub.docker.com/_/mysql?tab=tags> 。  
 可以通过 Sort by 查看其他版本的 MySQL,默认是最新版本 mysql:latest 。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6e8e010e3f81435e8b317aa1308c3856.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


我们这里下载mysql5.7的`docker pull mysql:5.7`,下载成功和可以看到。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b731273dded1466dbe31972c8bec8992.png)


然后就是关键了,我们要创建容器同时进行端口映射



docker run -d -p 3306:3306 --privileged=true -v /opt/mysql/conf/my.cnf:/etc/my.cnf -v /opt/mysql/data:/var/lib/mysql -v /opt/mysql/logs:/logs -e MYSQL_ROOT_PASSWORD=your password --name mysql mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci


我们来解释一下,首先我们通过宿主机的3306端口映射容器的3306端口。  
 然后通过数据卷将mysql的data数据文件,conf配置文件分别挂载到宿主机自己创建的三个目录,将来我们就可以直接同步数据,非常的方便。  
 **最后需要在防火墙开放我们宿主机的3306端口!**  
 那么下面我们就进入容器验收成果:  
 我们通过`mysql -uroot -p`输入密码登入我们的mysql  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/677b7b4eabe2468291e5e8d1ffb21b61.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后在mysql客户端试试能否远程登录,连接前要保证容器是开启的状态,没有记得docker start xxx  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3ac95251536f4d4da749bba969b70769.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


连接成功,docker安装mysql成功.


### 4.2、docker安装tomcat


这个比较复杂,我们需要用到一些新知识。  
 首先还是之前的老两步:  
 search–pull  
 我这里pull的是和我本地一致的版本:tomcat:8.5.63-jdk8-openjdk  
 pull好后,我们就需要创建容器,学过javaweb知识的肯定知道tomcat有两个比较重要的文件夹,webapps以及conf这两个文件夹,为了方便,我们自然而然能想到通过挂载的方式解决。  
 我们通过以下命令:



docker run -d --name tomcat -p 8080:8080 -v /opt/tomcat/conf:/usr/local/tomcat/conf -v /opt/tomcat/webapps:/usr/local/tomcat/webapps -v /opt/tomcat/logs/:/usr/local/tomcat/logs --restart=always tomcat:8.5.63-jdk8-openjdk


直接创建后,发现启动不起来,一直是restart状态,将 --restart=always 去掉重新run后发现状态变成了exit,就是启动不起来。  
 这是因为上面的命令中,我们也挂载了conf文件夹。这个是tomcat的配置文件夹。必须把tomcat中的conf中的文件复制到挂载文件上(**即/home/supervision\_app/app/conf目录下需要有配置文件**)  
 **而我们将空的数据卷与我们的容器同步,结果全是空的,自然启动不起来了**。  
 所以我们暂时有一个思路,\*\*创建一个不挂载数据卷的tomcat容器,如果能正常启动起来,就将它这里的数据移动到我们原来的数据卷中。\*\*其实这个思路是可行的。  
 我们docker rm -f tomcat后再次通过



docker run -d --name tomcat -p 8080:8080 --restart=always tomcat:8.5.63-jdk8-openjdk


**然后防火墙开放8080端口。**  
 创建tomcat,现在通过docker ps -a发现状态变成正常的了,那么我们通过  
 `docker exec -it tomcat /bin/bash`进入容器,进入成功。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3d1ee8642378478c9ab4aad80f9f5ef2.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


这个时候exit退出后,由于我们做了端口映射,我们试试远程能不能访问:  
 一输入发现404  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/cafac426683b4bacbcc3d762bb583f23.png)


这里其实已经说明,我们的tomcat已经起了。端口什么的都配好了。  
 使用命令: `docker exec -it 运行的tomcat容器ID /bin/bash` 进入到tomcat的目录  
 进入webapps文件夹,发现里面是空的(tomcat默认的欢迎页面实际上放在的路径应该是:webapps/ROOT/index.jsp或者index.html)  
 **发现下边还有个webapps.dist的文件,进入才发现原本应该在webapps文件中的文件都在webapps.dist文件中**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/653084a3c0f5449aa62c102522743dfb.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


**那么很简单,我们将webapps给删了,然后将webapps.dist改为webapps就行了。**



rmdir webapps
mv webapps.dist/ webapps


exit后`docker restart tomcat`后就可以发现启动成功  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/900ea65db40f4002ab2d6cadb1e29e16.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


但其实,我们解决的并不完美,**因为再另启动一个Tomcat容器时又会回到之前的窘境,既实际上问题的根源是在生成容器的镜像上,只有将镜像修改了,再生成的容器才不会再出现这个问题。**


所以我们得通过将我们的容器映射为新的镜像,然后通过这个镜像创建容器,就无后患了。  
 我们可以使用`docker commit`命令将运行着的容器映射成新的镜像  
 格式:`docker commit -a='作者-这个随意写' -m='‘修改内容--随意写' 容器名称或者ID 新生成镜像的名称:自己定义的版本号`  
 比方我以我现在这个可以正常运行的tomcat容器映射成镜像,



docker commit -a=‘孟博文’ -m=‘修改404’ tomcat tomcat:v1


我们映射完后通过docker images可以看到我们的镜像生成成功了。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/a5d8394409e94e96bcddcd2b6ebf24c0.png)


此时还没完,我们现在肯定想的是用这个新镜像创建新容器,但是我们之前那个tomcat容器还没有利用完:  
 因为你想想,我这个时候创建新容器,挂载还是空的,照样不行,所以我们将之前正常的tomcat容器文件复制到我们的挂载的数据卷上。  
 那怎么移动呢,docker自己提供了cp命令。



docker cp 容器名or id:容器目录or 文件 数据卷目录


我们将我们的conf以及webapps目录拷贝到/opt/tomcat下,在移动之前将以前空的文件删掉就行。



docker cp tomcat:/usr/local/tomcat/conf/ /opt/tomcat/
docker cp tomcat:/usr/local/tomcat/webapps/ /opt/tomcat/


然后发现我们的数据卷此时就有数据了:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d43561b95cc248da885addf2dee42caf.png)


这个时候tomcat容器光荣退休,我们把它删了。



docker rm -f tomcat


然后用我们的新镜像创建新的容器并挂载我们数据卷



docker run -d --name tomcat -p 8080:8080 -v /opt/tomcat/conf:/usr/local/tomcat/conf -v /opt/tomcat/webapps:/usr/local/tomcat/webapps -v /opt/tomcat/logs/:/usr/local/tomcat/logs --restart=always tomcat:v1


![在这里插入图片描述](https://img-blog.csdnimg.cn/dcc2561749d941479c9a5830987c55f8.png)


如果发现status为up就代表成功!去浏览器输入发现同样能进入主页!


![在这里插入图片描述](https://img-blog.csdnimg.cn/91fd2ffe48614ada98344e93ec07cd96.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


### 4.3、docker部署nginx


如果tomcat安装成功,其实nginx就非常简单了。  
 首先我们pull nginx的镜像,我这里拉取的是1.19.0的  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/4bcde0aa3a744995ae907b29a1ba062b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后通过docker run创建一个正常的nginx的容器



docker run -d --name=nginx -p 80:80 --restart=always nginx:1.19.0


![在这里插入图片描述](https://img-blog.csdnimg.cn/76b172d8f8cf426b9a8219e81860eb49.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


创建成功后,我们可以直接访问192,168.200.130:80访问


但是我们现在还没挂载,借用之前安装tomcat的思路,我们同样先在/opt创建nginx文件夹,然后在这下面创建三个文件夹:conf,logs,html分别存放我们的配置文件,日志文件,以及项目。  
 而nginx的这三份对应的文件在:  
 1、日志位置:**/var/log/nginx/**  
 2、配置文件位置:**/etc/nginx/nginx.conf**  
 3、项目位置:**/usr/share/nginx/html**  
 我们通过cp命令拷贝到我们的数据卷即可:



docker cp /var/log/nginx/ /opt/nginx/logs
docker cp nginx:/usr/share/nginx/html /opt/nginx/
docker cp nginx:/etc/nginx/nginx.conf /opt/nginx/conf


![在这里插入图片描述](https://img-blog.csdnimg.cn/cd28808f1e244123b94dfc55aef6fac1.png)


‘  
 这个时候通过`docker rm -f nginx`  
 然后创建新容器并挂载数据卷



docker run -d --name=nginx --restart=always -p 80:80 -v /opt/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /opt/nginx/html/:/usr/share/nginx/html -v /opt/nginx/logs:/var/logs/nginx nginx:1.19.0


此时通过`docker ps -a`  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5771c1db8a2d4af1a16df5a1a1389c6f.png)


这个时候访问192.168.200.130:80即可访问到我们的nginx,docker安装nginx成功!  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/bacbd38963934f3fb63b722c7eec4d45.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


### 4.4、docker安装redis5


拉取镜像redis:5:`docker pull redis:5`  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c105573f56094710817223b5a350e5ed.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后创建/opt/redis/conf和/opt/redis/data两个目录  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/103b2adf3a91434d86f09e208d62100a.png)


然后去<https://download.redis.io/redis-stable/redis.conf>下载redis.conf文件传到/opt/redis/conf  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/039c7ee584614eecb2f9d6b2131bf830.png)


vim这个文件,需要注意修改的地方:  
 `bind 127.0.0.1` #注释掉这部分,这是限制redis只能本地访问  
 `protected-mode no` #默认yes,开启保护模式,限制为本地访问  
 `daemonize no`#默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败  
 `databases 16` #数据库个数(可选),我修改了这个只是查看是否生效。。  
 `dir ./` #输入本地redis数据库存放文件夹(可选)  
 `appendonly yes` #redis持久化(可选)  
 修改完后,就可以创建容器并挂载了



docker run --restart=always -d --privileged=true -p 6379:6379 -v /opt/redis/conf/redis.conf:/redis.conf -v /opt/redis/data:/data --name redis redis:5 redis-server --appendonly yes


这里介绍一些参数的意义:  
 `--privileged=true` 提升容器内权限  
 `redis-server` redis-server就是redis的启动命令  
 `--appendonly yes` 开启数据持久化  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/a3cc4d5b5b914b70956cef6151f07726.png)


然后在redis客户端发现一样能登陆成功,redis安装成功!  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/978287d1c62948e68939f9f32efb4444.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


## 五、dockerfile


提前剧透:dockerfile就是用来制作镜像的  
 思考一下:  
 Docker 镜像本质是什么?  
 Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G?  
 Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/fd6e075fcdfe4b9089168889e7650b22.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


在讲原理之前,大家不妨先了解一下操作系统和linux的文件系统。  
 操作系统组成部分:  
 1.进程调度子系统  
 2.进程通信子系统  
 3.内存管理子系统  
 4.设备管理子系统  
 **5.文件管理子系统**  
 6.网络通信子系统  
 7.作业控制子系统  
 Linux文件系统由bootfs和rootfs两部分组成  
  bootfs:包含bootloader(引导加载程序)和 kernel(内核)  
  rootfs: root文件系统,包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc等标准目录和文件  
 不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos等  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0512c4c3100347d8960f2a2bfbe359f1.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_18,color_FFFFFF,t_70,g_se,x_16)


### 5.1、docker镜像原理


Docker镜像是由特殊的文件系统叠加而成  
 最底端是 `bootfs`,**并使用宿主机的bootfs,比方linux操作的时候会加载一次内核,然后docker加载的时候就不会再次重复加载,而是直接使用之前linux加载的内核。所以docker启动非常快。实现一种复用效果**。  
 第二层是 root文件系统`rootfs`,称为**base image**  
 然后再往上可以叠加其他的镜像文件,比方我们可以在基础镜像上放上jdk镜像,然后在jdk镜像上接着放tomcat的镜像。这三部分组合起来,我们就把它称作tomcat镜像。这种组合性的镜像叫做**只读镜像**!那么这样的好处,仙子啊假设我在tomcat这样一个组合镜像基础上,再安装一个nginx的镜像,只读镜像已经有的,如果nginx也刚好需要,它就不需要再去下载了,即我**下载的每一层镜像都可以被复用**!  
 统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,**这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。** 这也就解释了为什么tomcat这样一个镜像就有500多Mb,centos镜像反而只要200Mb.  
 一个镜像可以放在另一个镜像的上面。**位于下面的镜像称为父镜像,最底部的镜像成为基础镜像**。  
 **只读镜像不能修改**,如果我想修改的话,就有了下面的方法,当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器。


![在这里插入图片描述](https://img-blog.csdnimg.cn/a0739d6fa5924affb692be213de898b9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_18,color_FFFFFF,t_70,g_se,x_16)


而我们可以通过容器创建新的镜像,由此对镜像去做出一些改变,而可读镜像仍然是固定的,可复用的!  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/95aa58b1d9994724bc124368051e582b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


那么我们现在就来回答一下刚才的思考题:  
 1.Docker 镜像本质是什么?  
 是一个分层文件系统  
 2.Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G?  
 Centos的iso镜像文件包含`bootfs`和`rootfs`,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层  
 3.Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?  
 由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像,所有整个对外暴露的tomcat镜像大小500多MB  
 我们可以通过`docker inspect tomcat:v`1看一下我们的tomcat到底被分为多少层:你可以看到被分成了特别多层:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e174ec4df11a4ab79ddaa170faf18377.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


### 5.2、容器转化为镜像


命令:`docker commit -a’xxxx作者信息’ -m’修改信息’ 容器id/容器名称 自定义镜像名称:自定义版本号`  
 比方我们将修改好的tomcat转化为镜像:



docker commit -a=‘孟博文’ -m=‘修改404’ tomcat tomcat:v1


![在这里插入图片描述](https://img-blog.csdnimg.cn/ebc928334f46480e812ee7fa74248ee1.png)


这样就生成了我们想要的镜像,这在今后是非常方便的,我们比方在tomcat部署了一个web项目,然后我们就可以将它转化为我们的镜像,然后将这个镜像通过某种方式转给其他人,就ok了。  
 那我们该怎么将镜像分享出去呢,docker有一个压缩命令可以将镜像压缩为文件。



docker save -o 压缩文件名称(可以加路径,不加默认当前目录) 镜像名称:版本号


我们可以将这个压缩文件发给其他人,然后其他人可以把这个压缩文件转化为镜像,然后使用就是我们自己写改好的东西了。  
 那怎么把压缩文件还原成镜像:



docker load -i 压缩文件名称


那我们现在从头到尾演示一遍:  
 为了一个需要注意的知识点,我现在新建一个test文件夹然后写一个页面放进我们的webapps叫做test.html!  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/9391c4ad00724032adb2736ce626f6ed.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后由于**挂载**,它肯定是放在了我们的容器中的,我们可以看一下演示一下:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/066243267dd84c1eaf8aa53c2a446df5.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


现在我将这个生成镜像叫做tomcat:v2



docker commit -a ‘孟博文’ -m ‘挂载页面’ tomcat tomcat:v2


![在这里插入图片描述](https://img-blog.csdnimg.cn/790480ce6fcd416b9c61a1fee26c78d0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后我们先进去创建一个v2的容器看看我们挂载的test.html还在不在,假设我创建的tomcat容器我不挂载任何一个目录,因为你发给别人,别人肯定不能挂载到你这里的文件。



docker run -d --name=tomcat2 -p 8888:8080 --restart=always tomcat:v2


运行后进去这个容器,发现我们的test文件夹不见了!访问肯定也是404


![在这里插入图片描述](https://img-blog.csdnimg.cn/2974cf070d674a749113abf129111baf.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


**docker commit是只会保留容器的数据,不会保留任何挂载在宿主机的数据。**  
 如果我们在我们刚才生成的镜像里创建文件,那么毫无疑问会被保留下来,这也是为什么我们将空的webapps删了,将webapps.dist改为webapps能够在新镜像保留下来的原因。那怎么保留我们的数据,我们在之后的dockerfile会讲解。  
 然后我们现在尝试着将我们这个镜像生成压缩文件,然后删除我们这个v2镜像,再把这个压缩文件还原,看是否能重新生成该镜像。



docker save -o /opt/tomcat/tomcat.tar tomcat:v2


![在这里插入图片描述](https://img-blog.csdnimg.cn/fab9bdfc04b64141b5fe1f5ffa9b044d.png)



docker load -i /opt/tomcat/tomcat.tar


![在这里插入图片描述](https://img-blog.csdnimg.cn/955747ef166c438984fa89507a88d506.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


镜像重新生成成功,演示完毕!


### 5.3、dockerfile概述以及相关关键字


dockerfile概念:  
 Dockerfile 是一个文本文件  
 1、包含了一条条的指令  
 2、每一条指令构建一层,基于基础镜像,最终构建出一个新的镜像  
 3、对于开发人员:可以为开发团队提供一个完全一致的开发环境  
 4、对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了  
 5、对于运维人员:在部署时,可以实现应用的无缝移植


![在这里插入图片描述](https://img-blog.csdnimg.cn/0930bd03734a431a963a8bb57d5e6aa7.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


我们可以在docker官网搜到一些dockerFile.  
 Dochub网址:<https://hub.docker.com>




| 关键字 | 作用 | 备注 |
| --- | --- | --- |
|  |  |  |
| FROM | 指定父镜像 | 指定dockerfile基于那个image构建 |
| MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 |
| LABEL | 标签 | 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看 |
| RUN | 执行命令 | 执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN [“command” , “param1”,“param2”] |
| CMD | 容器启动命令 | 提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD [“command” , “param1”,“param2”] |
| ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
| COPY | 复制文件 | build的时候复制文件到image中 |
| ADD | 添加文件 | build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务 |
| ENV | 环境变量 | 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value |
| ARG | 构建参数 | 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数 |
| VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME [“目录”] |
| EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp |
| WORKDIR | 工作目录 | 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径 |
| USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 |
| HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 |
| ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大 |
| STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 |
| SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell |


### 5.4、dockerfile案例—自定义centos


我们自定义一个centos镜像要实现以下功能:  
 1、默认登陆路径为/usr  
 2、可以使用vim  
 实现步骤:  
 定义父镜像:`FROM centos:7`  
 定义作者信息:`MAINTAINER mbw <mbw@mbw.com>`  
 执行安装vim命令: `RUN yum install -y vim`  
 定义默认的工作目录:`WORKDIR /usr`  
 定义容器启动执行的命令:`CMD /bin/bash`  
 通过dockerfile构建镜像:`docker bulid –f dockerfile文件路径 –t 镜像名称:版本 URL`  
 我们现在在/opt创建dockerfile/centos目录,在其下vim一个dockerfile文件,写上以下内容:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/bdef9cf4fd134dc78af8d18ab13047c2.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_15,color_FFFFFF,t_70,g_se,x_16)


然后通过`docker build -f /opt/docker-files/centos/dockerfile -t mycentos:v1` .  
 `-f`后接的是dockerfile的路径  
 `-t`是自定义的镜像名:版本号  
 `.`表示当前路径,一般都是这个  
 生成后,我们通过docker images 查看  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/98b2226d870e41fd952c48dd2dee4f8b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后通过`docker run -it --name=mycentos mycentos:v1`创建并进入我们的容器  
 发现我们的默认工作目录已经变成了/usr  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5faa092d1fba4b8e95e37886520cbb88.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后试下vim,发现也可以成功。那么自定义centos就算完成了。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d8c3411c3bbc4b4db8981ce937240255.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


### 5.5、dockerfile实例二:测试一个springboot的项目


我们创建一个非常简单的springboot的项目来测试是否能运行  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/42b6a3195da641a2a441a19c8c59c08c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/bfed58ecc38140659976b5db802a9eef.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


在保证项目没问题的前提下,我们通过`mvn package`将我们的项目打成jar包  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/45ad269369a74ccc8faf2deb1763995c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d657fe4a71e04b3cb87a376e0d6e1d5c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


我们可以通过`java -jar xxx.jar`正常运行  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/89b65bbf13164478a714da1533b99fa9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后来到docker这边  
 首先pull一个jdk8的镜像



docker pull abrtech/alpine-oraclejdk8


![在这里插入图片描述](https://img-blog.csdnimg.cn/eb04c9f0f1e44f55995187fdb9ec5a96.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


一切都成功的情况下,我们可以创建dockerfile。  
 在`/opt/docker-files`创建`project/docker_springboot`目录,将生成的jar包放入并创建dockerfile  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/9e8d88351bbd49f5aa4ca5e22e7233b4.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


Dockerfile内容如下:  
 FROM 基础镜像:`FROM abrtech/alpine-oraclejdk8`  
 ADD 类似于linux命令中的copy:  
 `ADD docker_springboot-0.0.1-SNAPSHOT.jar app.jar`  
 暴露项目的服务端口:`EXPOSE 8080`  
 启动命令:`CMD java -jar app.jar`  
 编写完后**cd 到/opt/docker-files/project/docker\_springboot**执行  
 `docker build -f ./Dockerfile -t app .`创建镜像  
 执行完后可以通过`docker images`看到我们生成的镜像:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b8ba6967aa1549cebee4e634ce3e8212.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


然后运行容器启动jar包



docker run -it -p 9090:8080 --name=springboot_docker app


![在这里插入图片描述](https://img-blog.csdnimg.cn/6d360f781b1e4718ad30fc1530dab4f1.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


发现项目成功运行起来,输入192.168.200.130:9090/hello,访问成功!  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/60ceb7ad76994fe8be4646fd4159bbe0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


### 六、docker compose


微服务架构的应用系统中一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,维护的工作量会很大。  
 例如要从Dockerfile build image 或者去dockerhub拉取image  
 要创建多个container  
 要管理这些container(启动停止删除)  
 这样的工作量是非常恐怖且浪费时间的!  
 服务编排:按照一定的业务规则批量管理容器


### 6.1、服务编排


Docker Compose概念  
 Docker Compose是一个编排多容器分布式部署的工具,提供命令集管理容器化应用的完整开发周期,包括服务构建,启动和停止。使用步骤:  
 1、利用 Dockerfile 定义运行环境镜像  
 2、使用 docker-compose.yml 定义组成应用的各服务  
 3、运行 docker-compose up 启动应用  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/405d8cc281d44a2dbad3a7a7d4c3143b.png)


安装docker Compose



curl -L “https://get.daocloud.io/docker/compose/releases/download/1.27.3/docker-compose- ( u n a m e − s ) − (uname -s)- (unames)(uname -m)” -o /usr/local/bin/docker-compose


![在这里插入图片描述](https://img-blog.csdnimg.cn/5e8a7f6d68e74b2d929abed00d9ddd75.png)


然后设置文件可执行权限



chmod +x /usr/local/bin/docker-compose


验证是否安装成功可通过`docker-compose -v`,显示版本号就说明docker-compoe安装成功!  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/60ed9ef925f74047a1d827ad43c521f5.png)


要是想删除其实docker-compose也很简单,因为我们是通过二进制包方式安装的,直接删除这个文件就好



rm /usr/local/bin/docker-compose


### 6.2、docker-compose编排nginx+springboot的项目


我们首先通过docker images查看![在这里插入图片描述](https://img-blog.csdnimg.cn/1624e31254c5491b9b272721a55d99ba.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)  
 我们的镜像


之前我们直接通过run我们的app容器启动我们的springboot项目,但是假设现在我们需要nginx反向代理我们的项目,你可能会想,我再启动我的nginx就好了,是可以这样,但万一你的项目又要很多种数据库,再加上消息队列,还需要布置集群,你还愿意一个一个启动吗?  
 所以我们通过docker compose将这些全部放一起:  
 我们在/opt下新建docker-compose/docker-compose.yml,这个yml名字不能改变。  
 然后编辑docker-compose.yml,**语法格式注意是yml**



version: ‘3’
services:
#第一个要编排的服务
nginx:
#基础镜像
image: nginx:1.19.0
#端口映射
ports:
- 9090:80
#链接到其它服务的中的容器,这里可以是别名也可以是服务名称
links:
- app
#数据卷挂载,挂载我们宿主机自己nginx的配置文件
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
#第二个服务,其次也是被nginx链接的服务app
app:
image: app
#暴露的端口号
expose:
- “8080”


然后就是nginx的配置文件  
 我们在docker-compose.yml处于的当前目录新建当时我们挂载的目录  
 `mkdir -p /nginx/conf.d`,然后在这下面创建mbw.conf这个配置文件  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5cd40a7e22604aaba39144b75a0e68f0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


这样我们写的配置文件自然会被挂载进去,配置文件内容如下:



server {
listen 80;
access_log off;

  location / {
      proxy_pass http://app:8080;
  }

}


意思就是当访问192.168.200.130,就会自动代理到app这个镜像的8080端口。  
 这个app其实是我们刚才links里链接的app镜像。  
 然后:wq保存退出,**cd …/…/返回装有yml的目录**  
 通过`docker-compose up`启动我们的docker-compose即可  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/90322aac859e4bfa80d0a34ad4743ca8.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6Zuo772e5peL5b6L,size_20,color_FFFFFF,t_70,g_se,x_16)


启动成功!我们访问192.168.200.130:9090/hello(9090是映射的nginx的80端口)  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值