Docker
Docker
1. 安装Docker
1.1 卸载旧版
首先如果系统中已经存在旧的Docker,则先卸载:
1 | |
1.2 配置Docker的yum库
首先要安装一个yum工具
1 | |
安装成功后,执行命令,配置Docker的yum源:
1 | |
1.3 安装Docker
最后,执行命令,安装Docker
1 | |
1.4 启动和校验
1 | |

1.5 配置镜像加速
以阿里云镜像加速为例




2. Docker快速入门
2.1 部署MySQL
如果是利用传统方式部署MySQL,大概的步骤有:搜索并下载MySQL安装包;上传至Linux环境;编译和配置环境;安装。
最重要的是两个拉取的链接,改了后安装。端口号和名字无所谓。
1 | |
1 | |
而使用Docker安装,仅仅需要一步即可,在命令行输入下面的 命令:
1 | |





2.2 命令解读
- 镜像(Image):
静态的蓝图,描述了如何搭建应用。
是制作某种东西的配方/计划。- 容器(Container):
动态的实例,它是基于镜像创建出来并正在运行的应用。
是按照这个配方做出来的成品,并且是可以实际使用的。
利用Docker快速的安装了MySQL,非常的方便,不过我们执行的命令到底是什么意思呢?
1 | |
- docker run -d :
创建并运行一个容器,-d则是让容器以后台进程运行;- –name mysql2 : 给容器起个名字叫mysql2,你可以叫别的;
- -p 3307:3306 : 设置端口映射。
容器是隔离环境,外界不可访问。
但是可以将宿主机端口映射容器内到端口,当访问宿主机指定端口时,就是在访问容器内的端口了。
容器内端口往往是由容器内的进程决定,例如MySQL进程默认端口是3306,因此容器内端口一定是3306;而宿主机端口则可以任意指定,一般与容器内保持一致。
格式: -p 宿主机端口:容器内端口,示例就是将宿主机的3307映射到容器内的3306端口- -e TZ=Asia/Shanghai : 配置容器内进程运行时的一些参数
格式:-e KEY=VALUE,KEY和VALUE都由容器内进程决定
案例中,TZ=Asia/Shanghai是设置时区;
-e MYSQL_ROOT_PASSWORD=123456是设置MySQL默认密码;- mysql : 设置镜像名称,Docker会根据这个名字搜索并下载镜像
格式:REPOSITORY:TAG,例如mysql:8.0,其中REPOSITORY可以理解为镜像名,TAG是版本号
在未指定TAG的情况下,默认是最新版本,也就是mysql:latest。

3. Docker基础-常见命令
3.1 常见命令
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker pull | 拉取镜像 | docker pull |
| docker push | 推送镜像到DockerRegistry | docker push |
| docker images | 查看本地镜像 | docker images |
| docker rmi | 删除本地镜像 | docker rmi |
| docker run | 创建并运行容器(不能重复创建) | docker run |
| docker stop | 停止指定容器 | docker stop |
| docker start | 启动指定容器 | docker start |
| docker restart | 重新启动容器 | docker restart |
| docker rm | 删除指定容器 | docs.docker.com |
| docker ps | 查看运行状态 | docker ps |
| docker logs | 查看容器运行日志 | docker logs |
| docker exec | 进入容器 | docker exec |
| docker save | 保存镜像到本地压缩文件 | docker save |
| docker load | 加载本地压缩文件到镜像 | docker load |
| docker inspect | 查看容器详细信息 | docker inspect |

如何把镜像交给运维人员:
- 使用 docker save 形成本地压缩包,运维人员再使用docker load将本地这个压缩包进行解压;
- 将镜像推送docker push到镜像仓库,运维人员再从镜像仓库进行拉取docker pull;
- Docker run 每次都会重新创建一个容器;
- docker start 只是重新启动被停掉的容器
补充:默认情况下,每次重启虚拟机我们都需要手动启动Docker和Docker中的容器。通过命令可以实现开机自启:
1 | |
3.2 演示docker中nginx mysql
以Nginx为例给大家演示上述命令
1 | |

可以打成压缩包 免得拉取


1 | |


1 | |


1 | |


1 | |
容器内部有独立的文件系统(模拟的)



1 | |


1 | |

3.3 命令别名
给常用Docker命令起别名,方便我们 访问:
1 | |


然后,执行命令使别名生效
1 | |

4. Docker基础-数据卷
4.1 什么是数据卷
容器提供程序的运行环境,但是程序运行产生的数据、程序运行依赖的配置都应该与容器****解耦。

docker提供了程序运行的系统环境,但只包含当前镜像运行必备的系统函数和依赖,故nginx没有vi ll;即所有镜像是最小化的系统环境,只具备运行所必须的,故vi没有,在容器内修改文件非常困难,更不用说把静态资源拷贝到容器的html目录。

