【Docker】完整的搭建和发布过程

【Docker】完整的搭建和发布过程

【一】Mac版虚拟机CentOS搭建

【1】shell和ftp工具选择

选择是的mac版termius

【2】linux 命令 ip a / ip addr / ifconfig 不显示ip问题

原因:CentOS 7.x 默认不开启网卡

解决:修改ens33网卡配置文件

(1)如果没有 ifcfg-ens33文件 修改 ifcfg-eth0

cd etc/sysconfig/network-scripts/

vi ifcfg-ens33

vi ifcf-ens33 修改(ONBOOT=no)-> (ONBOOT=yes)

在这里插入图片描述保存文件

(2)重启网关服务器

命令:systemctl restart network
就可以了
在这里插入图片描述

【二】Docker安装

【1】Docker的安装

(1)查看系统的内核版本

uname -r 4.18.0-80.11.2.el8_0.x86_64

执行命令:uname -r
注意:x86 64位系统,如果是32位是不能安装 docker 的

(2)yum更新到最新版本

sudo yum -y update

执行命令:sudo yum update
注意:看到显示 Complete 就代表完成了,整个过程需要 5-10 分钟左右

更新gcc(C语言的编译环境)

yum -y install gcc
yum -y install gcc-c++

(3)安装Docker所需的依赖包

sudo yum install -y yum-utils device-mapper-persistent-data lvm2

执行命令:sudo yum install -y yum-utils device-mapper-persistent-data lvm2
注意:看到显示 Complete 就代表完成了,整个过程需要 1-3 分钟左右

(4)设置Docker的yum的源

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

(5)更新yum软件包索引

yum makecache fast

(6)查看仓库所有Docker版本

yum list docker-ce --showduplicates | sort -r

(7)安装Docker

安装默认最新版本的Docker

yum -y install docker-ce docker-ce-cli containerd.io

(8)启动Docker并添加开机自启动

启动Docker

sudo systemctl start docker

设置开机启动Docker

systemctl enable docker

重启docker

systemctl restart docker

停止docker

systemctl stop docker

(9)查看Docker版本

docker --version

(10)测试

ps -ef|grep docker
docker version

(11)卸载Docker

systemctl stop docker
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

(12)Docker常用命令

[root@CodeGuide ~]# docker --help				#Docker帮助
[root@CodeGuide ~]# docker --version			#查看Docker版本
[root@CodeGuide ~]# docker search <image>		#搜索镜像文件,如:docker search mysql
[root@CodeGuide ~]# docker pull <image>		#拉取镜像文件, 如:docker pull mysql
[root@CodeGuide ~]# docker images				#查看已经拉取下来的所以镜像文件
[root@CodeGuide ~]# docker rmi <image>		#删除指定镜像文件
[root@CodeGuide ~]# docker run --name <name> -p 80:8080 -d <image>		#发布指定镜像文件
[root@CodeGuide ~]# docker ps					#查看正在运行的所有镜像
[root@CodeGuide ~]# docker ps -a				#查看所有发布的镜像
[root@CodeGuide ~]# docker rm <image>			#删除执行已发布的镜像

(13)如何创建自启动的容器

(1)还没run创建容器的
使用 docker run 命令运行时,增加 --restart=always 参数即可

(2)已运行的容器修改其自启动策略
执行命令:
docker update --restart=always 容器名或容器ID
docker container update --restart=【容器策略】 容器名称

# no 容器退出时不重启容器
# on-failure 只有在非零状态退出时才重新启动容器
--restart=on-failure:【重启次数】
# always 无论退出状态如何都

【2】阿里云镜像加速

(1)获取阿里云加速器地址

登陆阿里云,点击控制台,然后点击菜单,找到“容器镜像服务”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YRAD3MdN-1672584376343)(evernotecid://9B99E324-7852-4A64-95A3-727CD2F9CB64/appyinxiangcom/12234224/ENResource/p1677)]

创建个人容器镜像托管服务

然后点击镜像工具,进入镜像加速器,即可看到阿里云加速器地址,把这个加速器地址配置到docker容器里
在这里插入图片描述

(2)创建文件夹并执行脚本

先创建文件夹

mkdir -p /etc/docker

执行脚本

tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://xqybwad5.mirror.aliyuncs.com"]
}
EOF

(3)重新加载配置文件

systemctl daemon-reload

(4)重新启动docker

systemctl restart docker

(5)查看 daemon.json 是否已经生效了

tail /etc/docker/daemon.json

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w2MT66LX-1672584376344)(evernotecid://9B99E324-7852-4A64-95A3-727CD2F9CB64/appyinxiangcom/12234224/ENResource/p1679)]

【三】环境容器的搭建

【1】安装Portainer

(1)拉取最新的Portainer镜像

docker pull portainer/portainer

(2)运行镜像(9000)

docker run -d -p 9000:9000 -v /root/portainer:/data -v /var/run/docker.sock:/var/run/docker.sock --name dev-portainer portainer/portainer

或者

docker run -d --restart=always --name portainer -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer

参数说明:

-d #容器在后台运行
-p 9000:9000 # 宿主机9000端口映射容器中的9000端口
-v /var/run/docker.sock:/var/run/docker.sock # 把宿主机的Docker守护进程(docker daemon)默认监听的Unix域套接字挂载到容器中
-v /root/portainer:/data # 把宿主机目录 /root/portainer 挂载到容器 /data 目录;
–name dev-portainer # 指定运行容器的名称

注意:在启动容器时必须挂载本地 /var/run/docker.socker与容器内的/var/run/docker.socker连接。

(3)访问Portainer可视化界面

(1)浏览器中输入:服务器的ip地址:9000,访问portainer可视化界面
第一次会弹出安装界面,配置账号密码、选择是本地Docker还是远程Docker,一般我们选择本地Docker,也就是local,可以查看宿主机配置信息、查看容器、镜像、网络、卷等相关信息。

在这里插入图片描述
(2)创建登录账号和密码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(4)一些问题的解决

(1)镜像错误,停掉&删除&重新创建
docker ps 查看正在运行的镜像
docker stop 镜像id 停止正在运行的镜像
docker rm 镜像id 停止正在运行的镜像
(2)9000端口访问不到,测试是否启动成功,以及关闭防火墙
在主机上访问映射了Portainer容器的端口,看容器是否正常运行
curl localhost:9000

由图可知能通过curl命令正常访问8088端口

关闭所有防火墙
service firewalld status
service firewalld stop
(3)

【2】安装JDK8

(1)查找JDK

docker search jdk

在这里插入图片描述
(2)拉取JDK1.8镜像
从上面列表里选取一个拉取

docker pull java

(3)查看下载的镜像

docker images

在这里插入图片描述
(4)启动JDK镜像

docker run -di --name=jdk8 java

(5)查看镜像运行情况

docker ps

在这里插入图片描述
(6)进入镜像

docker exec -it jdk8 /bin/bash

查看jdk版本
在这里插入图片描述
退出镜像

exit

(7)镜像的运维
停止镜像:docker stop jdk8
启动镜像:docker start jdk8
重启镜像:docker restart jdk8
删除容器:

# 1.查看历史所有容器
docker ps -a
# 2.删除容器
docker rm 容器id

【3】安装redis

(1)拉取redis镜像

docker pull redis:6.0.8

(2)在宿主机下新建目录/app/redis

在 SFTP 工具链接的云服务器中创建文件夹 /data/redis、/data/redis/data 你也可以在云服务器的控制台使用命令进行创建

sudo mkdir -p /data/redis
sudo mkdir -p /data/redis/data

把修改后的 redis.conf 文件通过 SFTP 上传到 /data/redis 文件夹下
在这里插入图片描述
新建一个redis.conf

touch redis.conf

也可以复制一个进去,下载地址:redis.conf

注意的是redis.conf里的内容要修改
【必须】bind 127.0.0.1 把#号注释掉这部分,使redis可以外部访问
【必须】daemonize 修改为no 用守护线程的方式启动
【必须】requirepass 设置你的Redis链接密码(也可以不设置)
【必须】appendonly 修改为yes,redis持久化  默认是no
【可选】tcp-keepalive 300 防止出现远程主机强迫关闭了一个现有的连接的错误 默认是300

#关闭保护,用于测试
protected-mode no
port 6379

(3)启动redis(6379)

docker run -p 6379:6379 --name redis6 -v /data/redis/redis.conf:/etc/redis/redis.conf  -v /data/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf --appendonly yes

解释

-p 6379:6379:把容器内的6379端口映射到宿主机6379端口
-v /data/redis/redis.conf:/etc/redis/redis.conf:把宿主机配置好的redis.conf放到容器内的这个位置中
-v /data/redis/data:/data:把redis持久化的数据在宿主机内显示,做数据备份
redis-server /etc/redis/redis.conf:这个是关键配置,让redis不是无配置启动,而是按照这个redis.conf的配置启动
–appendonly yes:redis启动后数据持久化

查看

sudo docker ps

在这里插入图片描述

查看日志

sudo docker logs redis6

在这里插入图片描述
没有报错,启动成功

(4)查看Portainer的页面

在这里插入图片描述

(5)使用本地RDM链接redis

这个时候你可能还是链接不上云服务器中的 Redis 服务,那么需要设置下防火墙,默认情况下可能你的防火墙并没有开启,需要手动执行:
1-启动防火墙 systemctl start firewalld
2-设置Redis 6379 端口:firewall-cmd --zone=public --add-port=6379/tcp --permanent
3-设置Portainer 9000 端口:firewall-cmd --zone=public --add-port=9000/tcp --permanent
4-重新加载:firewall-cmd --reload

配置redis
在这里插入图片描述
测试redis
在这里插入图片描述

(6)使用redis容器的终端链接redis

docker exec -it redis6 /bin/bash

在这里插入图片描述

(7)运维命令

(1)删除已经启动的镜像(假如多启动了一个名字为redis)
停止镜像:docker stop redis
删除镜像:docker rm -rf 镜像id
删除容器:docker rmi 镜像id

(2)启动redis:docker start redis6
(3)重启redis:docker restart redis6

【5】安装redis集群

(1)面试题

1-2亿条数据需要缓存,请问如何设计这个存储案例?
单机单台100%不可能,肯定是分布式存储,用redis如何落地?既然是分布式,那么一个数据落在哪一台服务器上?能不能保证下次读的时候也是从那一台服务器上读出来?

2亿条记录就是2亿个k-v,我们单机不行,必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:hash(key)%N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。

(1)哈希取余分区
在这里插入图片描述在这里插入图片描述(2)一致性哈希算法分区
在这里插入图片描述(3)哈希槽分区

(2)搭建三主三从redis集群

(1)新建6个docker容器实例

docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381

docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382

docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383

docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384

docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385

docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386

在这里插入图片描述
在这里插入图片描述
(2)进入容器redis-node-1并为6台机器构建集群关系

docker exec -it redis-node-1 /bin/bash
redis-cli --cluster create 192.168.19.11:6381 192.168.19.11:6382 192.168.19.11:6383 192.168.19.11:6384 192.168.19.11:6385 192.168.19.11:6386 --cluster-replicas 1

–cluster-replicas 1 表示为每个master创建一个slave节点

在这里插入图片描述
在这里插入图片描述
(3)链接进入6381作为切入点,查看节点状态

redis-cli -p 6381
cluster info

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)主从容错切换迁移案例

(1)数据读写存储
首先进入6381,尝试存储数据,发现有的数据槽位超过了6381分配的槽位,那么就会报错

docker exec -it redis-node-1 /bin/bash

单机模式连接

redis-cli -p 6381

在这里插入图片描述改成用集群方式连接,优化路由

redis-cli -p 6381 -c

