思维导图
快速入门
安装和配置
centos
卸载旧版
如果系统中已经存在旧的docker,则先进行卸载
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
配置docker的yum库
首先要安装一个yum工具
yum install -y yum-utils
安装成功后,执行命令,配置Docker的yum源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
安装docker
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
启动和校验
// 查看docker版本
docker -v
// 启动docker
systemctl start docker
// 执行docker ps命令,如果不报错,说明安装启动成功
docker ps
// 另外的语法
systemctl stop docker
systemctl restart docker
systemctl enable docker
配置镜像加速
阿里云
- 注册阿里云账号
- 在首页产品中,找到阿里云的容器镜像服务
- 进行具体的配置操作
windows
docker基础
快速入门
尝试部署MySQL
先停掉虚拟机中的MySQL,确保你的虚拟机已经安装Docker,且网络开通的情况下,执行下面命令即可安装MySQL
docker run -d --name mysql -p 3306:3306 -e TZ=Asia/Shanghai -e MYSQL_ROOT_PASSWORD=admin mysql
等待docker安装完成之后,尝试连接数据库,发现连接成功,mysql安装成功
效果:
哎?相比于之前的linux安装mysql,需要配置前置依赖、下载压缩包,还要按顺序解压、还要对mysql进行复杂的配置才能用,现在一行命令就搞定了。
就好像类似于下载一个QQ,只需要下载它的exe,然后疯狂next,最后生成完整的QQ文件夹,然后拿那个文件夹压缩给别人,别人进行解压之后也能立马使用了,所以Docker也就相当于这个过程。
命令解读
docker run:创建并运行一个容器
-d是让容器在后台运行
–name mysql:赋予容器的标识,必须唯一
-p 3306:3306:设置端口映射(前面的是宿主机端口,后面的是容器端口)
为什么需要设置端口映射,原因是镜像运行在一个容器中,容器是一个隔离环境,与宿主机之间是相对独立的存在、有独立的内存空间、IP地址和端口,只是使用了宿主机的操作系统资源。如果直接连接容器的IP是会被拒绝的,那么容器里面的软件服务我怎么使用呢?既然容器访问不了,我还访问不了宿主机吗,所以要做一个映射,将宿主机的指定端口映射到容器的指定端口,从而形成间接访问。
-e KEY=VALUE:设置环境变量,官方说需要哪些变量就要进行相应的配置,那么怎么知道需要配置哪些东西呢?可以去docker hub里面搜索获取。
mysql:运行的镜像名字,具体的名字结构,参考镜像-镜像命名
基础内容
镜像
概述
当我们利用docker安装应用时,docker会自动搜索并下载应用镜像image,镜像不仅包含本身,还包含所需要的运行环境、配置、系统函数库。也就说别人帮我们打包好这些东西了,只需要用在时候docker把它丢在一个隔离空间里面运行即可。
那么镜像怎么好,从哪里来呢?类似于maven的依赖,这些资源都会有一个仓库存储的。
镜像仓库:存储和管理镜像的平台,docker官方维护了一个公共仓库:docker Hub
那么本地向镜像仓库拉取代码的时候,过程是什么呢?
之前我们安装docker之后,要启动docker,启动docker后会自动生成一个docker daemon守护进程,这个守护进程就会等我们输入命令,daemon监听到我们敲命令之后,就会获取命令去运行
镜像命名
一般由两部分组成:[repository]:[tag]
- repository:敬香茗
- tag镜像版本,不指定tag,默认就是latest,代表最新版本的镜像
容器
Docker会在运行镜像的时候创建一个隔离环境,称为容器,容器之间互不干扰。
常见命令
最常见的命令就是操作镜像、容器的命令,详见官方文档:https://docs.docker.com/
根据一个案例来熟悉这些命令流程:
查看DockerHub,拉取Nginx镜像,创建并运行Nginx容器
需求:
- 在DockerHub中搜索Nginx镜像,查看镜像名称
- 拉取Nginx镜像
- 查看本地镜像列表
- 创建并运行Nginx容器
- 查看容器
- 停止容器
- 再次启动容器
- 进入Nginx容器
- 删除容器
实现:
- 去DockerHub中搜索Nginx的镜像内容
拉取最新版本的Nginx,如果还需要了解Nginx的详细信息,可以浏览具体文档
- 执行docker pull nginx,拉取最新的nginx
-
将nginx镜像打包给他人,这里自己做演示
-
- 将nginx打包:docker save -o nginx.tar nginx,表示将nginx镜像打包到当前目录下的nginx.tar文件里面
- 删除docker里面的nginx镜像:docker rmi nginx
- 查看现在的镜像内容:docker images,发现nginx镜像确实不见了
- 导入指定的tar包将nginx镜像恢复回来:docker load -i nginx.tar
- 再次输入docker images,发现nginx镜像又出现了
- 将nginx打包:docker save -o nginx.tar nginx,表示将nginx镜像打包到当前目录下的nginx.tar文件里面
注意:如果不知道怎么做,可以docker --help查看手册
- 创建并运行镜像:docker run -d --name nginx -p 80:80 nginx,结果是返回一串字符串
- 查看容器进程:docker ps,显示有一个nginx的容器正在运行
可以对输出的内容做格式化
docker ps --format “table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}”
效果如下:
注意:docker ps默认查看运行中的容器,如果要查看所有容器,需要添加一个选项-a
- 查看容器的日志信息:docker logs -f nginx,表示持续打印nginx的日志信息
- 进入容器的环境:docker exec -it nginx bash
效果:
表示进入了nginx环境,并且使用bash命令行模式
使用exit命令退出容器环境
同理:MySQL
这样进入MySQL客户端比较繁琐,可以一步到位
- 删除容器:docker rm nginx
命令别名
对于上面格式化输出docker ps内容命令来说,语法太长太繁杂,如果每次都要去复制或者写出来是比较麻烦的,所以可以用到linux里面的一个技巧。
命名别名,可以将你想要映射的命令通过key=value匹配
- 首先得找到root目录下得.bashrc文件进行编辑
vi ~/.bashrc (~等价于root)
- 添加如下得key-value内容
-
让更改生效
-
重启输入或者输入source命令
-
使用别名命令获取docker ps格式化后得输出内容
数据卷
场景引入
利用Nginx容器部署静态资源
需求:
创建Nginx容器,修改Nginx容器内的html目录下的index.html文件,查看变化
-
首先得找index.html在哪
a. 但是现在我怎么知道,全盘扫描可以,也可以通过dockerHub得官方文档获取信息
-
进入到nginx容器环境
a. docker exec -it ngix bash
b. 切换到执行目录:cd /usr/share/nginx/html
c. 编辑index.html:vi index.html,发现没有这个命令,原因是容器都是只安装软件的最小程度的资源,并不会多余的安装其他不想要的内容,那么说在容器内修改文件是比较困难的 -
引出数据卷内容
-
那我知道数据卷能解决之后,我怎么挂载呢?
a. 首先要知道挂载什么,挂载index.html文件
b. 然后是怎么挂载数据卷和Nginx文件内容
ⅰ. 需要在容器创建的同时挂载:-v 数据卷:容器内目录
ⅱ. 如果创建容器时,挂载了数据卷且数据卷不存在,会自动创建数据卷
c. 重新部署容器
ⅰ. docker stop nginx
ⅱ. docker rm nginx/直接使用docker rm -f nginx
ⅲ. docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
d. 查看容器是否部署成功和数据卷成功
ⅰ. docker ps / dpsf – 查看运行的容器信息
ⅱ. docker volume ls – 查看有哪些数据卷
ⅲ. docker volume inspect html – 查看数据卷详细信息
e. 切换到宿主机对应的路径位置
ⅰ. cd /var/lib/docker/volumes/html/_data
ⅱ. cat index.html
f. 开始修改文件内容
ⅰ. 将welcome to nginx,改为welcome to rainbow
ⅱ. 添加图片到html里面
g. 查看nginx容器内是否有文件变更
- 将静态资源部署到nginx的html目录
MySQL容器数据挂载
需求:
- 查看MySQL容器,判断是否有数据卷挂载
- 基于宿主机目录实现MySQL数据目录、配置文件、初始化脚本的挂载
实现:
- 查看nginx容器详情:docker inspect nginx
- 查看MySQL容器详情:docker inspect mysql
这里就有疑问了,我刚开始并没有挂载过mysql,这里为什么会挂载?
这些容器自动创建的数据卷,称为匿名卷;/var/lib/mysql是数据存储的目录
为什么mysql要将数据目录挂载到宿主机呢?
原因是:MySQL在运行过程中会不断产生数据,如果不做挂载,数据都会保存在容器内,将来这个容器这个体积就很大,这个时候想做迁移就非常难,出于数据解耦的考虑,自动将数据目录进行挂载了。
但是它挂载的数据卷是匿名卷,会出现另外的问题
匿名卷的名字随机生成,有这样的场景,现在要对mysql进行版本更新,要做更新就要对mysql容器删掉,然后创建新的容器,删除之后数据卷还在,数据也还在,但是我重新部署mysql,它自动创建的数据卷就跟之前的不一样了,这是不是等价于原来的数据就丢失了。也可以通过复制解决,但是这个匿名太长了,导致视觉上不好受,所以一般不建议使用匿名卷,而是进行自定义挂载。
-
将mysql的数据目录挂载到任意地方,而不是挂载到/var/lib/docker/volumes目录下了
-
依然是使用docker run,使用-v 本地目录:容器内的目录就可以实现本地目录挂载,唯一的区别就是将数据卷名字改为绝对路径
注意要使用绝对路径,如果使用相对路径会被docker识别为数据卷的名字
-
还需要挂载配置文件、初始化脚本
-
不知道在哪?去查询官方文档
注意:可以同时挂载多个数据卷
-
重新部署容器和挂载MySQL
-
在root目录创建mysql目录
-
在mysql目录创建data、init、conf目录并将黑马的配置文件和脚本复制到conf和init中
-
执行命令
注意不要漏-e,mysql容器是需要环境配置的
- 由于脚本文件自动执行
效果如下:
概述
数据卷是一个虚拟目录,是容器目录与宿主机目录之间的映射的桥梁
注意:/var/lib/docker/volumes路径是固定的
数据卷一旦创建,宿主机的volumes也会自动创建
这种映射是双向的,这样我就不用进入到Nginx环境里修改文件了,而是直接在宿主机上进行修改
基础操作
也可以通过docker volume --help查看所有的基础操作
自定义镜像
场景引入
既然是自定义,官方规定镜像要有什么,我们就要提供什么。
- 应用程序
- 系统函数库
- 运行配置
- 等等
还让我们回想一下部署Java的流程
- 准备一个linux服务器
- 安装JRE并配置环境变量
- 拷贝Jar包
- 运行Jar包
现在要部署到docker里面,也需要提供JRE吧
但是不同操作系统底层适配的具体不同,难道不同环境搞一套吗,这样还用docker干嘛?这个时候只需要将配套的系统函数库也导进去就行,JRE根据需求获取。
构建Java镜像的步骤
- 准备一个linux环境
- 安装JRE并配置环境变量
- 拷贝Jar包
- 编写运行脚本
上面每一步都会产生文件,但是docker制作的镜像并不是将它们产生的文件打包到一起,而是将每一步产生的文件分别打成一个压缩包,作为镜像的一部分,最终合到一起才是镜像。
这里涉及到docker的一个层(layer)的概念,每次添加安装包、依赖、配置等,每次操作都形成新的一层。
为什么要这样做呢?
优点如下:
- 可以将一些公用的基础依赖打包成镜像,作为地基供大家使用,专业称之为:基础镜像,包含的有系统函数库、环境、配置、文件等
- 存储体积减少,本地有之后就不用重复下载
最后还可以将里面的一个特殊镜像称之为入口(entrypoint),是软件镜像的入口、一般是程序的启动脚本和参数。
框架图如下:
那么这些基础镜像、层、入口都要我们自己去做是非常麻烦的,docker提供了一个dockerfile的功能,在里面描述相关的信息,docker就会根据里面的信息去自动构建。
Dockerfile
简介
DockerFile就是一个文本文件,其中包含一个个的指令Instruction,用指令来说明要执行什么操作来构建镜像
基础操作
更多命令参考:https://docs.docker.com/engine/reference/builder
基于ubuntu的构建Java镜像的示例:
左边是全流程的,右边是获取别人的基础镜像即可
当编写好了Dockerfile之后,可以利用下面的命令来构建镜像
docker build -t myImage:1.0 .
-t:给镜像命名,格式依然为repository:tag格式
.:指定dockerfile所在的目录,如果就在当前目录,则指定为.
下面演示一个示例:
- 先获取到黑马给的Dockerfile和docker-demo.jar包文件,我保存在CourseData目录/黑马/nginx/demo里面了
- 进入linux服务器、在创建root的目录下创建一个demo目录:mkdir demo
- 将第一点说到的文件复制到demo目录下,打开finalshell复制更便捷
- 由于Dockerfile里面描述的基础镜像在本地是不存在的,所以需要下载,但是下载太长时间了,这里直接将黑马给的复制过来即可
- 对jdk.tar进行load到docker中:docker load jdk.tar
- 查看镜像:docker images,发现多了个openjdk
- 切换回demo目录:cd demo
- 构建自定义镜像:docker build -t docer-demo .(没有指定文件名,docker就会去当前目录下去找Dockerfile文件进行解析)
- 查看镜像文件:docker images,发现镜像中多个了jdk-demo的镜像
- 将自定义镜像部署到容器上:docker run -d --name mydemo -p 8080:8080 docker-demo
- 查看容器运行状态:jpsf/docker ps,发现多个了jdk-demo
- 访问网页看看是否能访问的到:192.168.xx.xx:8080/hello/count
网络
场景引入
部署Java应用,如果Java里面用到了mysql、redis这些组件,就还需要进行访问,这些组件之间也是部署在容器中的,那么容器之间的访问的问题是我们需要考虑的。
查看容器的详细信息:
docker inspection mysql/nginx/redis
发生容器的ip地址是在同一个网段里面,原因是它们都有一个相同的网关
默认情况下,所有容器都是以bridge方式连接到docker的一个虚拟网桥上
那么既然在同一个网段可以相互访问不就没有问题了吗?
但是有个问题,容器的ip是docker随机分配的,那么我如果将容器下线之后,另一个容器上线,可能就会把这个ip获取到,我就没得用了,Java访问的mysql也是一个问题。
所以这个东西不能让docker自动创建,而是要人为干涉,自定义网络配置
自定义网络配置
查看当前本机上的网卡:ip addr
制定好网桥之后,指定部署到这个网桥里面的IP配置信息就不会变动了
常用的操作:
示例:创建一个自定义网络配置
可以通过docker network --help查看命令具体信息
- 查看docker的网卡:docker network ls
- 创建自定义网络:docker network create rainbow
- 再次查看docker网卡:docker network ls
- 将指定容器连接到自定义网络:docker network connect rainbow mysql
- 查看指定的容器详情:docker inspect mysql
上面这种是基于已创建的容器配置的自定义网络
还可以在镜像创建的时候给他配置自定义网络
注意:先把之前的容器删掉,docker rm docker-demo
再次启动docker-demo:docker run -d --name docker-name -p 8080:8080 --network rainbow docker-demo
这样就会直接对接自定义网络,而不是配置docker自动分配的网络
Docker-Compose
场景引入
部署后端
部署前端
Compose
简介
Docker Compose通过一个单独的docker-compose.yml模板文件来定义一组相关联的应用容器,帮助我们实现多个相互关联的docker容器的快速部署。
作用是:对多个容器进行统一的管理
一般是一个docker-compose文件对应一个项目
基础操作
配置
示例:
告诉docker-compose
- 我要部署哪些容器
- 每个容器的必要信息,这些信息与镜像部署到容器中需要的参数一致,只是格式不一样,bash与yaml
对比如下:
同理配置多个容器信息,根据yaml格式进行配置即可
执行命令
docker compose [option] [command]