数据卷(volume)是一个虚拟目录,是容器内目录与宿主机****目录之间映射的桥梁。
以Nginx为例,我们知道Nginx中有两个关键的目录:
- html:放置一些静态资源
- conf:放置配置文件
如果我们要让Nginx代理我们的静态资源,最好是放到html目录;
如果我们要修改Nginx的配置,最好是找到conf下的nginx.conf文件。但遗憾的是,容器运行的Nginx所有的文件都在容器内部。
所以我们必须利用数据卷将两个目录与宿主机目录关联,方便我们操作。
在上图中:
- 我们创建了两个数据卷:conf、html
- Nginx容器内部的conf目录和html目录分别与两个数据卷关联。
- 而数据卷conf和html分别指向了宿主机的/var/lib/docker/volumes/conf/_data目录和/var/lib/docker/volumes/html/_data目录
这样以来,容器内的conf和html目录就 与宿主机的conf和html目录关联起来,我们称为挂载。此时,我们操作宿主机的/var/lib/docker/volumes/html/_data就是在操作容器内的/usr/share/nginx/html/_data目录。
只要我们将静态资源放入宿主机对应目录,就可以被Nginx代理了。

4.2 数据卷命令
数据卷的相关命令有:
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker volume create | 创建数据卷 | docker volume create |
| docker volume ls | 查看所有数据卷 | docs.docker.com |
| docker volume rm | 删除指定数据卷 | docs.docker.com |
| docker volume inspect | 查看某个数据卷的详情 | docs.docker.com |
| docker volume prune | 清除数据卷 | docker volume prune |
注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据 卷会自动创建。
4.3 挂在本地目录或文件
1. nginx的html目录挂载
演示环节:演示一下nginx的html目录挂载

1 | |

1 | |

1 | |

1 | |


1 | |

什么是数据卷?
•数据卷是一个虚拟目录,它将宿主机目录映射到容器内目录,方便我们操作容器内文件,或者方便迁移容器产生的数据
如何挂载数据卷?
•在创建容器时,利用 -v 数据卷名:容器内目录完成挂载
•容器创建时,如果发现挂载的数据卷不存在时,会自动创建
2. mysql容器的数据挂载


容器运行时自动创建的卷,匿名卷。
1 | |


接下来,可以查看该目录下的MySQL的data文件:

可以发现,数据卷的目录结构较深,如果我们去操作数据卷目录会不太方便。在很多情况下,我们会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似:
1 | |
注意:本地目录或文件必须以
/或./开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
1 | |
其中,hm.cnf主要是配置了MySQL的默认编码,改为utf8mb4;而hmall.sql则是后面我们要用到的黑马商城项目的初始化SQL脚本。

1 | |

1 | |

1 | |

1 | |


1 | |



1 | |

5. Docker基础-镜像
5.1 镜像结构
- 镜像就是包含了应用程序、程序运行的系统函数库、运行配置等文件的文件包。构建镜像的过程其实就是把上述文件打包的过程。
- 镜像之所以能让我们快速跨操作系统部署应用而忽略其运行环境、配置,就是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。
- 自定义镜像本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成。




5.2 Dockerfile
由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。
而这种记录镜像结构的文件就称为Dockerfile。
其中的语法比较多,比较常用的有:
| 指令 | 说明 | 示例 |
|---|---|---|
| FROM | 指定基础镜像 | FROM centos:6 |
| ENV | 设置环境变量,可在后面指令使用 | ENV key value |
| COPY | 拷贝本地文件到镜像的指定目录 | COPY ./xx.jar /tmp/app.jar |
| RUN | 执行Linux的shell命令,一般是安装过程的命令 | RUN yum install gcc |
| EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
| ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.jar |

以后我们会有很多很多java项目需要打包为镜像,他们都需要Linux系统环境、JDK环境这两层,只有上面的3层不同(因为jar包不同)。如果每次制作java镜像都重复制作前两层镜像,是不是很麻烦。所以,就有人提供了基础的系统加JDK环境,我们在此基础上制作java镜像,就可以省去JDK的配置了:
1 | |
5.3 构建镜像



然后,执行命令,构建镜像:
1 | |



1 | |




1 | |

1 | |


- 镜像的结构是怎样的?
镜像中包含了应用程序所需要的运行环境、函数库、配置、以及应用本身等各种文件,这些文件分层打包而成。- Dockerfile是做什么的?
Dockerfile就是利用固定的指令来描述镜像的结构和构建过程,这样Docker才可以依次来构建镜像- 构建镜像的命令是什么?
docker build -t镜像名 Dockerfile目录
6. Docker基础-网络
上节课我们创建了一个Java项目的容器,而Java项目往往需要访问其它各种中间件,例如MySQL、Redis等。现在,我们的容器之间能否互相访问呢?我们来测试一下
首先,我们查看下MySQL容器的详细信息,重点关注其中的网络IP地址:
1 | |