在这里插入图片描述(2)容错切换迁移(测试主从切换)
首先在6381主机中查看集群信息
在这里插入图片描述停掉6381主机
在这里插入图片描述重新进入6382

docker exec -it redis-node-2 /bin/bash
redis-cli -p 6382 -c

查看集群信息,可以看到原来的6386从机已经变成了主机
在这里插入图片描述把6381启动以后,6381变成了新的从机,要想把6381重新变为主机,可以把现在6386停掉再重启

(4)主从扩容案例

(1)新建6387、6388两个节点,新建后启动,查看是否是8个节点

docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387

docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388

docker ps

在这里插入图片描述
(2)进入6387容器实例内部

docker exec -it redis-node-7 /bin/bash

(3)把新增的6387节点(空槽位)作为master节点加入原集群
把新增的6387作为master节点加入集群,6381就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群

redis-cli --cluster add-node 192.168.19.11:6387 192.168.19.11:6381

在这里插入图片描述(4)第1次检查集群情况

redis-cli --cluster check 192.168.19.11:6381

在这里插入图片描述
(5)重新分派槽号给6387

redis-cli --cluster reshard 192.168.19.11:6387

给新分配4096个槽位
在这里插入图片描述然后输入all,从每一个槽位上取一些过来

(6)第2次检查集群情况

redis-cli --cluster check 192.168.19.11:6381

在这里插入图片描述
(7)为主节点6387分配从节点6388
最后的编号是6387的编号

redis-cli --cluster add-node 192.168.19.11:6388 192.168.19.11:6387 --cluster-slave --cluster-master-id 9322efd4b8f57d0c01fccc2d2ba310021781f74f

(8)第3次检查集群情况

redis-cli --cluster check 192.168.19.11:6381

在这里插入图片描述

(5)主从缩容案例

(1)检查集群情况1获取6388的节点ID

redis-cli --cluster check 192.168.19.11:6382

(2)把6388删除,从集群中把4号从节点6388删除
最后跟的节点ID就是6388的节点ID

redis-cli --cluster del-node 192.168.19.11:6388 2e4ec79d0731b36c01a8d3739e30c67551b76eeb

(3)把6387的槽号清空,重新分配,本例把清出来的槽号都给6381

redis-cli --cluster reshard 192.168.19.11:6381

在这里插入图片描述
然后输出done表示结束
在这里插入图片描述
(4)第2次检查集群情况

redis-cli --cluster check 192.168.19.11:6382

在这里插入图片描述(5)把6387删除
最后跟的节点ID就是6387的节点ID

redis-cli --cluster del-node 192.168.19.11:6387 9322efd4b8f57d0c01fccc2d2ba310021781f74f

(6)第3次检查集群情况

redis-cli --cluster check 192.168.19.11:6382

可以看到没有6387的节点了

在这里插入图片描述

【6】安装kafka

(1)下载镜像

docker pull wurstmeister/kafka
docker pull wurstmeister/zookeeper

(2)启动zookeeper(2181)

docker run -d --name zookeeper -p 2181:2181 -t wurstmeister/zookeeper

(3)启动kafka(9092)

docker run -d --name kafka \
-p 9092:9092 \
-e KAFKA_BROKER_ID=0 \
-e KAFKA_ZOOKEEPER_CONNECT=换成你的服务器IP:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://换成你的服务器IP:9092 \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 wurstmeister/kafka

把这个整体命令复制到后台运行,运行前要把服务器IP换成你的

(4)防火墙设置

这里我们需要把 Zookeeper、Kafka 的端口对外开放;
1-设置zk 2181 端口:firewall-cmd --zone=public --add-port=2181/tcp --permanent
2-设置Kafka 9092 端口:firewall-cmd --zone=public --add-port=9092/tcp --permanent
3-重新加载:firewall-cmd --reload

(5)kafka日志

在这里插入图片描述在这里插入图片描述在 Docker 容器中可以点击 Kafka 进入日志查看和控制台操作

(6)Kafka 控制台操作

在这里插入图片描述
在 Kafka 控制台可以操作配置文件,查看日志,添加Topic

创建topic lottery_activity_partake

in/kafka-topics.sh --create --zookeeper 172.17.0.3:2181 --replication-factor 1 --partitions 1 --topic lottery_activity_partake

创建topic lottery_invoice

bin/kafka-topics.sh --create --zookeeper 172.17.0.3:2181 --replication-factor 1 --partitions 1 --topic lottery_invoice

创建Topic的时候,地址需要换成自己zookeeper的地址

(7)待补充

客户端操作
图形化管理工具

【7】安装mysql(3306)

(1)拉取镜像:docker pull mysql:5.7
(2)查看本地镜像:docker images
(3)创建一个mysql容器,首先在根目录下创建好一个文件夹allenuse
在这里插入图片描述

(4)运行容器:docker run -d -p 3306:3306 --privileged=true -v /allenuse/mysql/log:/var/log/mysql -v /allenuse/mysql/data:/var/lib/mysql -v /allenuse/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql5 mysql:5.7

如果报错的话,可能是端口3306被占用了,就用下面的命令解决
1-先查看当前占用端口:netstat -tanlp
2-杀死对应的进程:kill 1330
在这里插入图片描述(5)查看是否创建成功
1-查看容器:docker ps 或者 docker ps -a
2-查看启动日志:docker logs mysql5

(6)新建my.cnf,通过容器卷同步给mysql容器实例(解决中文乱码问题)

cd /allenuse/mysql/conf/

vi my.cnf

在这里插入图片描述

