docker学习文档
docker学习文档
目录
- 一、docker安装(环境:Centos)
- (一)、在线安装
- (二)、离线安装(说明:没有实现,先记录一下,后续可能会实现)
- 二、docker卸载(Linux)
- 三、docker命令
- 3.1、版本查看命令
- 3.2、帮助命令
- 3.3、启动/停止/重启/查看状态命令/开机启动
- 3.4、镜像命令
- 3.5、容器命令
- docker run [可选项] 镜像名称:标签 [命令] [其他参数…]
- docker update 容器id/容器名称 [可选项]
- docker ps [可选项]
- docker stats
- docker start 容器id/容器名称 ……
- docker restart 容器id/容器名称 ……
- docker stop 容器id/容器名称 ……
- docker kill 容器id/容器名称 ……
- docker rm [-f] 容器id/容器名称 ……
- docker logs 容器id/容器名称
- docker top 容器id/容器名称
- docker inspect 容器id
- docker cp 容器id/容器名称:容器内路径 目的主机路径
- docker export 容器id/容器名称>XXX.tar
- cat XXX.tar | docker import - 镜像用户/镜像用户[:镜像版本号]
- docker commit -m="描述信息" -a="作者名称" 容器id/名称 要创建的目标镜像名[:标签名]
- 四、docker镜像
- 五、本地镜像发布到阿里云
- 六、本地镜像推送到私有镜像库
- 七、容器数据卷(位于Linux系统中,相当于U盘)
- 八、docker中常规软件安装
- 九、docker中复杂软件安装(先欠着)
- 十、Dockerfile
- 十一、docker network
- 十二、compose
- 十三、Portainer
- 十四、CIG(CAdvisor收集 + InfluxDB存储 + Granfana展示)
- 十五、docker小知识点
一、docker安装(环境:Centos)
(一)、在线安装
1、docker官网
注意: 安装过程中需要在linux上登录root用户,否则部分命令将执行受阻
2、找到在CentOS中安装docker的文档
点击Developers》Docs,如下:
点击Download And Install,如下:
点击Docker fro Linux,如下:
点击CentOS,如下:
3、判断安装docker的CentOS环境是否符合要求
判断来源依然是官网,截图如下,如果你不知道你的CentOS版本,你可以在终端中使用cat /etc/redhat-release
命令查看当前CentOS版本
4、卸载旧版本
如果你之前已经安装过docker,然后本次安装的是新的docker版本,那需要先卸载旧版本,然后在安装新版本,卸载命令如下。如果你根本没有安装过docker,请忽略这一步。
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
上述命令来源于官网,截图如下:
5、安装gcc相关工具
5.1、判断CentOS是否能上外网
使用下列命令即可判断,如下:
ping www.baidu.com
如果无法连接外网,那就需要配置一下,博客如下:CentOS配置静态IP
5.2、安装gcc编译器
执行以下命令安装gcc编译器:
yum -y install gcc
注意:如果你不确定是否已经安装了,你也可以执行这条命令,多次执行该命令不会多次下载
5.3、安装gcc-c++编译器
执行以下命令安装gcc-c++编译器:
yum -y install gcc-c++
注意:如果你不确定是否已经安装了,你也可以执行这条命令,多次执行该命令不会多次下载
6、选择合适的安装方式
选择大多数人使用的安装方式就可以了,点击下图中的蓝色链接即可:
7、安装yum-utils安装包
安装yum-utils安装包,命令如下:
yum install -y yum-utils
8、安装阿里云镜像仓库
不能使用官方推荐的 https://download.docker.com/linux/centos/docker-ce.repo
,因为这是国外的镜像仓库,在国内使用容易产生TCP连接问题和超时问题
建议使用阿里云或者网易云的docker镜像仓库,我们下面以阿里云docker镜像仓库为例来进行安装配置,以下配置脚本来源于阿里云官网的文章Docker CE 镜像中,如下:
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
9、安装docker引擎
(1)安装最新版本docker,需要执行以下命令:
sudo yum -y install docker-ce docker-ce-cli containerd.io
(2)如果想安装其他版本docker,可以先使用以下命令查询所有docker版本列表
yum list docker-ce --showduplicates | sort -r
上述命令查询结果如下,其中红框中就是dockerVersion:
如果选好了docker版本,可以将下面命令中的dockerVersion替换掉,之后执行命令安装docker即可:
sudo yum install -y docker-ce-dockerVersion.x86_64 docker-ce-cli-
dockerVersion.x86_64 containerd.io
例如我选择的dockerVersion是3:19.03.9-3.el7
,那么命令就是:
sudo yum install -y docker-ce-3:19.03.9-3.el7.x86_64 docker-ce-cli-3:19.03.9-3.el7.x86_64 containerd.io
10、配置镜像加速器
10.1、配置阿里云镜像加速器(不太推荐,原因是部分镜像无法下载)
首先进入阿里云官网,并登录账号,搜索容器镜像服务,选择立即开通,如下:
找到需要执行的脚本命令,如下:
一定要在linux中执行上述截图中框起来的脚本命令才能完成加速功能
10.2、配置网易镜像加速器(推荐)
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["http://hub-mirror.c.163.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
11、启动docker
执行以下命令启动docker,如下:
systemctl start docker
注意: 启动完成不会有任何消息提示,但是可以通过ps -ef | grep docker
来验证是否docker是否启动成功
12、设置docker开机自启
执行以下命令:
systemctl enable docker
(二)、离线安装(说明:没有实现,先记录一下,后续可能会实现)
1、docker官网
注意: 安装过程中需要在linux上登录root用户,否则部分命令将执行受阻
2、找到在CentOS中安装docker的文档
点击Developers》Docs,如下:
点击Download And Install,如下:
点击Docker fro Linux,如下:
点击Binaries下面的Install daemon and client binaries on Linux
,如下:
tgz压缩包下载路径在以下位置:
之后点击x86_64/
,如下:
之后就可以选择适合自己的docker版本下载,下载速度很快,所以就不给安装包了,如下:
TODO 安装方法后续验证通过在补充
二、docker卸载(Linux)
执行以下命令即可,如下:
systemctl stop docker
sudo yum remove docker-ce docker-ce-cli containerd.io
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
以上命令来自于官网,截图如下:
三、docker命令
3.1、版本查看命令
// 查看docker版本(详细信息)
docker version
// 查看docker版本(简略信息)
docker --version
3.2、帮助命令
// 查询docker概要信息
docker info
// 帮助文档
docker help
// 单个命令帮助文档
docker 命令名称 help
3.3、启动/停止/重启/查看状态命令/开机启动
// 启动docker
systemctl start docker
// 停止docker
systemctl stop docker
// 重启docker
systemctl restart docker
// 查看docker状态
systemctl status docker
// 开启docker开机启动
systemctl enable docker
3.4、镜像命令
docker images [可选项] [镜像名称]
1、作用
列出本地所有镜像
2、参数说明
REPOSITORY:镜像在仓库中的名称
TAG:镜像标签版本号(用来标识当前镜像的不同版本)
IMAGE ID:镜像id前几位
CREATED:镜像创建时间
SIZE:镜像大小)
3、可选项
-a:列出本地的所有镜像,包含历史映像层
-q:只显示镜像id
注意:可选项-a和-q可以连用,比如docker images -aq
4、镜像名称
只查询当前镜像名称下面的所有不同标签镜像,比如:docker images tomcat
docker search [可选项] 镜像名称
1、作用
查找仓库中的镜像
2、参数说明
NAME:镜像名称
DESCRIPTION:镜像描述信息
STARS:点赞数量
OFFICIAL:是否官方;[OK]:官方,无内容:非官方
AUTOMATED:是否自动构建;[OK]:自动构建,无内容:不自动构建
3、可选项
--limit 数字:如果不使用limit,默认列出25个同名称镜像,不过我们可以通过limit进行限制,默认按照点赞数量STARS排序,例如:docker search --limit 5 redis
docker pull 镜像名称[:镜像标签]
1、作用
从远程仓库拉取镜像到本地
2、镜像标签
不使用镜像标签,默认的镜像标签就是latest,比如docker pull redis相当于docker pull redis:latest
使用镜像标签:如果你知道镜像标签,你可以直接添加即可,如果你不确定,可以先登录dockerhub官网,
地址是https://hub.docker.com,然后在左上角搜索框中搜索镜像名称,选择带有Official Image标志的镜像名称点击,
选择Tags,选择适合的镜像版本,点击右边的复制按钮,在linux中执行就可以拉取该版本的镜像了,例如docker pull redis:6.0.8
docker system df
1、作用
查看镜像、容器、数据卷所占用的空间
2、参数说明
TYPE:Images(镜像)、Containers(容器)、Local Volumes(本地卷)、Build Cache(构建缓存)
TOTAL:总数
ACTIVE:活动中的数量
SIZE:大小
RECLAIMABLE:可伸缩性
docker rmi [-f] 镜像名称:标签/id ……
1、作用
删除镜像
2、-f
不添加-f:如果存在活跃的镜像容器,执行该命令将会造成冲突,导致不能删除该镜像
添加-f:f对应的单词是force,代表强制的意思,所以即使出现了上述冲突的情况,也会删除该镜像
3、删除单个镜像
docker rmi -f 镜像名称:标签/id
4、删除多个镜像(多个镜像名称:标签/id之间用空格分隔)
docker rmi -f 镜像1名称/id 镜像2名称/id 镜像3名称/id ……
5、删除全部镜像
docker rmi -f $(docker images -aq)
docker save 镜像名称:标签/id…… > 压缩包名称
1、作用
将一个镜像打包成一个压缩包放在本地
2、例子
docker save a59a34125272 > images.tar
docker save -o 压缩包名称 镜像名称:标签/id……
1、作用
将一个或者多个镜像打包成一个压缩包放在本地
2、例子
docker save -o images.tar a59a34125272 d23bdf5b1b1b
3.5、容器命令
docker run [可选项] 镜像名称:标签 [命令] [其他参数…]
1、作用
创建容器
2、可选项
--name="容器名称":指定容器名称,默认是系统分类的,也可以写成:--name 容器名称
-d:后台启动容器,并且运行完毕返回容器id,即启动守护式容器(后台运行)
-i:以交互模式启动容器,常与 -t联用
-t:为容器重新分配一个伪输入终端
-P:随机端口映射,即docker中的端口对应linux中的端口是随机的,例如-P
-p:指定端口映射,即docker中的端口对应linux中的端口是设定的,可以出现多次,例如-p 3306:3306
-e:环境变量,配置到系统中的属性,可以出现多次
3、启动交互式容器(前台命令行)
-i和-t联用就可以启动一个交互式容器,比如:docker run -it ubuntu /bin/bash
4、退出交互式容器
退出之后停止容器:在交互式容器控制台输入exit之后点击回车键
退出不停止容器:点击Ctrl+p+q,操作是按住Ctrl,依次点击p和q
5、重新进入交互式容器
方法1(推荐使用):使用命令:docker exec -it 容器id/容器名称 /bin/bash,就可以重新进入交互式容器了,可以测试ubuntu
方法2:使用命令:docker attach 容器id/容器名称,就可以重新进入交互式容器了,可以测试ubuntu
两种方法区别:方法1将会在容器中打开新的终端,开启新的进程,输入exit退出容器,不导致容器停止;方法2反之,输入exit退出容器,将导致容器停止
6、启动守护式容器
使用参数-d就可以启动一个守护式容器,比如docker run -d redis:6.0.8
一般先使用docker run -d 镜像id/镜像名称:tags启动守护式容器,然后使用docker exec -it 容器id/容器名称 /bin/bash进入容器内部做事情
docker update 容器id/容器名称 [可选项]
1、作用
更新容器配置信息
2、可选项
非常多,比如:--restart=always
docker ps [可选项]
1、作用
列出所有正在运行的容器
2、参数说明
CONTAINER ID:容器id
IMAGE:镜像名称
COMMAND:命令
CREATED:创建时间
STATUS:启动状态
PORTS:端口
NAMES:容器名称
3、可选项
-a:列出所有容器,包括正在运行的容器和历史上运行过的容器
-q:返回值中只显示容器编号
-l:显示最近创建的1个容器
-n XXX:显示最近创建的XXX个的容器,其中XXX是显示的容器数量,例如:docker ps -n 3
docker stats
1、作用
动态查看docker容器状态
docker start 容器id/容器名称 ……
1、作用
启动已经停止的容器(我们可以通过docker ps -n 5看到最近的容器列表,STATUS的状态以Exited开头的就是已经停止的容器)
docker restart 容器id/容器名称 ……
1、作用
重启容器
docker stop 容器id/容器名称 ……
1、作用
停止容器
docker kill 容器id/容器名称 ……
1、作用
强制重启容器
docker rm [-f] 容器id/容器名称 ……
1、作用
删除已经停止的容器,容器删除之后通过docker ps -a命令也无法查询到,所以也就没有办法恢复了
2、-f
如果容器正在运行,可以通过添加-f参数删除正在运行的容器
3、一次性删除所有容器实例
方法1:docker rm -f $(docker ps -aq)
方法2:docker ps -aq | xargs docker rm -f
docker logs 容器id/容器名称
1、作用
查看容器日志
docker top 容器id/容器名称
1、作用
查看容器内运行的进程情况
docker inspect 容器id
1、作用
查看容器内部细节
docker cp 容器id/容器名称:容器内路径 目的主机路径
1、作用
备份容器内的数据到主机中,避免删除容器之后数据无法恢复
docker export 容器id/容器名称>XXX.tar
1、作用
备份容器;即导出容器中的所有内容为一个tar包归档文件,以备后续恢复该容器使用
2、例子
docker export distracted_stonebraker>/home/xm/testexport.tar
cat XXX.tar | docker import - 镜像用户/镜像用户[:镜像版本号]
1、作用
恢复容器导出的tar包为镜像;其中命令中“镜像用户/镜像用户”就是执行docker images命令看到的Images下的镜像名称
2、注意
命令中的/不是或者的意思,它就是一个符号而已
3、命令
cat testexport.tar | docker import - xm/ubuntu:latest
解释:将tar包归档文件导成镜像之后,可以通过docker images看到具体的镜像,例如上面命令执行之后,我们使用docker images看到的结果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
xm/ubuntu latest af0e6355799d 5 seconds ago 72.8MB
docker commit -m=“描述信息” -a=“作者名称” 容器id/名称 要创建的目标镜像名[:标签名]
1、作用
将当前容器提交成一个本地镜像
2、例子
docker commit -m="添加vim工具" -a="明快de玄米61" 132f48fd425a xm/ubuntu:1.0.0
结果:
REPOSITORY TAG IMAGE ID CREATED SIZE
xm/ubuntu 1.0.0 6cf11614c3a9 3 seconds ago 72.8MB
四、docker镜像
镜像概念
镜像是一种轻量级、可执行的独立软件包,它包含某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时所需的库、环境变量和配置文件等),这个打包好的运行环境就是镜像文件。只有通过镜像文件才能生成容器实例
镜像分层
通过docker pull 镜像名称:tags
拉取远程仓库镜像到本地的过程中,我们可以看到生成了很多的镜像id,这说明镜像是一层一层叠加起来的,我们看到了一个镜像,比如ubuntu是很多个镜像形成的
UnionFS(联合文件系统)
联合文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。联合文件系统是docker镜像的基础。镜像可以通过分层来进行集成,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像
特性:一次同时加载多个文件系统,但从外面来看,只能看到一个文件系统,联合加载会将各层文件系统叠加起来,最终联合文件系统会包含所有底层文件和目录
docker镜像加载原理
docker镜像实际上由一层一层的文件系统组成,这种层级的文件系统叫做UnionFS(联合文件系统)。
bootfs(boot file system)主要包含BootLoader和kernel,BootLoader主要是引导加载kernel,Linux刚启动的时候会加载bootfs文件系统,这就是docker镜像最底层的引导文件系统。这一层和我们典型的linux/unix系统是一样的,包括boot加载器和内核,所以我们才会说容器就是一个简易版的Linux环境。当bootfs加载完成之后整个内核就在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system)在bootfs之上,包含的就是典型Linux系统中的/dev、/bin、/etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如ubuntu、centos等
对于一个精简的OS,rootfs可以很小,只需要包含最合适的命令,工具和程序库就可以了,因为底层直接使用的就是Host的kernel,自己只需要提供rootfs就行了,由此可见对于不同的linux发行版,bootfs基本是一直的,rootfs会有差别,所以不同的发型版本可以共用bootfs
为什么docker要采用这种分层结构呢?
镜像分层最大的一个好处就是共享资源,其实就是为了复用资源。比如说有多个镜像都从相同的base镜像构建而来,那么Docker Host只需要在磁盘上保存一份base镜像,同时内存也只需要加载一份base镜像,就可以为所有镜像服务了,而且镜像的每一层都可以被共享
镜像层和容器层的关系
docker镜像层都是只读的,容器层是可写的。当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作容器层,容器层之下的都叫做镜像层
镜像分层小总结
docker中的镜像分层,支持通过扩展现有镜像。类似Java继承于一个Base基础类,自己在按需扩展。新镜像就是从base镜像一层一层叠加生成的,每安装一个软件,就是在现有镜像的基础上增加一层
五、本地镜像发布到阿里云
流转流程
推送本地镜像到阿里云
1、创建本地镜像
通过docker commit -m="描述信息" -a="作者名称" 容器id/名称 要创建的目标镜像名[:标签名]
命令创建一个本地镜像
2、在阿里云官网中配置命名空间和镜像仓库,并推送本地镜像到阿里云镜像仓库
登录阿里云官网,搜索容器镜像服务
,如下:
点击管理控制台,如下:
点击实例列表,选择个人实例,如下:
创建命令空间,如下:
创建镜像仓库,如下:
点击管理,找到上传命令,如下:
依次执行以下命令,将镜像推送到远程仓库,如下:
注意:
1、命令1输入之后,需要输入阿里云密码
2、命令2中的[ImageId]
是我们docker commit……生成的本地镜像id,然后[镜像版本号]
是在阿里云仓库中显示的镜像版本号
3、命令3中的[镜像版本号]
就是命令2中的镜像版本号
4、推送镜像到阿里云成功之后,通过docker images可以看到我们推送到阿里云的镜像
例如:
docker login --username=阿里云用户名 registry.cn-qingdao.aliyuncs.com
docker tag 6cf11614c3a9 registry.cn-qingdao.aliyuncs.com/20220128test/test:1.0.0
docker push registry.cn-qingdao.aliyuncs.com/20220128test/test:1.0.0
从阿里云下载镜像到本地
依照推送本地镜像到阿里云的截图,我们可以找到如下界面:
示例命令如下:
docker pull registry.cn-qingdao.aliyuncs.com/20220128test/test:1.0.0
六、本地镜像推送到私有镜像库
搭建私有镜像库
下载Docker Registry镜像:
docker pull registry
运行registry镜像,生成容器:
docker run -d -p 5000:5000 -v /xm/myregistry/:/tmp/registry --privileged=true registry
通过docker commit -m="描述信息" -a="作者名称" 容器id/名称 要创建的目标镜像名[:标签名]
命令生成新的镜像,例如:
docker commit -m="添加vim工具" -a="明快de玄米61" 132f48fd425a xm/ubuntu:1.0.0
通过docker tag 镜像:tags host:port/repository:tags
将新镜像复制一份,保证该份镜像符合私服规范,其中端口是固定的5000,但是ip是你本机的ip,例如:
docker tag xm/ubuntu:1.0.0 192.168.139.129:5000/xm/ubuntu:1.0.0
修改配置文件以支持http,如下:
首先使用vim /etc/docker/daemon.json
打开配置文件,然后把insecure-registries": ["ip:5000"]
添加进去,注意ip使用你本机的ip,例如:
{
"registry-mirrors": ["阿里云镜像加速网址"],
"insecure-registries": ["192.168.139.129:5000"]
}
重启docker和registry容器,如下:
// 重启docker容器
systemctl restart docker
// 找到停止的registry容器
docker ps -a
// 启动registry容器
docker start 容器id
推送镜像到本地镜像仓库
通过docker push 镜像名称:镜像标签
推送镜像到本地镜像仓库中,其中镜像名称和镜像标签就是上面生成的符合私服规范的镜像信息,例如:
docker push 192.168.139.129:5000/xm/ubuntu:1.0.0
通过curl -XGET http://ip/v2/_catalog
命令验证私服库上存在的镜像,其中ip是你本机的ip,例如:
curl -XGET http://192.168.139.129:5000/v2/_catalog
验证结果如下:
从本地镜像仓库拉取镜像
通过docker pull ip:5000/镜像名称:标签名称
(我至今不知道如何从本地镜像仓库看到标签名称)从本地镜像仓库上拉取镜像,例如:
docker pull 192.168.139.129:5000/xm/ubuntu:1.0.0
七、容器数据卷(位于Linux系统中,相当于U盘)
1、概念
简单来说:容器数据卷相当于一个U盘,我们通过电脑操作U盘中的文件,这些文件始终都在U盘中,而不是电脑中,容器数据卷存在于linux系统中,目的是将docker容器中的重要数据放到linux系统中
详细解释:卷就是目录或者文件,可以被于一个或多个容器使用,存在于linux操作系统中,被docker挂载到容器中,提供给容器使用,但不属于联合文件系统,因此能够绕过联合文件系统提供一些用于持续存储或共享数据的特性。卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此docker容器删除的时候不会删除数据卷
如果还不是很清晰,可以看一下这个:Docker容器数据卷-Volume小结
下面的截图也清晰的说明了容器数据卷相当于一个电脑上的U盘一样,如下:
2、–privileged=true
简单来说:让容器在操作linux系统中的容器数据卷具有绝对充足的权限
详细解释:我们会将docker容器中的一些重要内容放到Linux系统中,但是在centos7之中安全模块会比之前的加强,这种目录挂载情况被认为是不安全的行为,如果不进行任何操作,那么容器中的root用户只相当于linux系统的中一个普通用户,当然权限也是受限的,所以我们需要通过--privileged=true
参数保证容器内的root权限和linux系统中的权限相等,这样将数据从容器写到linux系统中就不会出现权限不足的情况了
3、作用
(1)数据卷可以在容器之间共享或者重用数据
详细解释:容器数据卷位于linux操作系统中,那么可以被多个容器所使用,我们将docker容器中的重要内容实时同步到linux系统中的容器数据卷,以便docker容器在误删除的时候恢复,当docker容器删除不会删除linux系统中的备份内容,这种作用相当于redis中的aof和rdb文件
(2)数据卷的更改可以在docker容器中实时生效
(3)数据卷中的更改不会包含在镜像的更新中
(4)数据卷的生命周期一致持续到没有容器使用它为止
4、命令
添加容器数据卷:
docker run -it --privileged=true -v linux宿主机绝对路径:容器绝对路径 镜像名称
例如:
docker run -it -v /tmp/testdocker/:/tmp/testdocker/ ubuntu /bin/bash
注意:如果上述两个目录不存在,当命令执行的时候,会自动创建,记得在目录名称后面添加/
验证容器数据卷是否挂载成功:
docker inspect 容器id/名称
验证结果如下:
禁止容器中写入文件:
对于上面的添加容器数据卷
命令,执行之后在容器中也是可以对文件进行读写操作的,其实相当于docker run -it --privileged=true -v linux宿主机绝对路径:容器绝对路径:rw 镜像名称
,其中rw相当于读写操作
如果需要禁止在容器中执行文件写入操作,只需要给容器数据卷添加一个只读权限就可以了,那么我们只能在linux系统中执行写入操作了,然后命令需要变成docker run -it --privileged=true -v linux宿主机绝对路径:容器绝对路径:ro 镜像名称
,其中ro代表read-only,如果我们在容器中想添加文件,将会出现以下提示:
5、容器数据卷的继承和共享
// 首先要创建容器u1
docker run -it -v /tmp/testdocker/:/tmp/testdocker/ --name="u1" ubuntu /bin/bash
// 然后退出容器u1,创建容器u2,并让u2的容器数据卷继承u1,相当于执行:docker run -it -v /tmp/testdocker/:/tmp/testdocker/ --name="u2" ubuntu /bin/bash
docker run -it --volumes-from u1 --name="u2" ubuntu /bin/bash
注意:我们在容器u1和u2的/tmp/testdocker/目录下、linux操作系统额/tmp/testdocker/目录下面执行的文件操作都是可以互通的,这就完成了容器数据卷的继承和共享
八、docker中常规软件安装
1、总体步骤
- 搜索镜像
- 拉取镜像
- 查看镜像
- 启动镜像
- 停止镜像
- 移除镜像
2、安装tomcat
拉取tomcat8镜像并运行(带jdk)
// 拉取镜像
docker pull billygoo/tomcat8-jdk8
// 找到tomcat8的镜像id
docker images
// 启动tomcat8镜像
docker run -d -p 8080:8080 --name="tomcat8-jdk8" tomcat8镜像id
// 在浏览器上访问http://ip:port/8080/可以查看tomcat首页效果
拓展:拉取最新tomcat镜像并运行
拉取镜像,启动容器:
// 拉取tomcat镜像到本地
docker pull tomcat
// 创建本地tomcat容器
docker run -d -p 8080:8080 tomcat
更改容器中的webapps目录,并在浏览器上访问tomcat:
tomcat 10:
首先通过docker ps看到tomcat容器,在通过docker exec -it 容器id /bin/bash进入tomcat容器之后,我们可以通过ls -l可以看到tomcat的根目录下面有webapp、webapps.dist目录,其中webapp是一个空的目录,那我们使用http://ip:port/8080/只会看到浏览器中展示404,所以我们需要使用rm -rf webapp命令删除webapp目录,而webapp.dist目录里面是之前的内容,所以我们需要使用mv webapp.list webapp进行名称更改,然后我们通过http://ip:port/8080/就能看到具体页面了
低版本tomcat:
启动tomcat之后通过http://ip:port/8080/就能看到具体页面了
3、安装mysql
拉取镜像,启动容器:
// 拉取镜像
docker pull mysql:5.7
// 启动容器
docker run -d --name mysql5.7 -p 3306:3306 --privileged=true --restart=always -v /docker/mysql/log:/var/log/mysql -v /docker/mysql/data:/var/lib/mysql -v /docker/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
// 设置编码方式,避免中文乱码
在/docker/mysql/conf中创建my.cnf文件,然后将下面的内容插入其中并保存;
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
// 重启mysql5.7容器
docker retstart mysql:5.7
// 进入容器
docker exec -it mysql5.7 /bin/bash
注意:
1、启动容器并为root用户设置密码的命令来自于dockerhub官网,如下:
2、启动容器的的命令中断容器数据卷代表日志
、数据
、配置文件
4、安装redis
// 拉取镜像
docker pull redis:6.0.8
// 创建redis.conf所属的目录
mkdir -p /docker/reids/conf
// 创建数据目录
mkdir -p /docker/reids/data
// 将以下链接中的redis.conf文件复制到conf目录下
链接:https://pan.baidu.com/s/1OLPyYh0NcwmXlHIKhFr3dQ?pwd=oq8y
更改参数说明:1、开启密码验证,搜索“requirepass”可见;2、注释“bind 127.0.0.1”,允许外部连接;3、设置“daemonize no”,避免和docker run中-d参数冲突,导致容器启动失败;4、设置“appendonly yes ”,开启容器持久化
// 创建容器
docker run -d -p 6379:6379 --privileged=true --name="redis6.0.8" --restart=always -v /docker/redis/conf/redis.conf:/etc/redis/redis.conf -v /docker/redis/data:/data redis:6.0.8 redis-server /etc/redis/redis.conf
说明:redis-server /etc/redis/redis.conf代表在redis-server启动的时候使用/etc/redis/redis.conf
// 进入容器
docker exec -it redis6.0.8 /bin/bash
5、安装nginx
// 创建前端资源存储目录
mkdir -p /root/nginx/html
// 2、在html下创建index.html测试文件
echo hello > /root/nginx/html/index.html
// 3、启动nginx
docker run -p 18880:80 \
--name nginx-test \
-d --restart=always \
-v /root/nginx/html:/usr/share/nginx/html \
nginx:1.10
4、测试效果
在浏览器上访问http://ip:18880/index.html,只要看到hello就是成功的
6、安装mongodb
// 1、创建数据存储目录
mkdir -p /root/mongodb/data
// 2、启动mongodb
docker run -p 27017:27017 \
--name mongodb-test \
-d --restart=always \
-v /root/mongodb/data:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD=123456 \
mongo
3、访问mongodb
用户名是root,密码是123456
7、安装minio
// 1、创建数据存储目录
mkdir -p /root/minio/data
// 2、启动minio
docker run -p 30024:9000 -p 30427:5000 \
--name minio-test \
-d --restart=always \
-e MINIO_ROOT_USER=admin \
-e MINIO_ROOT_PASSWORD=admin123456 \
-v /root/minio/data:/data \
minio/minio server /data --console-address ":5000"
// 3、访问minio
在浏览器上直接输入http://ip:30427
其中用户名是admin,密码是admin123456
8、安装nacos
1、创建数据库,比如名称叫做nacos,然后在数据库中插入以下sql语句
sql语句来自于:https://github.com/alibaba/nacos/blob/2.1.0/config/src/main/resources/META-INF/nacos-db.sql
2、启动nacos(设置单机模式、数据存储方式为mysql、mysql的相关信息)
docker run -p 18881:8848 -p 18882:9848 \
--name nacos-test \
-d --restart=always \
-e MODE=standalone \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.56.10 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=123456 \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e "MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=10000&socketTimeout=30000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true" \
nacos/nacos-server:v2.1.0
3、访问nacos
在浏览器上直接输入http://ip:18881/nacos
其中用户名和密码都是nacos
sql语句:
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info */
/******************************************/
CREATE TABLE `config_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) DEFAULT NULL,
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) DEFAULT NULL,
`c_use` varchar(64) DEFAULT NULL,
`effect` varchar(64) DEFAULT NULL,
`type` varchar(64) DEFAULT NULL,
`c_schema` text,
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_aggr */
/******************************************/
CREATE TABLE `config_info_aggr` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) NOT NULL COMMENT 'group_id',
`datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
`content` longtext NOT NULL COMMENT '内容',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_beta */
/******************************************/
CREATE TABLE `config_info_beta` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_tag */
/******************************************/
CREATE TABLE `config_info_tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_tags_relation */
/******************************************/
CREATE TABLE `config_tags_relation` (
`id` bigint(20) NOT NULL COMMENT 'id',
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`nid` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`nid`),
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = group_capacity */
/******************************************/
CREATE TABLE `group_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = his_config_info */
/******************************************/
CREATE TABLE `his_config_info` (
`id` bigint(64) unsigned NOT NULL,
`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`data_id` varchar(255) NOT NULL,
`group_id` varchar(128) NOT NULL,
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`content` longtext NOT NULL,
`md5` varchar(32) DEFAULT NULL,
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
`src_user` text,
`src_ip` varchar(20) DEFAULT NULL,
`op_type` char(10) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`encrypted_data_key` text NOT NULL COMMENT '秘钥',
PRIMARY KEY (`nid`),
KEY `idx_gmt_create` (`gmt_create`),
KEY `idx_gmt_modified` (`gmt_modified`),
KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = tenant_capacity */
/******************************************/
CREATE TABLE `tenant_capacity` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
CREATE TABLE `tenant_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`kp` varchar(128) NOT NULL COMMENT 'kp',
`tenant_id` varchar(128) default '' COMMENT 'tenant_id',
`tenant_name` varchar(128) default '' COMMENT 'tenant_name',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
CREATE TABLE users (
username varchar(50) NOT NULL PRIMARY KEY,
password varchar(500) NOT NULL,
enabled boolean NOT NULL
);
CREATE TABLE roles (
username varchar(50) NOT NULL,
role varchar(50) NOT NULL,
constraint uk_username_role UNIQUE (username,role)
);
CREATE TABLE permissions (
role varchar(50) NOT NULL,
resource varchar(512) NOT NULL,
action varchar(8) NOT NULL,
constraint uk_role_permission UNIQUE (role,resource,action)
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
9、安装rabbitmq
1、创建资源目录
mkdir -p /root/rabbitmq/data
2、启动rabbitmq
docker run -p 18883:5672 -p 18884:15672 \
--name rabbitmq-test \
-d --restart=always \
-v /root/rabbitmq/data/var/lib/rabbitmq \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin123456 \
rabbitmq:3.8.9-management
3、访问rabbitmq控制台
在浏览器上访问http://ip:18884
其中用户名是admin,密码是admin123456
10、安装Elasticsearch
// 1、创建目录和文件
mkdir -p /root/elasticsearch/data
mkdir -p /root/elasticsearch/plugin
mkdir -p /root/elasticsearch/config
// 2、填充配置文件
echo "http.host: 0.0.0.0" >> /root/elasticsearch/config/elasticsearch.yml
// 3、为目录授权,不然无法往data中的nodes目录添加数据,原因是权限不够
chmod -R 777 /root/elasticsearch
// 4、添加分词器
可以去这篇文章中的目录四中找分词器:https://blog.csdn.net/qq_42449963/article/details/133211608
// 5、启动Elasticsearch(其中discovery.type=single-node代表单节点,而ES_JAVA_OPTS用来设置堆内存空间)
docker run -p 18885:9200 -p 18886:9300 \
--name es-test \
-d --restart=always \
-v /root/elasticsearch/data:/usr/share/elasticsearch/data \
-v /root/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-v /root/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms512m -Xmx512m" \
elasticsearch:7.6.0
// 6、访问Elasticsearch
在浏览器中输入http://ip:18885能看到es信息就可以了
11、安装Kibana
// 1、启动kibana(ELASTICSEARCH用来设置Elasticsearch的9200端口信息,我直接用的上面启动的Elasticsearch容器)
docker run -p 18887:5601 \
--name kibana-test \
-d --restart=always \
-e ELASTICSEARCH_HOSTS=http://192.168.56.10:18885 \
kibana:7.6.0
九、docker中复杂软件安装(先欠着)
1、mysql主从复制搭建(先欠着)
2、redis集群搭建(先欠着)
十、Dockerfile
1、概念
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本
2、官方文档
https://docs.docker.com/engine/reference/builder/
3、基础知识
- 每条保留字指令都必须为答谢字母,并且指令后面至少要跟一个参数
- 指令执行顺序从上到下,依次执行
- #:表示注释
- 每条指令都会创建一个新的镜像层,并且对镜像进行提交
4、执行流程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器做出修改
- 执行类似于docker commit 的操作提交一个新的镜像层
- docker在基于刚提交的镜像运行一个新的容器
- 执行dockerfile中的下一条指令直到所有指令都执行完成
5、构建三步骤
- 编写Dockfile文件
- 使用docker build命令构建镜像
- 对镜像使用docker run XXX运行容器实例
6、常用保留字指令
注意: 介绍保留字指令的Dockfile参考配置文件地址:https://github.com/docker-library/tomcat/blob/master/10.0/jdk8/corretto/Dockerfile
FROM
当前新镜像是基于哪个镜像的,指令一个已经存在的镜像,例如:FROM amazoncorretto:8
MAINTAINER
镜像维护者的姓名和邮箱地址
RUN
1、作用
容器构建时需要运行的命令
2、格式
(1)shell格式(常用):使用方法是RUN <命令行命令>,其中<命令行命令>等同于在终端操作的shell命令
(2)exec格式:使用方法是RUN ["可执行文件", "参数1", "参数2"],例如RUN ["./test.php", "dev", "offline"]等价于RUN ./test.php dev offline
EXPOST
当前容器对外暴露出的端口,例如:EXPOSE 8080
WROKDIR
指定在创建容器之后,终端默认登录进来的工作目录,比如redis的dockerfile中写着WORKDIR /data
,然后我们使用docker exec……命令登陆之后看到的目录就是/data
USER
指定登录镜像之后的用户,如果不指定,那就代表是root
ENV
用来在构建镜像过程中设置并存储环境变量值,使用方法是:ENV 变量名称 变量值
,然后可以通过$变量名称
在其他地方使用该变量值,例如:
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
ARG
作用:定义Dockerfile作用域中的变量
格式: ARG <name>[=<default value>]
举例:
ARG JAR_FILE=app-kms-wiki-1.0.0.jar
ADD target/${JAR_FILE} app.jar
ARG和ENV区别:
ARG作用域:Dockerfile;只在Dockerfile中生效
ENV作用域:Dockerfile+镜像;在Dockerfile和镜像中都生效
VALUME
容器数据卷,用来进行数据保存和持久化工作,例如:VOLUME /data
,相当于直接启动命令中的docker run …… -v /data:/data ……
,也就是说宿主机和镜像中的该目录是共享的,这也就完成了数据持久化操作
ADD
1、作用
将宿主机目录下的文件拷贝至镜像,并且自动会处理URL和解压压缩包;相当于COPY和解压操作组合;
2、压缩包先改名在解压
如果需要对压缩包改名之后在解压,可以这样做:ADD 压缩包名称 改名后的压缩包名称
COPY
类似于ADD,拷贝宿主机中的文件或者目录到镜像中。将从构建上下文目录中的<源路径>的文件/目录(宿主机)复制到新的一层镜像中的<目标路径>位置,解释如下:
CMD
1、作用
指定容器启动之后需要做的事情
2、启动命令
(1)shell格式:CMD <命令>
(2)exec格式:CMD ["可执行文件", "参数1", "参数2"……]
(3)参数列表格式:CMD ["参数1", "参数2"……],在指定了ENTRYPOINT指令后,用CMD指定具体的参数
3、注意事项
(1)Dockerfile中可以有多个CMD指令,但只有最后一个生效,也就是说后面的CMD指令会覆盖之前所有的CMD指令
(2)CMD指令中的可执行文件会被docker run之后的可执行文件替换
解释:在之前启动tomcat8的时候,我使用的命令是docker run -it 8080:8080 tomcat /bin/bash,通过docker ps也可以看到tomcat容器启动成功,
但是访问localhost:8080却没有任何页面,这说明tomcat并没有启动成功,我们可以来看一下tomcat8的Dockfile文件,如下:
CMD ["catalina.sh", run]
相当于在容器启动之后需要启动tomcat,但是执行上述创建容器的命令之后,这行命令就改变了,如下:
CMD ["/bin/bash", run]
所以tomcat其实并没有真正启动,这就是问题症结所在
4、CMD和RUN的区别
运行时间不同:其中RUN是在docker build的时候运行的,而CMD是在docker run的时候运行的
ENTRYPOINT
1、作用
指定容器启动之后需要做的事情
2、命令格式
ENTERYPOINT ["指令", "参数1", "参数2"……]
3、注意
(1)、可以把CMD写到ENTERYPOINT后面,这里的CMD的作用就变成了为ENTERYPOINT传递参数,比如:
ENTERYPOINT ["指令", "参数1", "参数2"]
CMD["参数3"]
等价于:
ENTERYPOINT ["指令", "参数1", "参数2", "参数3"]
(2)、如果按照上述例子,我们此时使用docker run启动容器,然后在后面docker run后面添加了参数4,
那么按照CMD的使用方法,那么参数3将会被docker run后面的参数4替换掉,案例如下:
Dockerfile中的内容依然是:
ENTERYPOINT ["指令", "参数1", "参数2"]
CMD["参数3"]
创建容器的命令如下:
docker run -it XXX 参数4,
那么上面的Dockerfile的内容变成如下:
ENTERYPOINT ["指令", "参数1", "参数2"]
CMD["参数4"]
等价于:
ENTERYPOINT ["指令", "参数1", "参数2", "参数4"]
实例说明如下:
小总结
Dockerfile编写、构建镜像案例演示(在centos上安装并配置jdk)
素材:
jdk-8u121-linux-x64.tar.gz:https://pan.baidu.com/s/1FQu5gB6nUiLU7U5mttNvhQ,密码:cm55
编写Dockerfile(文件名称:Dockerfile):
# 基础镜像:centos
FROM centos
# 镜像维护者的姓名和邮箱地址
MAINTAINER 明快de玄米61<helloworld@qq.com>
# 定义环境变量
ENV MYPATH /usr/local
# 首次进入容器的位置
WORKDIR $MYPATH
# 安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
# 将jdk安装在/usr/local/java目录下面
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u121-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一目录下
ADD jdk-8u121-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_121
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
# 暴露80端口
EXPOSE 80
# 输出首次进入的目录
CMD echo $MYPATH
CMD echo "success--------------ok"
# 容器启动之后需要执行的命令,那我们就不需要在docker run后面添加/bin/bash了
CMD /bin/bash
构建镜像:
命令如下:
docker build -t centos-java8:1.0 .
对应-t,通过docker build --help的解释如下:
-t, --tag list Name and optionally a tag in the 'name:tag' format
--target string Set the target build stage to build.
--ulimit ulimit Ulimit options (default [])
本次使用第一种解释,上面可以看出镜像的名称centos-java8,而tag是1.0,然后.代表当前目录,代表Dockerfile文件所在的位置
虚悬镜像创建、查询、删除
创建虚悬镜像:
编写Dockerfile文件(名称就是Dockerfile),如下:
FROM centos
CMD echo "successful!"
运行命令,构建镜像,如下:
docker bulid .
本次没有使用-t来设置镜像名称和镜像标签,所以通过docker images看到内容如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 328182347781 7 seconds ago 231MB
查看所有虚悬镜像:
docker image ls -f dangling=true
删除所有虚悬镜像:
// 执行如下命令,然后出现选择项,需要输入y回车
docker image prune
编写Dockerfile发布微服务
创建微服务并运行,保证可以在IDEA中启动之后浏览器可访问,然后打jar包,这个跟着老师操作就可以了,这里提供一下jar包
https://pan.baidu.com/s/1TPOLIhKN_9jQCkSlAf53Pg?pwd=900t
将jar包上传到linux中,之后在同级目录下面编写Dockerfile,如下:
# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER 明快de玄米61
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名springBootDockerTest.jar
ADD docker-demo-0.0.1-SNAPSHOT.jar springBootDockerTest.jar
# 运行jar包
RUN bash -c 'touch /springBootDockerTest.jar'
ENTRYPOINT ["java", "-jar", "/springBootDockerTest.jar"]
# 暴露6001端口,毕竟程序暴露的端口就是6001
EXPOSE 6001
放置路径如下:
构建Dockerfile,生成镜像
docker build -t springbootdockertest:1.0 .
启动springBootDockerTest镜像
docker run -d -p 6001:6001 springbootdockertest
由于微服务中使用的端口是6001,然后我们也需要将6001暴露出来,然后在浏览器上访问ip:6001/端口
十一、docker network
1、docker network 常用命令
// 查看所有docker网络
docker network ls
解释:
NETWORK ID NAME DRIVER SCOPE
网络id 网络名称 驱动 范围
// 查看docker网络/镜像/容器的详细信息
docker inspect id/名称
// 创建docker网络
docker network create 网络名称
// 删除docker网络
docker network rm 网络id/名称
2、在linux宿主机上执行ifconfig命令的解释
情况1:未启动docker
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.139.129 netmask 255.255.255.0 broadcast 192.168.139.255
inet6 fe80::1797:c3de:f94c:2a7 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:64:09:f9 txqueuelen 1000 (Ethernet)
RX packets 1437 bytes 112583 (109.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1069 bytes 103821 (101.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 72 bytes 6260 (6.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 72 bytes 6260 (6.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
ether 52:54:00:c2:8d:e4 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
解释:
ens33就是我们常用的网络,如果在windows机器上执行ipcofnig,可以看到如下:
以太网适配器 VMware Network Adapter VMnet8:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::b994:d4d7:5e45:28fd%9
IPv4 地址 . . . . . . . . . . . . : 192.168.139.1
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . :
所以看到他们和ens33的ip前三位是一致的
而lo就是虚拟机的本地网络,代表localhost
然后virbr0的解释如下:在CentOS7的安装过程中如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的virbr0网卡(virbr0网卡:它还有一个固定的默认IP地址192.168.122.1),是做虚拟机网桥的使用的,其作用是为连接其上的虚机网卡提供 NAT访问外网的功能。
情况2:启动docker
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:20:82:b2:a9 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.139.129 netmask 255.255.255.0 broadcast 192.168.139.255
inet6 fe80::1797:c3de:f94c:2a7 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:64:09:f9 txqueuelen 1000 (Ethernet)
RX packets 1437 bytes 112583 (109.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1069 bytes 103821 (101.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 72 bytes 6260 (6.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 72 bytes 6260 (6.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
ether 52:54:00:c2:8d:e4 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
解释:
可以看出相比于之前的多了一个docker0,如果我们使用docker inspect bridge
,可以看到如下:
[
{
"Name": "bridge",
"Id": "9f79433911aaa5bb259b389bbbfd7a15a52b866089769a148297ebe0f5d5189c",
"Created": "2022-02-02T18:39:32.703246041+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
其中倒数第6行就是我们在linux宿主机上执行ifconfig
命令后docker0
的出处
3、四大docker网络模式
3.1、总览
3.2、 docker容器的ip会发生变动
// 拉取ubuntu镜像
docker pull ubuntu
// 创建ubuntu容器,名称叫做u1
docker run -it --name u1 ubuntu // 记得使用Ctrl+p+q退出
// 创建ubuntu容器,名称叫做u2
docker run -it --name u2 ubuntu // 记得使用Ctrl+p+q退出
// 查看容器名称为u1的容器详细信息
docker inspect u1 | tail -n 20
解释:信息如下:
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "9f79433911aaa5bb259b389bbbfd7a15a52b866089769a148297ebe0f5d5189c",
"EndpointID": "f30f0369ef17ce53019a36ce1fb4b0bed8db7e8c53b2f3a81e7b1bab18d2bb3f",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
可以看出网络模式是bridge模式,而IPAddress是172.17.0.2
// 查看容器名称为u2的容器详细信息
docker inspect u2 | tail -n 20
解释:信息如下:
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "9f79433911aaa5bb259b389bbbfd7a15a52b866089769a148297ebe0f5d5189c",
"EndpointID": "4627925092ee5bc045a3ea77c2051790418be30f8e60cdda4a233240d6080dcd",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
}
]
可以看出网络模式是bridge模式,而IPAddress是172.17.0.3
// 删除容器名称为u2的容器,创建名称为u2的ubuntu容器,并查看容器名称为u3的容器详细信息
docker rm -f u2
docker run -it --name u3 ubuntu // 记得使用Ctrl+p+q退出
docker inspect u3 | tail -n 20
解释:信息如下:
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "9f79433911aaa5bb259b389bbbfd7a15a52b866089769a148297ebe0f5d5189c",
"EndpointID": "0446438ebdaed3a9a112e66beda7ccc5e4b95c643d2cd6c770cfb8e0cc59ba05",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
}
]
可以看出网络模式是bridge模式,而IPAddress是172.17.0.3,因此可以说明容器被删除之后,它原有的ip就会变成其他容器的ip地址
3.3、bridge
3.3.1、概念
Docker服务默认会创建一个 docker0网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理网卡或虚拟网卡。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,docker0网桥的作用是主机和容器之间互相通信的桥梁,这就将所有容器和本地主机都放到同一个物理网络。
3.3.2、说明
- docker run命令执行的时候,如果不指定网桥模式的话,使用的就是bridge模式,在docker容器启动之后,会在linux虚拟机中虚拟一个docker容器网桥(docker0),而通过bridge模式启动的容器,将会以docker0的ip地址作为网关,并根据网关的前三段不变原则分配对应的ip地址,在上面的命令中可以通过
docker inspect 容器id/名称 | tail -n 20
查看容器使用的网桥模式和ip地址 - 网桥docker0将会创建对等的虚拟设备接口,其中一个叫veth,另一个叫eth0,由于所有docker容器都和网桥docker0连接在一起,而网桥docker0和linux宿主机连接在一起,所以容器之间、容器和宿主机都是可以相互通信的。
3.3.3、验证
执行命令如下:
// 创建tomcat8081容器
docker run -d -p 8081:8080 --name tomcat8081 billygoo/tomcat8-jdk8
// 创建tomcat8082容器
docker run -d -p 8082:8080 --name tomcat8082 billygoo/tomcat8-jdk8
// 在新窗口登录tomcat8081容器
docker exec -it tomcat8081 /bin/bash
// 在新窗口登录tomcat8082容器
docker exec -it tomcat8082 /bin/bash
在Linux宿主机执行ip addr
命令,结果如下:
在tomcat8081
容器内部执行ip addr
命令,如下:
在tomcat8082
容器内部执行ip addr
命令,如下:
对比发现:linux宿主机中是19: veth67b4e46@if18
和23: veth76b3f9f@if22
,然后tomcat8081
容器中是18: eth0@if19
,但是tomcat8082
容器中是22: eth0@if23
,这也印证了上面图片中docker0网关veth和容器eth0一一对应的情况
3.4、host
3.4.1、概念
直接复用宿主机的ip地址与外界通信,不在通过docker0网关进行转换
3.4.2、说明
容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,而是使用宿主机的IP和端口。如果容器想使用的端口已经被占用了,那么容器所用端口就会在原来的基础上递增,直到找到合适端口,假设8080端口已经被其他容器占用了,然后tomcat容器使用host模式启动,那么这个tomcat容器将会使用8081端口
3.4.3、验证
执行命令如下:
docker run -d --network host --name tomcat8083 billygoo/tomcat8-jdk8
由于network模式是host模式,所以tomcat容器和linux宿主机共享ip和端口,因此容器的默认端口就是所使用的端口,如果存在端口被占用的情况,使用端端口就会递增,所以不用使用-p命令设置端口。当然如果使用了-p设置端口,也不会起到任何作用,和不使用-p是一样的道理,并且会出现警告WARNING: Published ports are discarded when using host network mode
如果我们进入上面创建的容器内部执行ip addr
命令,可以看到在linux宿主机中执行ip addr
命令是一样的效果
然后我们可以访问http://ip:8080
来验证一下,当然最好在linux的浏览器中验证,避免效果不正确
3.5、none
3.5.1、概念
在none模式下,并不为Docker容器进行任何网络配置。 也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo。需要我们自己为Docker容器添加网卡、配置IP等。也就是禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)
3.5.2、验证
执行命令如下:
docker run -d --network none --name tomcat8084 billygoo/tomcat8-jdk8
进入容器之后,使用ip addr
的结果、在linux宿主机中查看容器详细信息如下:
3.6、container
3.6.1、概念
新创建容器依赖于已经创建的容器,并且和已创建的容器共用同一套ip和port,我们通过ip addr
命令在上述两个容器中可以看到同样的结果,除了网络方面,其他例如文件系统、进程列表是隔离的
3.6.2、验证
由于新创建容器和原有容器共用同一套ip和port,所以不能使用tomcat进行测试,毕竟tomcat的端口会冲突的,所以我们使用alpine(小巧的tomcat)来演示,执行命令如下:
// 拉取alpine
docker pull alpine
// 创建容器alpine1
docker run -it --name alpine1 alpine:latest
// 执行ip addr命令,执行完成后使用Ctrl+p+q退出
ip addr
// 创建容器alpine2
docker run -it --name alpine1 alpine:latest
// 执行ip addr命令,千万不要退出,不然就无法登录进来了,毕竟等会还要执行ip addr呢
ip addr
执行效果如下:
由于容器alpine2
依附于容器alpine1
,我们可以新开一个窗口执行docker stop alpine1
, 然后我们此时停止容器alpine1
,再看容器alpine2
的网络状态如下:
可以只剩余一个lo
了
3.7、自定义网络
3.7.1、概念
自定义网络本身就维护好了容器名和ip的对应关系,我们使用ip或者容器名都可以ping通对应的容器
3.7.2、解决痛点
如果两个容器需要通信,我们不能写死ip,毕竟ip可能在容器重启之后就会发生变化,所以我们需要写死的是容器名称,那么就需要让两个容器之间可以通过容器名称进行通信,这就需要使用是自定义器网络
这种情况在搭建集群的时候经常要使用,比如redis集群之间的互相通信要使用容器名称而不是ip
3.7.3、验证
执行命令如下:
// 创建自定义网络,其中custom_nework是自定义网络名称
docker network create custom_network
// 创建容器tomat81,使用自定义网络
docker run -it -p 8081:8080 --network custom_network --name tomcat81 billygoo/tomcat8-jdk8
// 创建容器tomat82,使用自定义网络,记得执行下面命令需要新开一个窗口
docker run -it -p 8082:8080 --network custom_network --name tomcat82 billygoo/tomcat8-jdk8
// 在容器tomcat81中执行ping命令,发现可以ping通
ping tomcat82
// 在容器tomcat82中执行ping命令,发现可以ping通
ping tomcat81
在集群搭建的时候我们不再写死ip了,只需要写死容器名称就可以了,再也不用担心容器重启之后ip会发生变化的问题了,这也使得docker容器网络得到了很好的规划
十二、compose
1、安装compose
(1)找到安装文档位置
首先登录官网,然后找到安装文档位置,如下:
(2)安装compose
记得登录root用户身份,然后在执行下面的命令:
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
(3)给docker-compose赋予可执行权限
chmod +x /usr/local/bin/docker-compose
(4)验证compose版本
docker-compose --version
如果出现docker-compose version 1.29.2, build 5becea4c
就说明compose安装成功了
2、卸载compose
首先登录官网,然后找到卸载文档位置,如下:
由于我们使用curl命令安装,所以执行命令如下:
rm /usr/local/bin/docker-compose
3、compose相关知识点
3.1、概念
Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动 / 关闭这些容器
3.2、解决痛点
部署一个web微服务项目,不仅包含微服务容器本身,还包括redis、mysql等容器,如果使用docker run命令,那么这些容器全部启动和关闭就太累了,所以docker官方给我们提供了docker-compose多服务部署的工具。Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器,这也被称作是一个项目(project)。
3.3、compose文件名称
docker-compose.yml
3.4、compose服务和工程
服务:
一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器
工程:
由一组关联的应用容器组成的一个完整业务单元,需要在 docker-compose.yml 文件中定义
3.5、compose使用步骤
步骤1:
编写各个微服务应用对应的Dockerfile文件,并且构建出对应的镜像(不包括redis、mysql等已经形成的镜像)
步骤2:
编写docker-compose.yml,用来定义一个完整业务单元,安排好整体应用中的各个容器服务。
步骤3:
执行docker-compose up命令来启动并运行整个应用程序,完成一键部署上线
4、compose常用命令
docker-compose -h # 查看帮助
docker-compose up # 启动所有docker-compose服务(控制台会出现日志),即启动docker-compose.xml
docker-compose up -d # 启动所有docker-compose服务并后台运行
docker-compose down # 停止并删除容器、网络、卷、镜像。
docker-compose exec yml里面的服务id # 进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker-compose ps # 展示当前docker-compose编排过的运行的所有容器
docker-compose top # 展示当前docker-compose编排过的容器进程
docker-compose logs yml里面的服务id # 查看容器输出日志
docker-compose config # 检查配置
docker-compose config -q # 检查配置,有问题才有输出
docker-compose restart # 重启服务
docker-compose start # 启动服务
docker-compose stop # 停止服务
5、编写docker-compose.xml发布微服务
5.1、创建微服务镜像
创建微服务并运行,保证可以在IDEA中启动之后浏览器可访问,然后打jar包,这个跟着老师操作就可以了,这里提供一下jar包
https://pan.baidu.com/s/1TPOLIhKN_9jQCkSlAf53Pg?pwd=900t
将jar包上传到linux中,之后在同级目录下面编写Dockerfile,如下:
# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER 明快de玄米61
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名springBootDockerTest.jar
ADD docker-demo-0.0.1-SNAPSHOT.jar springBootDockerTest.jar
# 运行jar包
RUN bash -c 'touch /springBootDockerTest.jar'
ENTRYPOINT ["java", "-jar", "/springBootDockerTest.jar"]
# 暴露6001端口,毕竟程序暴露的端口就是6001
EXPOSE 6001
放置路径如下:
构建Dockerfile,生成镜像
docker build -t springbootdockertest:1.0 .
5.2、编写docker-compose.yml
# compose版本需要是3,这和docker版本相对应,文档地址:https://docs.docker.com/compose/compose-file/compose-file-v3
version: "3"
# services下面放置所有服务
services:
# 微服务名称是microService
microService:
# springbootdockertest:1.0是镜像名称和标签
image: springbootdockertest:1.0
# 指定容器名称
container_name: microService01
# 指定容器端口映射
ports:
- "6001:6001"
# 指定容器外挂地址
volumes:
- /app/microService:/data
# 指定容器所使用的网络
networks:
- atguigu_net
# 所依赖服务,也就是下面两个先启动才能启动该微服务容器
depends_on:
- redis
- mysql
redis:
image: redis:6.0.8
ports:
- "6379:6379"
volumes:
- /app/redis/redis.conf:/etc/redis/redis.conf
- /app/redis/data:/data
networks:
- atguigu_net
# 容器启动完成需要执行的命令
command: redis-server /etc/redis/redis.conf
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: '123456'
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'db2021'
MYSQL_USER: 'zzyy'
MYSQL_PASSWORD: 'zzyy123'
ports:
- "3306:3306"
volumes:
- /app/mysql/db:/var/lib/mysql
- /app/mysql/conf/my.cnf:/etc/my.cnf
- /app/mysql/init:/docker-entrypoint-initdb.d
networks:
- atguigu_net
#解决外部无法访问的问题
command: --default-authentication-plugin=mysql_native_password
# 创建网络,其中atguigu_net是网络名称,网络名称后面的:不能缺少
networks:
atguigu_net:
放置路径如下:
5.3、启动compose
docker-compose up -d
5.4、创建测试环境
启动完成之后,使用docker ps
找到mysql容器的容器id,使用docker exec -it mysql容器id /bin/bash
进入容器,使用mysql -uroot -p123456
登录root用户,在命令行执行create database db2021;
创建数据库,然后使用use db2021;
切换数据库,然后执行如下建表语句:
CREATE TABLE `t_user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',
`password` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
`sex` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ',
`deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表'
5.5、访问swagger进行微服务测试
首先在windows浏览器上访问http://ip:6001/swagger-ui.html
,然后访问数据库新增3条记录接口
,如下:
之后访问查询1条记录
接口,填写id等于1,点击Execute按钮查询用户信息,如下:
5.6、停止并删除容器
docker-compose down
5.7、难点解释
1、微服务项目中application.properties文件中使用的不是ip,而是服务名称,这场docker network中的知识,虽然我们在docker network中使用的是容器名称,本次使用的是服务名,可能在compose中使用的就是服务名
application.properties中用到的服务名称就是docker-compose.yml
文件中services
下面的服务名称,docker-compose.yml如下:
我们可以看一下微服务项目中application.properties中的配置信息,如下:
十三、Portainer
1、安装Portainer
1.1、Protainer官网
1.2、找到在Linux中安装Portainer的文档
点击Install,如下:
找到安装文档位置,如下:
1.3、安装前提要求
(1)docker安装并运行(2)启动docker的用户身份是root用户
1.4、安装命令
在linux上执行命令如下:
docker run -d -p 8000:8000 -p 9000:9000 -p 9443:9443 --name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:2.11.0
这些命令来自于官网,如下:
其中9443使用https访问,而9000使用http访问
命令中的--restart=always
代表当docker重启之后portainer也会重启,当我们把docker和portainer启动之后,可以使用systemctl restart docker
重启docker,然后通过docker ps
看一下portainer是否重启成功
1.5、登录控制台
// 方法1:
https://ip:9443
// 方法2:
http://ip:9000
首次登录之后需要设置用户名和密码,其中密码可以设置为12345678
,用户名是admin,进入控制台首页之后,点击localhost进行本地控制台,如下:
1.6、常规操作
查看容器信息:
发布容器:
十四、CIG(CAdvisor收集 + InfluxDB存储 + Granfana展示)
1、概念
CAdvisor监控收集+InfluxDB存储数据+Granfana展示图表,如下图:
三种容器作用分别如下:
2、创建并启动cig三容器
2.1、在/usr/local下面创建cig文件夹
2.2、在上一步创建的cig文件夹中创建docker-compose.yml,内容如下
version: '3.1'
volumes:
grafana_data: {}
services:
influxdb:
image: tutum/influxdb:0.9
restart: always
environment:
- PRE_CREATE_DB=cadvisor
ports:
- "8083:8083"
- "8086:8086"
volumes:
- ./data/influxdb:/data
cadvisor:
image: google/cadvisor
links:
- influxdb:influxsrv
command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
restart: always
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
grafana:
user: "104"
image: grafana/grafana
user: "104"
restart: always
links:
- influxdb:influxsrv
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- HTTP_USER=admin
- HTTP_PASS=admin
- INFLUXDB_HOST=influxsrv
- INFLUXDB_PORT=8086
- INFLUXDB_NAME=cadvisor
- INFLUXDB_USER=root
- INFLUXDB_PASS=root
2.3、启动docker-compose文件
docker-compose up -d
2.4、检查3个容器是否启动
docker ps
结果如下:
3、使用cig
3.1、访问三容器的控制台
// 浏览cAdvisor收集服务
http://ip:8080
// 浏览influxdb存储服务
http://ip:8083
// 浏览grafana展现服务
http://ip:3000
3.2、influxdb使用说明
3.3、grafana使用说明
3.3.1、登录信息
用户名:admin
密码:admin
3.3.2、配置数据源
本次使用的数据源是influxdb,首先选择数据源,如下:
设置docker-compose中的服务名为数据库ip,如下:
配置数据库、用户名、密码,如下:
只要看到Data source is working
就代表数据库连接成功了
3.3.3、添加仪表盘查看数据
点击添加仪表盘按钮,如下:
选择数据展示方式,如下:
选择图表展示方式,如下:
设置仪表盘参数,点击右上角的save即可,如下:
生成仪表盘结果如下:
十五、docker小知识点
docker run XXX执行过程: 本地寻找(1、存在:创建容器;2、不存在:去远程仓库查找)》远程仓库查找(1、存在:拉取镜像之后创建容器;2、不存在:报错)
虚悬镜像: 如果使用docker images发现某镜像的镜像名称和标签名称都是<none>
,那就是虚悬镜像(注意:这种镜像毫无作用,建议删除虚悬镜像)
更多推荐
所有评论(0)