docker inspect dd 的IPAddress是172.17.0.4

1 | |


- 服务部署可以连接到dd。dd的IPAddress是dovker网桥分配的,假设服务重新启动,或是再重启过程中有其他服务启动,这个数字会变化,故dd现在IPAddress的是172.17.0.4,在java代码中配置这个172.17.0.4,重启后变了就连不上了。
- 但是,容器的网络IP其实是一个虚拟的IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时很可能MySQL容器的IP会发生变化,连接会失败。
加入自定义网络的容器才可以通过容器名互相访问,Docker的网络操作常见命令有:
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker network create | 创建一个网络 | docker network create |
| docker network ls | 查看所有网络 | docs.docker.com |
| docker network rm | 删除指定网络 | docs.docker.com |
| docker network prune | 清除未使用的网络 | docs.docker.com |
| docker network connect | 使指定容器连接加入某网络 | docs.docker.com |
| docker network disconnect | 使指定容器连接离开某网络 | docker network disconnect |
| docker network inspect | 查看网络详细信息 | docker network inspect |

1 | |

1 | |

1 | |

通过自定义网络,容器间的相互访问非常方便,只需要容器名即可互相访问,即使mysql重启IP地址变了,也没关系,ping容器名即可找到。
1 | |
7. 项目部署


在正式部署前,我们先删除之前的dd容器。
mysql容器中已经准备好了商城的数据,所以就不再删除了。
7.1 部署java项目–服务部署
hmall项目是一个maven聚合项目,使用IDEA打开hmall项目,查看项目结构如图:

我们要部署的就是其中的hm-service,其中的配置文件采用了多环境的方式:

其中的application-dev.yaml是部署到开发环境的配置,application-local.yaml是本地运行时的配置。
查看application.yaml,你会发现其中的JDBC地址并未写死,而是读取变量:
这两个变量在application-dev.yaml和application-local.yaml中并不相同:

在dev开发环境(也就是Docker部署时)采用了mysql作为地址,刚好是我们的mysql容器名,只要两者在一个网络,就一定能互相访问。





将hm-service目录下的Dockerfile和hm-service/target目录下的hm-service.jar一起上传到虚拟机的root目录:

1 | |

dis查看镜像
1 | |







nginx要加入网络,别漏了,否则报错404


服务部署总结:
- 把项目打包,打包完成后,把得到的jar包和dockerfile一起扔到虚拟机里(好像似乎必须是/root否则没有mybatis-plus);
- 利用命令自己构建镜像,再用docker run部署应用。
7.2 部署前端


为什么要创建新的容器是因为:之前的nginx容器只挂载了html目录没有挂载conf文件,没有办法对nginx的conf文件做配置。故需要创建新的容器对配置文件挂载。





我们现在要做的就是把整个nginx目录上传到虚拟机的/root目录下:


若此处hmxr不改,后面的浏览器访问192.168.203.128:18080,一直转圈加载不出来


1 | |


能不能跟后端java应用产生联动?试试搜索商品和分页查询

证明前后端与数据库这三个容器的互连没有问题,项目成功部署。

- 部署java应用:先把java应用打成包,把jar包和Dockerfile上传到虚拟机,用docker build命令构建成镜像,然后启动。
- 部署静态资源nginx前端:需要准备好html前端静态资源资源目录和配置文件conf,创建容器跟其挂载。
7.3 DockerCompose
1. 基本语法
大家可以看到,我们部署一个简单的java项目,其中包含3个容器:MySQL,Nginx,Java项目。而稍微复杂的项目,其中还会有各种各样的其它中间件,需要部署的东西远不止3个。如果还像之前那样手动的逐一部署,就太麻烦了。
而Docker Compose就可以帮助我们实现多个相互关联的Docker容器的快速部署。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器。

举例来说,用docker run部署MySQL的命令如下:
如果用docker-compose.yml文件来定义,就是这样:


黑马商城部署文件:
1 | |
2. 基础命令
编写好docker-compose.yml文件,就可以部署项目了。常见的命令:
基本语法如下:
1 | |
其中,OPTIONS和COMMAND都是可选参数,比较常见的有:
| 类型 | 参数或指令 | 说明 |
|---|---|---|
| Options | -f | 指定compose文件的路径和名称 |
| -p | 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念 | |
| Commands | up | 创建并启动所有service容器 |
| down | 停止并移除所有容器、网络 | |
| ps | 列出所有启动的容器 | |
| logs | 查看指定容器的日志 | |
| stop | 停止容器 | |
| start | 启动容器 | |
| restart | 重启容器 | |
| top | 查看运行的进程 | |
| exec | 在指定的运行中容器中执行命令 |
演示:
现在用docker compose一键部署,之前部署的容器都删掉。
1 | |



1 | |

失败 3306端口被占用,删除容器和镜像重试



1 | |





1 | |