[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8

(7)重启mysql容器实例,再重新进入并查看字符编码
1-重启:docker restart mysql5
2-查看字符编码:docker exec -it mysql5 /bin/bash

在这里插入图片描述(8)新建库新建表再插入中文测试

(9)如果不小心把mysql的容器删除了如何恢复
之前已经配置了容器卷,mysql的数据已经在本地存储了,只需要重新执行创建容器的命令就行了

docker run -d -p 3306:3306 --privileged=true -v /allenuse/mysql/log:/var/log/mysql -v /allenuse/mysql/data:/var/lib/mysql -v /allenuse/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql5 mysql:5.7

(10)防火墙设置
1-设置mysql 3306 端口:firewall-cmd --zone=public --add-port=3306/tcp --permanent
2-重新加载:firewall-cmd --reload

(11)本地连接
在这里插入图片描述
在这里插入图片描述
(12)如果3306端口被占用了怎么处理
1-先查看当前占用端口:netstat -tanlp
2-杀死对应的进程:kill 1330

【8】安装mysql主从复制

(1)新建主服务器容器实例3307

docker run -p 3307:3306 --name mysql-master -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/lib/mysql -v /mydata/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7

在这里插入图片描述

(2)进入/mydata/mysql-master/conf目录下新建my.cnf

在这里插入图片描述

[mysqld]
##设置server-id,同一局域网中需要唯一
server_id=101
##指定不需要同步的数据库名称
binlog-ignore-db=mysql
##开启二进制日志功能
log-bin=mall-mysql-bin
##设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
##设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
##二进制日志过期清理时间。默认值为0,表示不自动清理
expire_logs_days=7
##跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断
##如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062

(3)修改完配置后重启master实例

docker restart mysql-master

在这里插入图片描述

(4)进入mysql-master容器

docker exec -it mysql-master /bin/bash

mysql -uroot -proot

(5)master容器实例内创建数据同步用户

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';

GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%';

(6)新建从服务器容器实例3308

docker run -p 3308:3306 --name mysql-slave -v /mydata/mysql-slave/log:/var/log/mysql -v /mydata/mysql-slave/data:/var/lib/mysql -v /mydata/mysql-slave/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7

在这里插入图片描述

(7)进入/mydata/mysql-master/conf目录下新建my.cnf

在这里插入图片描述

[mysqld]
##设置server-id,同一局域网中需要唯一
server_id=102
##指定不需要同步的数据库名称
binlog-ignore-db=mysql
##开启二进制日志功能
log-bin=mall-mysql-bin
##设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
##设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
##二进制日志过期清理时间。默认值为0,表示不自动清理
expire_logs_days=7
##跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断
##如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
##relay_log配置中继日志
relay_log=mall-mysql-relay-bin
##log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
##slave设置为只读(具有super权限的用户除外)
read_only=1

(8)修改完配置后重启slave实例

docker restart mysql-slave

(9)在主数据库中查看主从同步状态

show master status;

在这里插入图片描述

(10)进入mysql-slave容器

docker exec -it mysql-slave /bin/bash

mysql -uroot -proot

(11)在从数据库中配置主从复制

change master to master_host='192.168.19.11',master_user='slave',master_password='123456',master_port=3307,master_log_file='mall-mysql-bin.000001',master_log_pos=617,master_connect_retry=30;

(12)在从数据库中查看主从同步状态

show slave status \G;

在这里插入图片描述

(13)在从数据库中开启主从同步

start slave;

在这里插入图片描述

(14)查看从数据库状态发现已经同步

(15)主从复制测试

在主库执行以下sql

create database testslave;

use testslave;

CREATE TABLE hero ( id int(11) AUTO_INCREMENT, name varchar(30) , hp float , damage int(11) , PRIMARY KEY (id) )  DEFAULT CHARSET=utf8;

insert into hero values (null, '盖伦', 616, 100);

在从库进行查询,查询成功。

【9】安装xxl-job

(1)导入sql

在 Docker 容器中部署 xxl-job,在部署之前我们需要一个 Mysql 的环境,这个环境我们已经在上一章节中安装完成。

本章节下载了 xxl-job 2.1.2 对应 SQL 文件已经存放到这里,你可以直接打开使用

/*
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50639
 Source Host           : localhost:3306
 Source Schema         : xxl_job

 Target Server Type    : MySQL
 Target Server Version : 50639
 File Encoding         : 65001

 Date: 04/12/2021 16:28:12
*/

create database xxl_job;

USE xxl_job;

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for xxl_job_group
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_group`;
CREATE TABLE `xxl_job_group` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
  `title` varchar(12) NOT NULL COMMENT '执行器名称',
  `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
  `address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of xxl_job_group
-- ----------------------------
BEGIN;
INSERT INTO `xxl_job_group` VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2021-11-20 20:28:29');
INSERT INTO `xxl_job_group` VALUES (2, 'lottery-job', '抽奖系统任务调度', 0, NULL, '2021-11-20 20:28:29');
COMMIT;

-- ----------------------------
-- Table structure for xxl_job_info
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_info`;
CREATE TABLE `xxl_job_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `job_group` int(11) NOT NULL COMMENT '执行器主键ID',
  `job_desc` varchar(255) NOT NULL,
  `add_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `author` varchar(64) DEFAULT NULL COMMENT '作者',
  `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
  `schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
  `schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
  `misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
  `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
  `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
  `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
  `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
  `executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
  `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
  `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
  `glue_source` mediumtext COMMENT 'GLUE源代码',
  `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
  `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
  `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',
  `trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行',
  `trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
  `trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of xxl_job_info
-- ----------------------------
BEGIN;
INSERT INTO `xxl_job_info` VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2021-11-06 14:54:29', 'XXL', '', 'CRON', '0/1 * * * * ?', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '', 1, 1637411338000, 1637411339000);
INSERT INTO `xxl_job_info` VALUES (2, 2, '活动状态扫描', '2021-11-06 11:43:49', '2021-11-13 10:19:56', '小傅哥', '', 'CRON', '0/1 * * * * ?', 'DO_NOTHING', 'FIRST', 'lotteryActivityStateJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2021-11-06 11:43:49', '', 0, 0, 0);
INSERT INTO `xxl_job_info` VALUES (3, 2, '扫描用户抽奖奖品发放MQ状态补偿', '2021-11-13 10:23:59', '2021-11-13 13:47:26', '小傅哥', '', 'CRON', '0/5 * * * * ?', 'DO_NOTHING', 'FIRST', 'lotteryOrderMQStateJobHandler', '1', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2021-11-13 10:23:59', '', 0, 0, 0);
COMMIT;

-- ----------------------------
-- Table structure for xxl_job_lock
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_lock`;
CREATE TABLE `xxl_job_lock` (
  `lock_name` varchar(50) NOT NULL COMMENT '锁名称',
  PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of xxl_job_lock
-- ----------------------------
BEGIN;
INSERT INTO `xxl_job_lock` VALUES ('schedule_lock');
COMMIT;

-- ----------------------------
-- Table structure for xxl_job_log
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_log`;
CREATE TABLE `xxl_job_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `job_group` int(11) NOT NULL COMMENT '执行器主键ID',
  `job_id` int(11) NOT NULL COMMENT '任务,主键ID',
  `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
  `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
  `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
  `executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
  `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
  `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
  `trigger_code` int(11) NOT NULL COMMENT '调度-结果',
  `trigger_msg` text COMMENT '调度-日志',
  `handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
  `handle_code` int(11) NOT NULL COMMENT '执行-状态',
  `handle_msg` text COMMENT '执行-日志',
  `alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',
  PRIMARY KEY (`id`),
  KEY `I_trigger_time` (`trigger_time`),
  KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB AUTO_INCREMENT=56303 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of xxl_job_log
-- ----------------------------
BEGIN;
COMMIT;

-- ----------------------------
-- Table structure for xxl_job_log_report
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_log_report`;
CREATE TABLE `xxl_job_log_report` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
  `running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
  `suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
  `fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of xxl_job_log_report
-- ----------------------------
BEGIN;
INSERT INTO `xxl_job_log_report` VALUES (1, '2021-11-06 00:00:00', 0, 133, 17686, NULL);
INSERT INTO `xxl_job_log_report` VALUES (2, '2021-11-05 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (3, '2021-11-04 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (4, '2021-11-13 00:00:00', 0, 6, 13177, NULL);
INSERT INTO `xxl_job_log_report` VALUES (5, '2021-11-12 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (6, '2021-11-11 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (7, '2021-11-20 00:00:00', 0, 0, 25195, NULL);
INSERT INTO `xxl_job_log_report` VALUES (8, '2021-11-19 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (9, '2021-11-18 00:00:00', 0, 0, 0, NULL);
COMMIT;

-- ----------------------------
-- Table structure for xxl_job_logglue
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_logglue`;
CREATE TABLE `xxl_job_logglue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `job_id` int(11) NOT NULL COMMENT '任务,主键ID',
  `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
  `glue_source` mediumtext COMMENT 'GLUE源代码',
  `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
  `add_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of xxl_job_logglue
-- ----------------------------
BEGIN;
COMMIT;

-- ----------------------------
-- Table structure for xxl_job_registry
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_registry`;
CREATE TABLE `xxl_job_registry` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `registry_group` varchar(50) NOT NULL,
  `registry_key` varchar(255) NOT NULL,
  `registry_value` varchar(255) NOT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `i_g_k_v` (`registry_group`,`registry_key`(191),`registry_value`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of xxl_job_registry
-- ----------------------------
BEGIN;
COMMIT;

-- ----------------------------
-- Table structure for xxl_job_user
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_user`;
CREATE TABLE `xxl_job_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '账号',
  `password` varchar(50) NOT NULL COMMENT '密码',
  `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
  `permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',
  PRIMARY KEY (`id`),
  UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of xxl_job_user
-- ----------------------------
BEGIN;
INSERT INTO `xxl_job_user` VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

我们使用本地 SQL 链接工具,并创建 xxl-job 库已经导入 xxl-job.sql 文件
在这里插入图片描述

(2)安装xxl-job(7397)

(1)拉取镜像:docker pull xuxueli/xxl-job-admin:2.3.0
(2)部署(修改成你的数据库服务器IP、账号、密码、accessToken):docker run -e PARAMS=" --server.port=7397 --spring.datasource.url=jdbc:mysql://172.17.0.6:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 --spring.datasource.username=root --spring.datasource.password=123456 --xxl.job.accessToken=xdsl3ewi3al1oehxmo68pqxer" -p 7397:7397 -v /logs/xxl-job:/data/applogs --name xxl-job-admin --restart=always -d xuxueli/xxl-job-admin:2.3.0
(3)查看日志
在这里插入图片描述
(4)打开xxl-job的后台
http://你的ip:7397/xxl-job-admin/
在这里插入图片描述

(3)配置任务

(1)打开上面的xxl-job的后台:http://你的ip:7397/xxl-job-admin/
(2)添加xxl-job执行器,一个执行器也就是一个应用实例
设置执行器的AppName,注册方式为自动注入,创建一个执行器,这里的名字要对应上,不能错。
在这里插入图片描述
(3)添加job
在任务管理里,选择执行器,创建新的任务,指定负责人和报警邮件,调度类型选择Cron,编写Cron命令为【0/5 * * * * ?】表示5秒执行一次。另外JobHandler为lotteryOrderMQStateJobHandler,运行模式为bean
然后就是在执行器下创建任务
在这里插入图片描述

(4)工程配置xxl-job

(1)查看xxl-job启动参数
在这里插入图片描述
(2)配置启动参数,在yml配置文件中加上配置信息
1-xxl-job的启动地址和端口号,这个端口号是启动的端口号(注意这里是虚拟机或者服务器的ip和端口号)
2-执行器的名称,也就是执行器的AppName,还有端口号,这个端口号是执行器自动注册的端口号
3-指定日志路径(这个路径要提前创建好,在我们的虚拟机或者服务器上要提前创建)
4-日志清除周期

# http://39.96.73.167:7397/xxl-job-admin
# 账号:admin
# 密码:123456
xxl:
  job:
    admin:
      ### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
      addresses: http://39.96.73.167:7397/xxl-job-admin
    executor:
      ### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
      appname: lottery-job
      ### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
      address:
      ### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
      ip: 3e62f9.natappfree.cc
      ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
      port: 9999
      logpath: /Users/fuzhengwei/itstack/data/applogs/xxl-job/jobhandler
      logretentiondays: 50
    accessToken: xdsl3ewi3al1oehxmo68pqxer

(5)测试验证(待补充)

【10】安装nacos(8848)

(1)拉取镜像:docker pull nacos/nacos-server
(2)安装部署:docker run -d -p 8848:8848 --env MODE=standalone --name nacos nacos/nacos-server

(3)打开链接:http://服务器IP:8848/nacos/ - 账号:nacos 密码:nacos
在这里插入图片描述
(4)访问出现问题
[root@allen02 conf]# curl http://192.168.19.22:8848/nacos/#/login
curl: (7) Failed connect to 192.168.19.22:8848; Connection refused

防火墙已经关了,重启docker,过了一会又好了

(5)本地配置(待补充)

【11】安装Elasticsearch(9200)

(1)拉取镜像:docker pull elasticsearch:7.6.2
(2)执行安装:docker run --name elasticsearch -d -e ES_JAVA_OPTS=“-Xms128m -Xmx256m” -e “discovery.type=single-node” -p 9200:9200 -p 9300:9300 elasticsearch:7.6.2

--name表示镜像启动后的容器名称
-d: 后台运行容器,并返回容器ID;
-e: 指定容器内的环境变量
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口

(3)检查portainer
在这里插入图片描述
(4)启动
http://39.96.73.167:9200
在这里插入图片描述

【12】安装Kibana(5601)

(1)拉取镜像:docker pull kibana:7.6.2
(2)添加配置:kibana.yml
1-创建/data/kibana/config文件夹,编辑kibana.yml
2-覆盖配置文件,如下

#
# ** THIS IS AN AUTO-GENERATED FILE **
#

# Default Kibana configuration for docker target
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://39.96.73.167:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true
# 设置中文显示
i18n.locale: "zh-CN"

配置 elasticsearch 地址
配置 zh-CN 中文显示

(3)执行安装:
docker run -d
–name=kibana
–restart=always
-p 5601:5601
-v /data/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml
kibana:7.6.2

(4)访问验证:http://39.96.73.167:5601/app/kibana#/home
在这里插入图片描述

【13】安装canal(待补充)

(1)canal介绍
canal 是一款 阿里巴巴 MySQL binlog 增量订阅&消费组件,模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议。MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal ),canal 解析 binary log 对象(原始为 byte 流),之后把数据转存到其他需要保存的服务中。文档:https://github.com/alibaba/canal/wiki

我们会在 docker 环境,把 Mysql 数据库中抽奖系统的分库分表数据使用 canal 同步到 ES 文件系统中

【14】安装nginx(80)

(1)下载Nginx镜像(下面两种选择一个)

docker pull nginx:下载最新版Nginx镜像 (其实此命令就等同于 : docker pull nginx:latest )
docker pull nginx:xxx:下载指定版本的Nginx镜像 (xxx指具体版本号)

在这里插入图片描述

(2)创建Nginx配置文件

启动前需要先创建Nginx外部挂载的配置文件(/home/nginx/conf/nginx.conf),之所以要先创建,是因为Nginx本身容器只存在/etc/nginx目录,本身就不创建nginx.conf文件,当前服务器和容器都不存在nginx.conf文件时,执行启动命令的时候docker会把nginx.conf作为目录创建,这不是我们想要的结果

# 创建挂载目录
mkdir -p /home/nginx/conf
mkdir -p /home/nginx/log
mkdir -p /home/nginx/html

容器中的nginx.conf文件和conf.d文件夹复制到宿主机

# 生成容器,会创建下面需要的那些文件
docker run --name nginx -p 9001:80 -d nginx
# 将容器nginx.conf文件复制到宿主机
docker cp nginx:/etc/nginx/nginx.conf /home/nginx/conf/nginx.conf
# 将容器conf.d文件夹下内容复制到宿主机
docker cp nginx:/etc/nginx/conf.d /home/nginx/conf/conf.d
# 将容器中的html文件夹复制到宿主机
docker cp nginx:/usr/share/nginx/html /home/nginx/

在这里插入图片描述

(3)创建Nginx容器并运行

先停掉并删除正在运行的Nginx容器

# 直接执行docker rm nginx或者以容器id方式关闭容器
# 找到nginx对应的容器id
docker ps -a
# 关闭该容器
docker stop nginx
# 删除该容器
docker rm nginx
 
# 删除正在运行的nginx容器
docker rm -f nginx

创建容器

docker run \
-p 9002:80 \
--name nginx \
--restart=always \
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /home/nginx/conf/conf.d:/etc/nginx/conf.d \
-v /home/nginx/log:/var/log/nginx \
-v /home/nginx/html:/usr/share/nginx/html \
-d nginx:latest

命令分析
–name nginx:启动容器的名字
–restart=always:当docker启动的时候,容器自启动
-d:后台运行
-p 9002:80:将容器的 9002(后面那个) 端口映射到主机的 80(前面那个) 端口
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:挂载nginx.conf配置文件
-v /home/nginx/conf/conf.d:/etc/nginx/conf.d:挂载nginx配置文件
-v /home/nginx/log:/var/log/nginx:挂载nginx日志文件
-v /home/nginx/html:/usr/share/nginx/html:挂载nginx内容
nginx:latest:本地运行的版本
\:shell命令换行(注意的时候换行前有个空格)

单行模式

docker run -p 9002:80 --name nginx --restart=always -v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /home/nginx/conf/conf.d:/etc/nginx/conf.d -v /home/nginx/log:/var/log/nginx -v /home/nginx/html:/usr/share/nginx/html -d nginx:latest

(4)结果检测

在这里插入图片描述
然后访问一下网址试试
在这里插入图片描述
成功

(5)修改nginx配置

【四】总结上面案例中的概念和常用的Docker命令

【1】常用的概念

(1)Client客户端
Docker是一个客户端-服务器(C/S)架构程序,Docker客户端只需要向Docker服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。

(2)Image镜像
简单理解,Docker镜像就是一个Linux的文件系统,这个文件系统里面包含可以运行在Linux内核的程序以及相应的数据。

通过镜像启动一个容器,一个镜像就是一个可执行的包,其中包括运行应用程序所需要的所有内容:包含代码,运行时间,库,环境变量和配置文件等。

Docker把App文件打包成一个镜像,并且采用类似多次快照的存储技术,可以实现:
1-多个App可以共用相同的底层镜像(初始的操作系统镜像)
2-App运行时的IO操作和镜像文件隔离
3-通过挂载包含不同配置/数据文件的目录或者卷(Volume),单个App镜像可以用来运行无数个不同业务的容器。

(3)Container容器
镜像和容器的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

(4)镜像分层
Docker支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的。
在这里插入图片描述
从上图可以看到,新镜像是从base镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。

镜像分层最大的好处就是共享资源。比如说有多个镜像都从相同的base镜像构建而来,那么Docker Host只需在磁盘上保存一份base镜像,同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被分享。

如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如etc下的文件,这时其他容器的etc是不会被修改的,修改只会被限制子啊单个容器里,这就是容器copy-on-write特性

(5)Volume数据卷
实际上我们的容器就好像是一个简易版的操作系统,只不过系统中只安装了我们的程序运行所需要的环境,前边说到容器是可以删除的,那如果删除了,容器里的程序产生的需要持久化的数据怎么办呢?容器运行的时候我们可以进容器去查看,容器一旦删除就什么都没有了。

所以数据卷就是来解决这个问题的,是用来将数据持久化到我们宿主机上,与容器间实现数据共享,简单的说就是将宿主机的目录映射到容器中的目录,应用程序在容器中的目录读写数据会同步到宿主机上,这样容器发生的数据就可以持久化了,比如我们的数据库容器,就可以把数据存储到我们宿主机上的真是磁盘里。

(6)Registry注册中心
Docker用Registry来保存用户构建的镜像。Registry分为公共和私有两种。Docker公司运行公共的Registry叫做Docker Hub。用户可以在Docker Hub注册账号,分享并保存自己的镜像。一个Docker Registry中可以包含多个仓库Repository;每个仓库可以包含多个标签Tag,每个标签对一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签对应该软件的各个版本。我们可以通过【仓库名:标签】的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。

【2】镜像命令

官方文档:https://docs.docker.com/reference

(1)查看镜像:docker images
(2)搜索镜像:docker search 镜像名称
(3)拉取镜像:docker pull 镜像名称
(4)删除单个镜像:docker rmi 镜像ID
(5)删除多个镜像:docker rmi 镜像ID 镜像ID 镜像ID
(6)删除所有镜像:docker rmi docker images -q

注意:如果通过某个镜像创建了容器,则该镜像无法删除。
解决办法:先删除镜像中的容器,再删除该镜像。

【3】容器命令

(1)查看容器:docker ps
(2)查看停止的容器:docker ps -f status=exited
(3)查看所有容器:docker ps -a
(4)查看最后一次运行的容器:docker ps -l
(5)列出最近创建的n个容器:docker ps -n 5

(6)创建和启动容器:docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
-i:表示运行容器;
-t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端;
–name:为创建的容器命名;
-v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个 -v 做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上;
-d:在 run 后面加上 -d 参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加 -i -t 两个参数,创建容器后就会自动进容器里);
-p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个 -p 做多个端口映射。
-P:随机使用宿主机的可用端口与容器内暴露的端口映射。

(7)创建并进入容器:docker run -it --name 容器名称 镜像名称:标签 /bin/bash
(8)退出当前容器:exit
(9)守护式方式创建容器:docker run -di --name 容器名称 镜像名称:标签
(10)登录守护式容器方式:docker exec -it 容器名称|容器ID /bin/bash
(11)停止容器:docker stop 容器名称|容器ID
(12)启动容器:docker start 容器名称|容器ID
(13)文件拷贝
如果我们需要将文件拷贝到容器内可以使用cp命令:docker cp 需要拷贝的文件或目录 容器名称:容器目录
也可以将文件从容器内拷贝出来:docker cp 容器名称:容器目录 需要拷贝的文件或目录
(14)目录挂载
我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器,而且这个操作是双向绑定的,也就是说容器内的操作也会影响到宿主机,实现备份功能。

但是容器被删除的时候,宿主机的内容并不会被删除。如果多个容器挂载同一个目录,其中一个容器被删除,其他容器的内容也不会受到影响。

创建容器添加-v参数,格式为宿主机目录:容器目录,例如:

docker run -di -v /home/ruoyi/data:/usr/local/data --name centos7-01 centos:7

# 多目录挂载
docker run -di -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名

目录挂载操作可能会出现权限不足的提示。这是因为CentOS7中的安全模块SELinux把权限禁掉了,在docker run时通过–privileged=true给该容器加权限来解决挂载的目录没有权限的问题。

1-匿名挂载
匿名挂载只需要写容器目录即可,容器外对应的目录会在/var/lib/docker/volumes中生成。

# 匿名挂载
docker run -di -v /usr/local/data --name centos7-02 centos:7
# 查看 volume 数据卷信息
docker volume ls

2-具名挂载
具名挂载就是给数据卷起了个名字,容器外对应的目录会在/var/lib/docker/volume中生成。

# 匿名挂载
docker run -di -v docker_centos_data:/usr/local/data --name centos7-03 centos:7
# 查看 volume 数据卷信息
docker volume ls

3-指定目录挂载
之前挂载方式就属于指定目录挂载,这种方式的挂载不会在/var/lib/docker/volume目录生成内容。

docker run -di -v /mydata/docker_centos/data:/usr/local/data --name centos7-01 centos:7
# 多目录挂载
docker run -di -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名

4-查看目录挂载关系
通过docker volume inspect数据卷名称 可以查看该数据卷对应宿主机的目录地址。

执行命令:docker volume inspect docker_centos_data

通过docker inspect容器ID或名称 ,在返回的JSON节点中找到Mounts,可以查看详细的数据挂载信息。

5-只读/读写

# 只读。只能通过修改宿主机内容实现对容器的数据管理。
docker run -it -v /宿主机目录:/容器目录:ro 镜像名

# 读写,默认。宿主机和容器可以双向操作数据。
docker run -it -v /宿主机目录:/容器目录:rw 镜像名

(15)删除容器

# 删除指定容器
docker rm 容器名称|容器ID

# 删除多个容器
docker rm 容器名称|容器ID 容器名称|容器ID

(16)查看容器 IP 地址

我们可以通过以下命令查看容器的元信息:docker inspect 容器名称|容器ID

也可以直接执行下面的命令直接输出 IP 地址。

docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称|容器ID

【4】镜像构建

(1)介绍

我们可以通过公共仓库拉取镜像使用,但是,有些时候公共仓库拉取的镜像并不符合我们的需求。尽管已经从繁琐的部署工作中解放出来,但是实际开发时,我们可能希望镜像包含整个项目的完整环境,在其他机器上拉取打包完整的镜像,直接运行即可。

Docker 支持自己构建镜像,还支持将自己构建的镜像上传至公共仓库,镜像构建可以通过以下两种方式来实现:

(1)从容器创建一个新的镜像
docker commit
(2)配合Dockerfile文件创建镜像
docker build

(2)docker commit构建镜像

目标:接下来我们通过基础镜像centos:7,在该镜像中安装jdk和tomcat以后将其制作为一个新的镜像mycentos:7。

(1)创建容器

# 拉取镜像
docker pull centos:7

# 创建容器
docker run -di --name centos7 centos:7

(2)拷贝资源

# 将宿主机的 jdk 和 tomcat 拷贝至容器
docker cp jdk-8u111-linux-x64.tar.gz centos7:/root

docker cp apache-tomcat-8.5.27.tar.gz centos7:/root

(3)安装资源

# 进入容器
docker exec -it centos7 /bin/bash

# 切换至 /root 目录
cd root/

# 创建 java 和 tomcat 目录
mkdir -p /usr/local/java
mkdir -p /usr/local/tomcat

# 将 jdk 和 tomcat 解压至容器 /usr/local/java 和 /usr/local/tomcat 目录中
tar -zxvf jdk-8u111-linux-x64.tar.gz -C /usr/local/java/
tar -zxvf apache-tomcat-8.5.27.tar.gz -C /usr/local/tomcat/

# 配置 jdk 环境变量
vi /etc/profile

# 在环境变量文件中添加以下内容
export JAVA_HOME=/usr/local/java/jdk1.8.0_111/
export PATH=$PATH:$JAVA_HOME/bin

# 重新加载环境变量文件
source /etc/profile

# 测试环境变量是否配置成功
java -version

# 删除容器内 jdk 和 tomcat
rm jdk-8u111-linux-x64.tar.gz apache-tomcat-8.5.27.tar.gz -rf

(4)构建镜像

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
docker commit -a="ruoyi" -m="jdk8 and tomcat8" centos7 mycentos:7

(5)参数介绍
-a:提交的镜像作者;
-c:使用 Dockerfile 指令来创建镜像;
-m:提交时的说明文字;
-p:在 commit 时,将容器暂停。

(6)使用构建的镜像创建容器

# 创建容器
docker run -di --name mycentos7 -p 8080:8080 mycentos:7

# 进入容器
docker exec -it mycentos7 /bin/bash

# 重新加载配置文件
source /etc/profile

# 测试 java 环境变量
java -version

# 启动 tomcat
/usr/local/tomcat/apache-tomcat-8.5.27/bin/startup.sh

访问http://{ip}:{port},看到tomcat页面说明环境表示成功。

【五】挂载是怎么个事

【六】网络是怎么个事

【七】Dockerfile

【1】介绍

在Docker中构建镜像最常用的方式,就是使用Dockerfile。Dockerfile是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。官方文档:https://docs.docker.com/engine/reference/builder

在这里插入图片描述
通过架构图可以看出通过dockerfile可以直接构建一个属于自己的镜像。

官方镜像确实足够好了,足够适用于大多数应用程序,但是如果我们想自己创建属于我们自己的业务镜像,这个时候必须自定义镜像。

【2】Dockerfile的基础知识

(1)每条保留字指令都必须为大写,并且后面都要跟至少一个参数
(2)指令按照从上到下,顺序执行
(3)#表示注释
(4)每条指令都会创建一个新的镜像层并对镜像进行提交
(5)创建Dockerfile的时候可以直接在一个目录下面,使用vim Dockerfile来创建文件,然后直接编辑内容保存

【3】Dockerfile 常用指令

(1)FROM
当前镜像是基于哪个镜像的,第一个指令必须是FROM

FROM :
指明构建的新镜像是来自于哪个基础镜像,如果没有选择tag,那么默认值为latest

(2)MAINTAINER
MAINTAINER
指明镜像维护者及其联系方式(一般是邮箱地址)。官方说明已过时,推荐使用LABEL

(3)LABEL
LABEL = …
功能是为镜像指定标签。也可以使用LABEL来指定镜像作者

(4)RUN
RUN
构建镜像时运行的Shell命令,比如构建的新镜像中我们想在/usr/local目录下创建一个java目录
(5)ADD
ADD …
拷贝文件或目录到镜像中。src 可以是一个本地文件,还可以是一个url。然后自动下载和解压

(6)COPY
COPY …
拷贝文件或目录到镜像中。用法同 ADD,只是不支持自动下载和解压

(7)EXPOSE
EXPOSE [/…]
暴露容器运行时的监听端口给外部,可以指定端口是监听 TCP 还是 UDP,如果未指定协议,则默认为 TCP

(8)ENV
ENV = …
设置容器内环境变量

(9)CMD
CMD [“executable”,“param1”,“param2”]
启动容器时执行的Shell命令。在Dockerfile中只能有一条CMD指令。如果设置了多条CMD,只有最后一条会生效

(10)ENTRYPOINT
ENTRYPOINT [“executable”, “param1”, “param2”]
启动容器时执行的 Shell 命令,同 CMD 类似,不会被 docker run 命令行指定的参数所覆盖,如果设置了多条ENTRYPOINT,只有最后一条会生效

(11)WORKDIR
WORKDIR param
为 RUN、CMD、ENTRYPOINT 以及 COPY 和 AND 设置工作目录

(12)VOLUME
VOLUME [“param”]
指定容器挂载点到宿主机自动生成的目录或其他容器。一般的使用场景为需要持久化存储数据时

【4】Dockerfile指令的使用案例

(1)先拉取一个centos的镜像

docker pull centos

在这里插入图片描述

(2)启动centos

现在的centos里面是空的

docker run centos:latest

没有任何反应,只有一个空的操作系统,不会有其他服务阻塞操作系统

然后使用后台启动

docker run -d centos:latest

查看,还是没有任何运行的镜像,那是因为启动之后马上就关闭了
在这里插入图片描述

(3)阻塞操作系统,启动的一刹那就进入操作系统

# 等操作系统运行之后再进入
docker exec -it centos:latest
# 在操作系统启动的时候就进入
docker run -it centos:latest

在这里插入图片描述

(4)测试FROM指令

接下来在centos镜像的基础上构建我们自己的镜像
直接在用户根目录下创建Dockerfile文件

vim Dockerfile

添加下面内容

FROM centos:latest

保存退出
在这里插入图片描述

(5)构建镜像

docker build -t mycentos:01 .

在这里插入图片描述在这里插入图片描述
可以看到镜像已经创建成功了

(6)一点优化

可以看到根目录下除了Dockerfile还有其他不相关的文件,例如anaconda-ks.cfg,在构建镜像的时候会把这些文件都发送给docker,但是这些我们是用不到的。所以平时可以新建一个docker文件夹,然后把用到的相关文件都放在这个文件夹下
在这里插入图片描述

(7)测试RUN指令

原始的centos系统是没有安装vim的,我们要使用vim需要用yum下载
在这里插入图片描述我们希望镜像构建的时候自动安装好vim工具。

RUN命令就是在上一步的命令基础上执行一些命令操作
在这里插入图片描述
修改Dockerfile文件如下
在这里插入图片描述保存退出以后,重新构建

docker build -t mycentos:02 .

发现报错了,报错内容如下
在这里插入图片描述
原因就是CentOS在2020 年 12 月 8 号,CentOS 官方宣布了停止维护 CentOS Linux 的计划,并推出了 CentOS Stream 项目,CentOS Linux 8 作为 RHEL 8 的复刻版本,生命周期缩短,于 2021 年 12 月 31 日停止更新并停止维护(EOL)。

解决方法为更改镜像,需要将镜像从 mirror.centos.org 更改为 vault.centos.org

修改Dockerfile,添加内容如下

RUN cd /etc/yum.repos.d/
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
RUN yum update -y
RUN yum install -y vim

在这里插入图片描述然后再次构建镜像

docker build -t mycentos:02 .

执行结果,镜像构建成功,yum已经成功更新并安装了vim
在这里插入图片描述
运行镜像,并使用vim

docker run -it mycentos:02

在这里插入图片描述

补充信息:RUN命令还可以使用数组的语法,例如【RUN [“yum”,“install”,“-y”,“vim”]】,这种数组的方式就不能使用缓存了

(8)测试EXPOSE指令

当前容器对外暴露出的端口号,EXPOSE指令的作用只是声明,它只是方便描述端口暴露信息,即使这里不加,后面也可以启动的时候也可以通过-p命令指定端口

在这里插入图片描述
构建,然后运行镜像

docker build -t mycentos:03 .
docker run -it mycentos:03

(9)测试WORKDIR指令

指定在创建容器之后,终端默认登录进来的工作目录,一个落脚点。我们以前使用run命令启动一个容器以后,工作目录默认是跟根目录“/”
在这里插入图片描述
而WORKDIR命令用来为Dockerfile中的任何RUN,CMD,ENTRPOINT,COPY和ADD指令设置工作目录,如果WORKDIR不存在,即使它没有在任何后续Dockerfile指令中使用,它也会被创建。

WORKDIR指令可以在Dockerfile中多次使用,如果提供了相对路径,则该路径将与先前WORKDIR指令的路径相对

在这里插入图片描述
然后创建并启动

docker build -t mycentos:04 .
docker run -it mycentos:04

可以看到默认进入的是自定义的allen目录
在这里插入图片描述

(10)测试ADD指令

我们以后创建镜像的时候,可能要把本地的jar包拷贝到镜像里面

我们首先在本地docker文件夹里创建一个txt文件,然后尝试在构建镜像的时候把这个txt文件拷贝进去
在这里插入图片描述这里已经指定了工作目录为/allen/data,然后添加宿主机当前目录下额xxx.txt文件到镜像的工作目录里,也就是放进/allen/data里。

然后创建并启动

docker build -t mycentos:05 .
docker run -it mycentos:05

可以看到默认进入的工作目录就是/allen/data,并且目录下有添加进来的xxx.txt文件
在这里插入图片描述

(11)测试COPY指令

其实跟ADD命令的使用方式和作用是一样的,那么ADD和COPY的区别到底是什么呢?

COPY功能比较简单,它就只能拷贝文件到镜像里,不能做额外的操作,仅仅是一个复制的作用,而ADD相对有一点强大,ADD还能搭配URL使用,当ADD和URL使用时会自动通过URL进行下载

例如我们通过URL直接下载一个tomcat,并且使用RUN执行解压等一系列操作
Tomcat下载地址:https://downloads.apache.org/tomcat/tomcat-8/v8.5.91/bin/apache-tomcat-8.5.91.tar.gz

在这里插入图片描述

然后创建并启动

docker build -t mycentos:06 .
docker run -it mycentos:06

在这里插入图片描述

(12)测试ENV指令

上面我们在使用WORKDIR设置工作目录的时候,有时候要多次使用来切换RUN命令的工作目录,这个时候我们就可以用ENV来把常用目录设置成配置,方便统一修改和使用

在这里插入图片描述

然后创建并启动

docker build -t mycentos:07 .
docker run -it mycentos:07

可以看到默认工作目录切换回了/allen/data
在这里插入图片描述

(13)测试VOLUME指令

VOLUME指令和EXPOSE指令类似,都是声明指令,方便查看描述信息,不加的话也没关系,可以通过-v命令在启动的时候挂载数据卷

如果我们不使用VOLUME命令,直接使用-v命令

docker run -v datas:/allen mycentos:07

启动成功以后查看数据卷列表

docker volume ls

在这里插入图片描述
进入数据卷查看

docker inspect datas

在这里插入图片描述
进入具体的目录里查看

cd /var/lib/docker/volumes/datas/_data

在这里插入图片描述
如果是使用VOLUME的话
在这里插入图片描述

(14)测试CMD命令

指定一个容器启动时要运行的命令,Dockerfile中可以有多个CMD指令,但是只有最后一个才会生效,CMD会被docker run之后的参数替换

例如我们在构建镜像的时候,要启动jar包,就会使用java -jar命令。

使用语法:
(1)直接命令方式
java -jar ems.jar
(2)JSON数组方式(推荐)
[“java”,“-jar”,“ems.jar”]

更推荐json数组的方式,因为json数组可以支持传参

案例1:用CMD展示/allen/data下面的文件(ENTRYPOINT的用法相同)
在这里插入图片描述

docker build -t mycentos:08 .
docker run mycentos:08

在这里插入图片描述

(15)测试ENTRYPOINT指令

指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序和参数

首先我们把CMD和ENTRYPOINT都改成是json数组形式
在这里插入图片描述
(1)如果是CMD命令
我们想要替换ls展示的目录,可以直接使用传参的方式来覆盖

docker run 镜像:版本号 覆盖自己定义的命令

docker run mycentos:08 ls /apps
或者
docker run mycentos:08 ls /

CMD传参更方便

(2)如果是ENTRYPOINT命令
docker run --entrypoint=覆盖命令 镜像:版本号 传递参数

docker run --entrypoint=ls mycentos:08 /apps

(3)如何搭配使用
我们如果要执行一个jar包,可能会使用以下命令

CMD java -jar ems.jar
ENTRYPOINT java -jar ems.jar

java -jar这个指令是不会变的,可能变的是ems.jar这个变量,所以我们希望java -jar不可以通过传参修改,而ems.jar可以通过传参覆盖修改,于是我们可以把这两个指令搭配起来使用。

使用ENTRYPOINT来写容器固定的指令,CMD来给ENTRYPOINT传递参数,注意的是配合使用时必须使用json数字语法才能传参覆盖

ENTRYPOINT ["java","-jar"]
CMD ["ems.jar"]

前面的文件展示也可以改成下面这样

ENTRYPOINT ["ls"]
CMD ["/allen/data"]

在这里插入图片描述

(4)创建镜像并启动

docker build -t mycentos:09 .
docker run mycentos:09

在这里插入图片描述测试一下传参

docker run mycentos:09 /

在这里插入图片描述

【3】构建镜像

Dockerfile文件编写好以后,真正构建镜像时需要通过docker build命令。

docker build命令用于使用Dockerfile创建镜像,进入放置Dockerfile的文件夹,然后执行命令,或者在命令中指明Dockerfile的路径

# .的意思就是使用当前目录的 Dockerfile 创建镜像
docker build -t mycentos:7 .

# 通过 -f Dockerfile 文件的位置创建镜像
docker build -f /home/ruoyi/docker/Dockerfile -t mycentos:7 .

-f:指定要使用的 Dockerfile 路径;
–tag, -t:镜像的名字及标签,可以在一次构建中为一个镜像设置多个标签。

【4】Dockerfile 实践

接下来我们通过基础镜像centos:7,在该镜像中安装jdk和tomcat以后将其制作为一个新的镜像mycentos:7

(1)创建目录,编写Dockerfile文件

mkdir -p /usr/local/`dockerfile`

(2)执行命令:vi Dockerfile,写入信息。

# 指明构建的新镜像是来自于`centos:7`基础镜像
FROM centos:7
# 通过镜像标签声明了作者信息
LABEL maintainer="ruoyi.vip"

# 设置工作目录
WORKDIR /usr/local
# 新镜像构建成功以后创建指定目录
RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
# 拷贝文件到镜像中并解压
ADD jdk-8u111-linux-x64.tar.gz /usr/local/java
ADD apache-tomcat-8.5.27.tar.gz /usr/local/tomcat
# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080
# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_111
ENV PATH $PATH:$JAVA_HOME/bin
# 启动容器时启动 tomcat
CMD ["/usr/local/tomcat/apache-tomcat-8.5.27/bin/catalina.sh", "run"]

(3)构建镜像

docker build -f /home/ruoyi/docker/Dockerfile -t mycentos:test .

(4)启动镜像

docker run -di --name mycentos -p 8080:8080 mycentos:test

(5)进入容器

docker exec -it mycentos7 /bin/bash

(6)查看镜像构建历史

docker history mycentos:7
docker history 镜像名称:标签|ID

【5】镜像仓库

(1)介绍
我们使用的镜像都是从DockerHub公共仓库拉取的,我们也学习了如何制作自己的镜像,但是通过tar包的方式实现镜像的备份恢复迁移对于团队协作开发并不是特别友好,我们也可以将镜像推送至DockerHub仓库方便使用。

温馨提示:如果构建的镜像内携带了项目数据,建议还是使用私有仓库比较好。

(2)注册账号
官网:https://hub.docker.com
在这里插入图片描述

(3)登录账号
通过docker login命令输入账号密码登录DockerHub
在这里插入图片描述
(4)推送镜像至仓库
为了方便测试,我们将hello-world镜像拉取至本地,然后再上传至DockerHub仓库中。

docker tag hello-world:latest ruoyivip/test-hello-world:1.0.0
docker push ruoyivip/test-hello-world:1.0.0

(5)查看仓库
在这里插入图片描述

(6)拉取镜像
通过docker pull ruoyivip/test-hello-world:1.0.0测试镜像是否可以拉取。

(7)退出账号
通过docker logout退出账号

【六】用dockerfile完成项目部署的案例

【1】案例一:自己创建一个增删改查的项目并用Dockerfile部署

(1)创建一个springboot项目

项目创建后,完成以下准备工作
(1)idea连接数据库
首先启动mysql容器

docker start mysql5

然后idea连接mysql,跟上面Navicat连接的过程类似
在这里插入图片描述
(2)添加相关的依赖
确认一下springboot版本为2.5.2

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.49</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.19</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>
<!--domain.page-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

(3)编写yml配置文件

server:
  port: 8989
  servlet:
    context-path: /docker_springboot
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/tmall_springboot?characterEncoding=UTF-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.allen.docker_springboot.entity

(4)下载自动生成代码的插件easycode
(5)使用插件自动生成增删改查的代码在这里插入图片描述在这里插入图片描述

(6)查看代码的生成结果

在这里插入图片描述
修改启动类,加上扫描路径
在这里插入图片描述

(7)启动项目,测试接口
访问地址:http://localhost:8989/docker_springboot/category/64
在这里插入图片描述

(2)docker创建网络

docker network create apps

然后查看容器

docker ps

在这里插入图片描述
然后把mysql加到网络中去

docker network connect apps e3

最后查看一下网络

docker inspect apps

在这里插入图片描述

(3)把项目打成jar包

打成jar包之前,要把yml配置文件里的mysql的ip地址,端口号,密码等信息都换成服务器的,不能直接用localhost。

我们可以直接把ip改成对应服务器的ip来替换localhost,还有另外一种方式,因为上面已经设置了网络,名称为mysql5,所以我们可以直接用mysql5
在这里插入图片描述

然后开始打包

在这里插入图片描述

(4)创建Dockerfile文件,并上传jar包

进入之前创建的专门放置docker文件的文件夹/docker,然后创建一个专属该项目的文件夹/docker_springboot,进入,然后vi Dockerfile创建Dockerfile文件,编辑输入以下内容

FROM java:8
ENV APP_PATH=/docker/docker_springboot
WORKDIR $APP_PATH
ADD ./docker_springboot-0.0.1-SNAPSHOT.jar $APP_PATH/app.jar
EXPOSE 8989
ENTRYPOINT ["java","-jar"]
CMD ["app.jar","-Dfile.encoding=GBK", "--server.port=8989"]

在这里插入图片描述

(5)用dockerfile构建镜像

进入存放Dockerfile的目录下面

cd /root/docker/docker_springboot

#docker build –f (dockerfile文件路径) –t 镜像名称:版本  .
docker build -t apps:1.0 .

构建完毕
在这里插入图片描述查看镜像,可以看到下面已经有镜像了

docker images

在这里插入图片描述

(6)使用镜像创建容器

暴露的端口号是8989

#这里可以使用【镜像id】,也可以使用名称+版本号【apps:1.0】
docker run -d -p 8989:8989 --name apps apps:1.0

这一步我们可以使用–network直接加入网络,也可以在后面再加入,先使用上面的创建命令
docker run -d -p 8989:8989 --name apps --network apps apps:1.0

下面开始加入网络

docker network connect apps 容器id

查看网络

docker inspect apps

查看运行的容器

docker ps

在这里插入图片描述
通过【docker logs 容器ID】来查看springboot的日志,看看是不是真的启动成功了

如果有报错,要删除容器和镜像,然后需要重新打包执行

docker ps
停止运行的容器:docker stop 容器id
删除容器:docker rm 容器id
docker images
删除镜像:docker rmi -f 镜像id

或者可以使用下面这个命令启动,不用后台启动了,可以直接查看启动日志

#docker run -p 8989:8989 镜像ID
docker run -p 8989:8989 镜像ID

看到下面的日志说明启动成功了
在这里插入图片描述

(7)本地测试

关闭所有防火墙
service firewalld status
service firewalld stop

然后访问地址:http://192.168.19.7:8989/docker_springboot/category/64
在这里插入图片描述

【2】案例二:部署包括mysql和Redis的springboot项目war包

(1)准备项目代码进行本地测试

这里用的是how2j的一个付费项目:天猫整站 Springboot

(2)修改项目代码的配置

包括mysql和redis,连接信息的ip和端口等等要改成对应的数据

(3)项目打成war包

因为不是前后端分离的项目,如果打成jar包的话会报错找不到jsp文件
所以把项目打成war包,需要修改pom.xml
在这里插入图片描述

然后使用maven执行clean+package
在这里插入图片描述
找到war包的位置,package点击完后,控制台输出打包结果,复制路径找到war包

在这里插入图片描述

(4)启动各个容器

包括docker、mysql、redis
这些镜像在上面已经拉取和创建了

(1)启动docker:sudo systemctl start docker
(2)启动mysql:docker start mysql
(3)启动redis:docker start redis

(5)导入项目的数据到mysql

可以通过外网的工具navicat连接服务器的mysql,然后方便操作
在这里插入图片描述

(6)上传springboot项目到服务器,防火墙开放端口

在服务器中新建一个文件夹用来存放我们的项目文件,可以使用sftp工具实现往服务器上传文件

mkdir -p /usr/local/docker

(7)编写dockerfile文件

(1)新建一个txt文件即可

cd /usr/local/docker

touch tmall_docker

vi tmall_docker

标准的还是进入目录后,直接vim就行了

cd /usr/local/docker

vim Dockerfile

(2)添加的内容如下:

#定义父镜像
FROM java:8
#定义作者信息
MAINTAINER AllenSun<>
#VOLUME指定临时文件目录为tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
#ADD 将war包添加到容器中并更名为tmall_docker.war
ADD ./tmall_springboot_middle-0.0.1-SNAPSHOT.war tmall_docker.war
#暴露7777端口作为项目端口
EXPOSE 7777
CMD ["java","-jar","tmall_docker.war","-Dfile.encoding=GBK", "--server.port=7777"]

在这里插入图片描述

(8)用dockerfile构建镜像

#docker build –f (dockerfile文件路径) –t 镜像名称:版本  .
docker build -f ./tmall_docker -t springboot_tmall:1.6 .

在这里插入图片描述

docker image查看镜像是否创建成功

在这里插入图片描述

(9)使用镜像创建容器

暴露的端口号是7777

#docker run -d -p 7777:7777 镜像ID
docker run -d -p 7777:7777 镜像ID

报错了
在这里插入图片描述
重启docker和jdk+redis+nysql,再执行上面的命令就可以了

systemctl restart docker
docker start 镜像名

(10)本地测试

首先通过【docker logs 容器ID】来查看springboot是不是真的启动成功了
在这里插入图片描述
然后访问网址链接:ip地址:7777/tmall_springboot/login

在这里插入图片描述
如果使用的过程中有报错,那就用上面的命令看看日志内容。

【3】案例三:用Dockerfile构建一个自定义镜像

我们可以通过公共仓库拉取镜像使用,但是,有些时候公共仓库拉取的镜像并不符合我们的需求。尽管已经从繁琐的部署工作中解放出来,但是实际开发时,我们可能希望镜像包含整个项目的完整环境,在其他机器上拉取打包完整的镜像,直接运行即可。

接下来我们通过基础镜像centos:7,在该镜像中安装jdk和tomcat以后将其制作为一个新的镜像mycentos:7

(1)编写Dockerfile文件

mkdir -p /usr/local/`dockerfile`

执行命令:vi Dockerfile,写入信息。

# 指明构建的新镜像是来自于`centos:7`基础镜像
FROM centos:7
# 通过镜像标签声明了作者信息
LABEL maintainer="ruoyi.vip"

# 设置工作目录
WORKDIR /usr/local
# 新镜像构建成功以后创建指定目录
RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
# 拷贝文件到镜像中并解压
ADD jdk-8u111-linux-x64.tar.gz /usr/local/java
ADD apache-tomcat-8.5.27.tar.gz /usr/local/tomcat
# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080
# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_111
ENV PATH $PATH:$JAVA_HOME/bin
# 启动容器时启动 tomcat
CMD ["/usr/local/tomcat/apache-tomcat-8.5.27/bin/catalina.sh", "run"]

(2)构建镜像

docker build -f /home/ruoyi/docker/Dockerfile -t mycentos:test .

(3)启动镜像

docker run -di --name mycentos -p 8080:8080 mycentos:test

(4)进入容器

docker exec -it mycentos7 /bin/bash

(5)使用镜像仓库
我们使用的镜像都是从DockerHub公共仓库拉取的,我们也学习了如何制作自己的镜像,但是通过tar包的方式实现镜像的备份恢复迁移对于团队协作开发并不是特别友好,我们也可以将镜像推送至DockerHub仓库方便使用。

温馨提示:如果构建的镜像内携带了项目数据,建议还是使用私有仓库比较好。

(6)注册账号
官网:https://hub.docker.com
通过docker login命令输入账号密码登录DockerHub

在这里插入图片描述(7)推送镜像至仓库
为了方便测试,我们将hello-world镜像拉取至本地,然后再上传至DockerHub仓库中。

docker tag hello-world:latest ruoyivip/test-hello-world:1.0.0
docker push ruoyivip/test-hello-world:1.0.0

(8)查看仓库
在这里插入图片描述(9)拉取镜像
通过docker pull ruoyivip/test-hello-world:1.0.0测试镜像是否可以拉取。

【七】docker-compose

【1】介绍(docker容器太多了如何管理)

docker和docker compose是两个不同的工具。

docker是一种开源容器化平台,可以把应用程序和它们的依赖项打包在一个可移植的容器里,以便在任何环境中快速部署。

docker compose是一个用于定义和运行多容器docker应用程序的工具,使用compose可以使用yaml文件来配置应用程序的服务,并启动/停止/重新生成这些服务。你需要定义一个yaml格式的配置文件docker-compose.ymal,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动或者关闭这些容器。

使用一个dockerfile模板文件可以定义一个单独的应用容器,如果需要定义多个容器就需要服务编排,而compose允许用户在一个模板(ymal格式)中定义一组相关联的应用容器(被称为一个project,即项目),例如一个web服务再加上后端的数据库服务容器等。

【2】举例说明

上面的流程中,已经创建了很多容器,例如mysql、nacos、xxl-job、kafka、zookeeper等等,为了操作方便还给这些容器加上了–restart-always命令让它们自启动。但是这些容器的启动顺序和加载条件我们如何来设置呢?例如我们要先启动mysql,然后启动nacos。我们要先启动zookeeper再启动kafka。除此以外,我们在部署微服务的时候,也会有多个容器的启动顺序问题,同样需要编排。

【3】docker-compose.yml 文件详解

(1)介绍

Docker Compose允许用户通过docker-compose.yml文件(YAML 格式)来定义一组相关联的容器为一个工程(project)。一个工程包含多个服务(service),每个服务中定义了创建容器时所需的镜像、参数、依赖等。

Docker Compose模板文件我们需要关注的顶级配置有version、services、networks、volumes几个部分,除version外,其他几个顶级配置下还有很多下级配置,后面也会详细给大家介绍,先来看看这几个顶级配置都什么意思:

(1)version:描述Compose文件的版本信息,当前最新版本为3.8,对应的Docker版本为19.03.0+
(2)services:定义服务,可以多个,每个服务中定义了创建容器时所需的镜像、参数、依赖等
(3)networkds:定义网络,可以多个,根据DNS server让相同网络中的容器可以直接通过容器名称进行通信
(4)volumes:数据卷,用于实现目录挂载

示例

# 描述 Compose 文件的版本信息
version: "3.8"

# 定义服务,可以多个
services:
  nginx: # 服务名称
    image: nginx # 创建容器时所需的镜像
    container_name: mynginx # 容器名称,默认为"工程名称_服务条目名称_序号"
    ports: # 宿主机与容器的端口映射关系
      - "80:80" # 左边宿主机端口:右边容器端口
    networks: # 配置容器连接的网络,引用顶级 networks 下的条目
      - nginx-net

# 定义网络,可以多个。如果不声明,默认会创建一个网络名称为"工程名称_default"的 bridge 网络
networks:
  nginx-net: # 一个具体网络的条目名称
    name: nginx-net # 网络名称,默认为"工程名称_网络条目名称"
    driver: bridge # 网络模式,默认为 bridge

使用docker-compose up创建并启动所有服务。

# 前台启动
docker-compose up

# 后台启动
docker-compose up -d

使用docker-compose down可以停止并删除容器、网络。

(2)version 版本信息

描述Compose文件的版本信息,当前最新版本为3.8,对应的Docker版本为19.03.0+。关于每个版本的详细信息请参考:https://docs.docker.com/compose/compose-file/compose-versioning/

(3)services 定义服务

services用来定义服务,可以多个,每个服务中定义了创建容器时所需的镜像、参数、依赖等,就像将命令行参数传递给docker run一样。同样,网络和数据卷的定义也是一样的。

比如,通过docker run命令构建一个MySQL应用容器的命令如下:

docker run -di --name mysql8 -p 3306:3306 -v /mydata/docker_mysql/conf:/etc/mysql/conf.d -v /mydata/docker_mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=1234 mysql:8

使用docker-compose.yml以后则可以这样定义:

version: "3.8"
# 定义服务,可以多个
services:
  mysql: # 服务名称
    image: mysql:8 # 创建容器时所需的镜像
    container_name: mysql8 # 容器名称,默认为"工程名称_服务条目名称_序号"
    ports: # 宿主机与容器的端口映射关系
      - "3306:3306" # 左边宿主机端口:右边容器端口
    environment: # 创建容器时所需的环境变量
      MYSQL_ROOT_PASSWORD: 1234
    volumes:
      - "/mydata/docker_mysql/conf:/etc/mysql/conf.d"
      - "/mydata/docker_mysql/data:/var/lib/mysql"

(4)image 镜像名称标签

指定创建容器时所需的镜像名称标签或者镜像ID。如果镜像在本地不存在,会去远程拉取。

services:
  web:
    image: hello-world

(5)dockerfile 构建镜像

(1)build 构建容器:除了可以基于指定的镜像构建容器,还可以基于Dockerfile文件构建,在使用up命令时会执行构建任务。

(2)context 文件路径:该选项可以是Dockerfile文件的绝对/相对路径,也可以是远程Git仓库的URL,当提供的值是相对路径时,相对当前docker-compose.yml文件所在目录。

(3)构建镜像
一般情况下,默认都基于文件名叫Dockerfile的文件构建镜像,当然也可以是自定义的文件名,使用dockerfile声明,不过这个选项只能声明文件名,文件所在路径还是要通过centext来声明。

build:
  context: . # 相对当前 docker-compose.yml 文件所在目录
  dockerfile: Dockerfile-alternate # 基于名称为 Dockerfile-alternate 的文件构建镜像

(6)container_name 容器名称

Compose创建的容器默认生成的名称格式为:工程名称_服务条目名称_序号。如果要使用自定义名称,使用container_name声明。

services:
  mycentos:
    build: .
    container_name: mycentos7 # 容器名称,默认为"工程名称_服务条目名称_序号"

因为Docker容器名称必须是唯一的,所以如果指定了自定义名称,就不能将服务扩展至多个容器。这样做可能会导致错误。

(7)depends_on 容器依赖

使用Compose最大的好处就是敲最少的命令做更多的事情,但一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。例如在没有启动数据库容器的情况下启动了Web应用容器,应用容器会因为找不到数据库而退出。depends_on就是用来解决容器依赖、启动先后问题的配置项。

version: "3.8"

services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: mysql

上述YAML文件定义的容器会先启动db和redis两个服务,最后才启动web服务。

(8)ports 暴露端口

容器对外暴露的端口,格式:左边宿主机端口:右边容器端口。

ports:
  - "80:80"
  - "8080:8080"

(9)expose 接受端口范围

容器暴露的端口不映射到宿主机,只允许能被连接的服务访问。

expose:
  - "80"
  - "8080"

(10)restart 重启策略

容器重启策略,简单的理解就是Docker重启以后容器要不要一起启动

services:
  nginx:
    image: nginx
    container_name: mynginx
    ports:
      - "80:80"
    restart: always

(1)no:默认的重启策略,在任何情况下都不会重启容器;
(2)on-failure:容器非正常退出时,比如退出状态为非0(异常退出),才会重启容器;
(3)always:容器总是重新启动,即使容器被手动停止了,当Docker重启时容器也还是会一起启动;
(4)unless-stopped:容器总是重新启动,除非容器被停止(手动或其他方式),那么Docker重启时容器则不会启动。

(11)environment 环境变量

添加环境变量。可以使用数组也可以使用字典。布尔相关的值(true、false、yes、no)都需要用引号括起来,以确保 YML 解析器不会将它们转换为真或假。

environment:
  RUOYI_ENV: development
  SHOW: 'true'
  SESSION_SECRET:

或者以下格式

environment:
  - RUOYI_ENV=development
  - SHOW=true
  - SESSION_SECRET

env_file 文件获取环境变量,从文件中获取环境变量,可以指定一个或多个文件,其优先级低于environment指定的环境变量。

env_file:
  - /opt/runtime_opts.env # 绝对路径
  - ./common.env # 相对路径,相对当前 docker-compose.yml 文件所在目录
  - ./apps/web.env # 相对路径,相对当前 docker-compose.yml 文件所在目录

注意:env 文件中的每一行需采用键=值格式。以#开头的行会被视为注释并被忽略。空行也会被忽略。

(12)command 执行命令

覆盖容器启动后默认执行的命令。

command: echo "helloworld"

该命令也可以是一个列表。

command: ["echo", "helloworld"]

(13)volumes 目录挂载

数据卷,用于实现目录挂载,支持指定目录挂载、匿名挂载、具名挂载。

(1)指定目录挂载的格式为:左边宿主机目录:右边容器目录,或者左边宿主机目录:右边容器目录:读写权限;
(2)匿名挂载格式为:容器目录即可,或者容器目录即可:读写权限;
(3)具名挂载格式为:数据卷条目名称:容器目录,或者数据卷条目名称:容器目录:读写权限。

# 描述 Compose 文件的版本信息
version: "3.8"

# 定义服务,可以多个
services:
  mysql: # 服务名称
    image: mysql:8 # 创建容器时所需的镜像
    container_name: mysql8 # 容器名称,默认为"工程名称_服务条目名称_序号"
    ports: # 宿主机与容器的端口映射关系
      - "3306:3306" # 左边宿主机端口:右边容器端口
    environment: # 创建容器时所需的环境变量
      MYSQL_ROOT_PASSWORD: 1234
    volumes:
      # 绝对路径
      - "/mydata/docker_mysql/data:/var/lib/mysql"
      # 相对路径,相对当前 docker-compose.yml 文件所在目录
      - “./conf:/etc/mysql/conf.d“
      # 匿名挂载,匿名挂载只需要写容器目录即可,容器外对应的目录会在 /var/lib/docker/volume 中生成
      - "/var/lib/mysql"
      # 具名挂载,就是给数据卷起了个名字,容器外对应的目录会在 /var/lib/docker/volume 中生成
      - "mysql-data-volume:/var/lib/mysql"

# 定义数据卷,可以多个
volumes:
  mysql-data-volume: # 一个具体数据卷的条目名称
    name: mysql-data-volume # 数据卷名称,默认为"工程名称_数据卷条目名称"

(14)network_mode 网络模式

设置网络模式,类似 docker run 时添加的参数 --net host 或者 --network host 的用法

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

(15)networks

配置容器连接的网络,引用顶级 networks 下的条目。

# 定义服务,可以多个
services:
  nginx: # 服务名称
    networks: # 配置容器连接的网络,引用顶级 networks 下的条目
      - nginx-net # 一个具体网络的条目名称

# 定义网络,可以多个。如果不声明,默认会创建一个网络名称为"工程名称_default"的 bridge 网络
networks:
  nginx-net: # 一个具体网络的条目名称
    name: nginx-net # 网络名称,默认为"工程名称_网络条目名称"
    driver: bridge # 网络模式,默认为 bridge

(16)aliases

网络上此服务的别名。同一网络上的其他容器可以使用服务名或此别名连接到服务容器。同一服务在不同的网络上可以具有不同的别名。

# 定义服务,可以多个
services:
  nginx: # 服务名称
    networks: # 配置容器连接的网络,引用顶级 networks 下的条目
      nginx-net: # 一个具体网络的条目名称
        aliases: # 服务别名,可以多个
          - nginx1 # 同一网络上的其他容器可以使用服务名或此别名连接到服务容器

# 定义网络,可以多个。如果不声明,默认会创建一个网络名称为"工程名称_default"的 bridge 网络
networks:
  nginx-net: # 一个具体网络的条目名称
    name: nginx-net # 网络名称,默认为"工程名称_网络条目名称"
    driver: bridge # 网络模式,默认为 bridge

【4】compose的概念和常用命令

(1)部分命令选项
1)-f,–file:指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定,指定多个 yml;
2)-p, --project-name:指定工程名称,默认使用 docker-compose.yml 文件所在目录的名称;
3)-v:打印版本并退出;
4)–log-level:定义日志等级(DEBUG, INFO, WARNING, ERROR, CRITICAL)。
#help

(2)help
docker-compose -help查看帮助。

(3)config
docker-compose config -q验证docker-compose.yml文件。当配置正确时,不输出任何内容,当配置错误时,输出错误信息。

(4)pull
docker-compose pull拉取服务依赖的镜像。

# 拉取工程中所有服务依赖的镜像
docker-compose pull
# 拉取工程中 nginx 服务依赖的镜像
docker-compose pull nginx
# 拉取镜像过程中不打印拉取进度信息
docker-compose pull -q

(5)up
docker-compose up创建并启动所有服务的容器。指定多个yml加-f选项。以守护进程模式运行加-d选项。

# 前台启动
docker-compose up
# 后台启动
docker-compose up -d
# -f 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定,指定多个 yml
docker-compose -f docker-compose.yml up -d 

(6)logs
docker-compose logs查看服务容器的输出日志。默认情况下,docker-compose将对不同的服务输出使用不同的颜色来区分。可以通过–no-color来关闭颜色。

# 输出日志,不同的服务输出使用不同的颜色来区分
docker-compose logs
# 跟踪日志输出
docker-compose logs -f
# 关闭颜色
docker-compose logs --no-color

(7)ps
docker-compose ps列出工程中所有服务的容器。

# 列出工程中所有服务的容器
docker-compose ps
# 列出工程中指定服务的容器
docker-compose ps nginx

(8)run
docker-compose run在指定服务容器上执行一个命令。

# 在工程中指定服务的容器上执行 echo "helloworld"
docker-compose run nginx echo "helloworld"

(9)exec
docker-compose exec进入服务容器。

# 进入工程中指定服务的容器
docker-compose exec nginx bash
# 当一个服务拥有多个容器时,可通过 --index 参数进入到该服务下的任何容器
docker-compose exec --index=1 nginx bash

(10)pause
docker-compose pause暂停服务容器

# 暂停工程中所有服务的容器
docker-compose pause
# 暂停工程中指定服务的容器
docker-compose pause nginx

(11)unpause
docker-compose unpause恢复服务容器。

# 恢复工程中所有服务的容器
docker-compose unpause
# 恢复工程中指定服务的容器
docker-compose unpause nginx

(12)restart
docker-compose restart重启服务容器。

# 重启工程中所有服务的容器
docker-compose restart
# 重启工程中指定服务的容器
docker-compose restart nginx

(13)start
docker-compose start启动服务容器。

# 启动工程中所有服务的容器
docker-compose start
# 启动工程中指定服务的容器
docker-compose start nginx

(14)stop
docker-compose stop停止服务容器。

# 停止工程中所有服务的容器
docker-compose stop
# 停止工程中指定服务的容器
docker-compose stop nginx

(15)kill
docker-compose kill通过发送SIGKILL信号停止指定服务的容器。

# 通过发送 SIGKILL 信号停止工程中指定服务的容器
docker-compose kill nginx

(16)rm
docker-compose rm 删除服务(停止状态)容器。

# 删除所有(停止状态)服务的容器
docker-compose rm
# 先停止所有服务的容器,再删除所有服务的容器
docker-compose rm -s
# 不询问是否删除,直接删除
docker-compose rm -f
# 删除服务容器挂载的数据卷
docker-compose rm -v
# 删除工程中指定服务的容器
docker-compose rm -sv nginx

(17)down
停止并删除所有服务的容器、网络、镜像、数据卷。

# 停止并删除工程中所有服务的容器、网络
docker-compose stop
# 停止并删除工程中所有服务的容器、网络、镜像
docker-compose down --rmi all
# 停止并删除工程中所有服务的容器、网络、数据卷
docker-compose down -v

(18)images
docker-compose images打印服务容器所对应的镜像。

# 打印所有服务的容器所对应的镜像
docker-compose images
# 打印指定服务的容器所对应的镜像
docker-compose images nginx

(19)port
docker-compose port打印指定服务容器的某个端口所映射的宿主机端口。

docker-compose port nginx 80

(20)top
docker-compose top显示正在运行的进程。

# 显示工程中所有服务的容器正在运行的进程
docker-compose top
# 显示工程中指定服务的容器正在运行的进程
docker-compose top nginx

(1)启动

# 前台启动
docker-compose up
# 后台启动
docker-compose up -d

(2)停止并删除容器、网络

docker-compose down

【八】compose的安装

【1】在线安装

# 通过url下载
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 授权
sudo chmod +x /usr/local/bin/docker-compose

【2】离线安装

(1)下载地址
https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-linux-x86_64

# 改名为docker-compose
mv docker-compose-Linux-x86_64 docker-compose

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

docker-compose -v

在这里插入图片描述

【九】用Docker-compose完成项目部署的案例

【2】ruoyi系统的容器化部署过程

(1)安装Nacos

拉取官方nacos镜像,目前若依微服务最新版本需要安装的是2.0.4版本,如需更改请根据实际情况修改拉取的版本号

docker pull nacos/nacos-server

启动nacos 需要暴露8848 9848 9849 端口

docker run --env MODE=standalone --name nacos -d -p 8848:8848 -p 9848:9848 -p 9849:9849 nacos/nacos-server

MODE=standalone表示单机启动

(2)安装Nginx

拉取官方nginx镜像,默认拉取最新版本

docker pull nginx

创建Nginx容器。

docker run -di --name nginx -p 80:80 nginx

将容器内的配置文件拷贝到指定目录(请先提前创建好目录)

# 创建目录
mkdir -p /home/ruoyi/nginx

# 将容器内的配置文件拷贝到指定目录
docker cp nginx:/etc/nginx /home/ruoyi/nginx/conf

终止并删除容器 需要执行

docker stop nginx
docker rm nginx

创建Nginx容器,并将容器中的/etc/nginx目录和宿主机的/home/ruoyi/nginx/conf目录进行挂载。

docker run -di --name nginx -p 80:80 -v /home/ruoyi/nginx/conf:/etc/nginx nginx

(3)安装Mysql8

(1)拉取官方mysql8.0镜像

docker pull mysql:8.0

(2)在本地创建mysql的映射目录

mkdir -p /home/mysql/data /home/mysql/logs /home/mysql/conf

(3)创建容器,将数据、日志、配置文件映射到本机

#此处的password为即将设置的数据库密码建议修改成为自己的密码
docker run -p 3306:3306 --name mysql -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/logs:/logs -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0

(4)进入容器/执行命令:docker exec -it mysql /bin/bash

更改数据库密码

docker exec -it mysql /bin/bash		#未挂载镜像时进入MySQL方式
//docker exec -it 122c297e7298 bash  #挂载后进入容器方式,容器id 使用此命令进入mysql需要先执行docker ps 找到mysql镜像id
mysql -uroot -p
use mysql
flush privileges;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';
flush privileges;
exit

(4)安装redis

拉取官方redis镜像

docker pull redis

创建容器

docker run -di --name redis -p 6379:6379 redis

连接容器中的Redis时,只需要连接宿主机的IP + 指定的映射端口即可。

(5)下载若依系统

git地址:https://gitee.com/y_project/RuoYi-Cloud
项目提供了docker部署,只需要复制jar文件到对应的/docker/ruoyi目录下。

(6)修改bootstrap.yml配置文件

在这里插入图片描述
其他服务bootstrap.yml配置与auth保持一致

ruoyi-gateway如不需要使用sentinel可以将此处注释
在这里插入图片描述

(7)打包

(1)在运行代码正常无bug情况下开始打包操作,然后把所有服务都停止
在这里插入图片描述
(2)maven执行clean操作(请保证执行clean操作是在ruoyi(root)里进行操作)
在这里插入图片描述
(3)将所有模块配置完成后进行maven打jar包操作(在模块未运行的情况下进行打包操作)
在这里插入图片描述执行完毕可以看到所在模块下已经生成target文件了
在这里插入图片描述

(8)操作项目文件里的文件/docker/ruoyi

(1)将生成的jar包放入若依自带的docker文件夹指定目录
在这里插入图片描述
(2)把生成的jar包复制到对应的文件里
在docker文件夹下ruoyi目录的操作到此为止dockerfile文件无需进行操作

(9)操作docker/mysql

将项目里的SQL脚本文件放到此文件夹目录下
【注意的是:项目里给的ry-cloud脚本里没有建库语句,需要自己加上。更简单的,还是自己使用navicat连上数据库以后,直接建库,然后执行建表脚本就行了】
在这里插入图片描述

因为我们在docker里面安装的是mysql8.0版本所以下面需要进行修改一下配置

在这里插入图片描述

(10)操作docker/nacos

进入此目录编辑nacos配置文件
在这里插入图片描述在这里插入图片描述

(11)操作docker\nginx\conf

编辑这个文件
在这里插入图片描述
建议使用默认配置
在这里插入图片描述
因为我们在docker中拉取的是nginx最新版本索引nginx的dockerfile不需要进行修改操作

(12)操作docker\nginx\html\dist这个文件

此处将前端代码打包,只介绍在idea打包方式,前端项目打包可让前端进行打包
进入ruoyi-ui目录
在这里插入图片描述
执行npm run build:prod命令【执行此命令前置操作下载前端依赖需执行npm install --registry=https://registry.npm.taobao.org命令】

在这里插入图片描述
在这里插入图片描述
docker/redis无需进行操作

(13)操作docker下docker-compose.yml文件

编辑此文件
因为拉去的nacos镜像为2.0.4版本,mysql镜像为8.0版本索引进行以下操作
在这里插入图片描述
在这里插入图片描述

(14)将docker文件夹上传至linux

把准备好的docker文件放到home文件夹下
在这里插入图片描述

(15)运行服务

(1)首先禁用防火墙

systemctl status firewalld.service
systemctl stop firewalld.service

也可永久关闭防火墙

systemctl disable firewalld.service

(2)查看docker日志

# 输出日志,不同的服务输出使用不同的颜色来区分
docker-compose logs
# 跟踪日志输出
docker-compose logs -f
# 关闭颜色
docker-compose logs --no-color

(3)查看所侦听的端口

netstat -luntp			#用于查看服务端口是否被侦听

(4)运行服务

cd /home/docker/		#进入docker文件所在目录

./deploy.sh port		# 开启所需端口	因为在之前已经关闭防火墙,此命令无需执行
	
#注意执行完此命令后请执行	docker-compose logs -f 	#跟踪启动服务的日志打印 
#如有报错说明配置有误,请先解决完报错保证nacos,mysql,redis启动成功
./deploy.sh base		# 启动基础环境(必须)

启动后发现报错
在这里插入图片描述这是因为在启动docker的时候防火墙做了策略,如果容器在运行中,停止防火墙,在操作容器就会报这个错误,我们可以重启docker解决此问题

systemctl restart docker

然后再执行

./deploy.sh base		# 启动基础环境(必须)

在这里插入图片描述

(16)检查一下启动结果

(1)连接nacos
IP地址为虚拟机IP地址

http://192.168.136.135:8848/nacos

(2)编辑nacos配置
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
此处仅介绍system配置,其他配置参考system配置即可

配置完成后执行下面命令保证修改后的配置能够被服务读取

./deploy.sh stop		# 关闭所有环境/模块		重启服务时执行此操作保证修改的配置被读取

./deploy.sh rm			# 删除所有环境/模块		重启服务时执行此操作保证修改的配置被读取

(17)修改完配置后再次启动

(1)执行完以上命令后再次执行以下命令

./deploy.sh base		#执行完此命令请等待两分钟保证nacos,mysql,redis成功启动后执行后续命令

执行完./deploy.sh base命令后在linux中查看正在运行的容器,以下为成功启动并运行
在这里插入图片描述
nacos启动有点慢,在portainer要看到下面结果才算启动完成
在这里插入图片描述

(2)base命令成功启动完服务后执行此命令
等到nacos页面能正常访问了,再执行

./deploy.sh modules		# 启动程序模块(必须)base命令成功启动完服务后执行此命令

执行后要等一会,等到服务启动成功,可以看nacos的服务列表,看看是不是都注册成功了,从而判断是否启动成功

浏览器访问http://192.168.136.135 IP地址为虚拟机IP地址,默认访问80端口

(18)启动出现问题

启动模块以后,使用docker-compose logs -f跟踪查看启动日志,发现gatewaye和auth都启动成功了,但是modules没有启动成功,在nacos的服务列表里也没有,报错内容如下
在这里插入图片描述
ruoyi-system模块报错:
Invalid bound statement (not found): com.ruoyi.system.mapper.SysConfigMapper.selectConfigList

翻译:无效绑定,找不到selectConfigList方法
1.出现此报错,普遍步骤查看xml -->> namespace + 方法id是否与mapper中对应
2.如果对应仍然报错,则可能是未读取到xml,打包后看target中是否存在xml文件,如果不存在则需要看resource文件夹是否是资源目录或者在xml中指定包路径
3.另外可能就是项目根本就没读取到nacos配置,需要我们在bootstrap.yml中设置

本人是第三种情况

【十】基于Docker+Jenkins+Git的发布环境搭建

【十】k8s学习笔记