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

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

  • 【一】环境的搭建
    • 【1】shell和ftp工具选择
    • 【2】安装Docker
      • (1)查看系统的内核版本
      • (2)yum更新到最新版本
      • (3)安装Docker所需的依赖包
      • (4)设置Docker的yum的源
      • (5)查看仓库所有Docker版本
      • (6)安装Docker
      • (7)启动Docker并添加开机自启动
      • (8)查看Docker版本
      • (9)卸载Docker
      • (10)Docker常用命令
      • (11)如何创建自启动的容器
    • 【3】安装Portainer
      • (1)拉取最新的Portainer镜像
      • (2)运行镜像
      • (3)访问Portainer可视化界面
      • (4)一些问题的解决
    • 【4】安装redis
      • (1)准备好redis.conf
      • (2)修改的内容
      • (3)SFTP上传redis.conf
      • (4)启动redis
      • (5)查看Portainer的页面
      • (6)使用本地RDM链接redis
      • (7)使用redis容器的终端链接redis
    • 【5】安装redis集群
      • (1)面试题
      • (2)搭建三主三从redis集群
      • (3)主从容错切换迁移案例
      • (4)主从扩容案例
      • (5)主从缩容案例
    • 【6】安装kafka
      • (1)下载镜像
      • (2)启动zookeeper
      • (3)启动kafka
      • (4)防火墙设置
      • (5)kafka日志
      • (6)Kafka 控制台操作
      • (7)待补充
    • 【7】安装mysql
    • 【8】安装mysql主从复制
      • (1)新建主服务器容器实例3307
      • (2)进入/mydata/mysql-master/conf目录下新建my.cnf
      • (3)修改完配置后重启master实例
      • (4)进入mysql-master容器
      • (5)master容器实例内创建数据同步用户
      • (6)新建从服务器容器实例3308
      • (7)进入/mydata/mysql-master/conf目录下新建my.cnf
      • (8)修改完配置后重启slave实例
      • (9)在主数据库中查看主从同步状态
      • (10)进入mysql-slave容器
      • (11)在从数据库中配置主从复制
      • (12)在从数据库中查看主从同步状态
      • (13)在从数据库中开启主从同步
      • (14)查看从数据库状态发现已经同步
      • (15)主从复制测试
    • 【9】安装xxl-job
      • (1)导入sql
      • (2)安装xxl-job
      • (3)配置任务
      • (4)工程配置xxl-job
      • (5)测试验证(待补充)
    • 【10】安装nacos
    • 【11】安装Elasticsearch
    • 【12】安装Kibana
    • 【13】安装canal(待补充)
    • 【14】安装nginx
      • (1)下载Nginx镜像(下面两种选择一个)
      • (2)创建Nginx配置文件
      • (3)创建Nginx容器并运行
      • (4)结果检测
      • (5)修改nginx配置
  • 【二】总结上面案例中的概念和常用的Docker命令
    • 【1】常用的概念
    • 【2】镜像命令
    • 【3】容器命令
    • 【4】镜像构建
      • (1)介绍
      • (2)docker commit构建镜像
  • 【三】挂载是怎么个事
  • 【四】网络是怎么个事
  • 【五】Dockerfile
    • 【1】介绍
    • 【2】Dockerfile 常用指令
    • 【3】构建镜像
    • 【4】Dockerfile 实践
    • 【5】镜像仓库
  • 【六】用dockerfile完成项目部署的案例
    • 【1】案例一:包括mysql和Redis
  • 【七】docker-compose
    • 【1】介绍(docker容器太多了如何管理)
    • 【2】举例说明
    • 【3】docker-compose.yml 文件详解
      • (1)介绍
      • (2)version 版本信息
      • (3)services 定义服务
      • (4)image 镜像名称标签
      • (5)dockerfile 构建镜像
      • (6)container_name 容器名称
      • (7)depends_on 容器依赖
      • (8)ports 暴露端口
      • (9)expose 接受端口范围
      • (10)restart 重启策略
      • (11)environment 环境变量
      • (12)command 执行命令
      • (13)volumes 目录挂载
      • (14)network_mode 网络模式
      • (15)networks
      • (16)aliases
    • 【4】compose的概念和常用命令
    • 【5】compose的实战安装和配置过程
    • 【6】ruoyi系统的容器化部署过程
  • 【八】基于Docker+Jenkins+Git的发布环境搭建
  • 【九】k8s学习笔记

【一】环境的搭建

【1】shell和ftp工具选择

选择是的mac版termius

【2】安装Docker

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

[root@CodeGuide ~]# uname -r
4.18.0-80.11.2.el8_0.x86_64

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

(2)yum更新到最新版本

[root@CodeGuide ~]# sudo yum update
Last metadata expiration check: 1:15:10 ago on Sat 27 Nov 2021 04:22:53 PM CST.
Dependencies resolved.
Nothing to do.
Complete!

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

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

[root@CodeGuide ~]# sudo yum install -y yum-utils device-mapper-persistent-data lvm2
Last metadata expiration check: 1:16:16 ago on Sat 27 Nov 2021 04:22:53 PM CST.
Package yum-utils-4.0.21-3.el8.noarch is already installed.
Package device-mapper-persistent-data-0.9.0-4.el8.x86_64 is already installed.
Package lvm2-8:2.03.12-10.el8.x86_64 is already installed.
Dependencies resolved.
Nothing to

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

(4)设置Docker的yum的源

[root@CodeGuide ~]# sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Adding repo from: https://download.docker.com/linux/centos/docker-ce.repo

执行命令:sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

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

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

(6)安装Docker

安装默认最新版本的Docker

udo yum install docker-ce

安装指定版本,例如

sudo yum install docker-ce-20.10.11.ce

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

启动Docker

sudo systemctl start docker

设置开机启动Docker

systemctl enable docker

重启docker

systemctl restart docker

停止docker

systemctl stop docker

(8)查看Docker版本

docker --version

(9)卸载Docker

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine

(10)Docker常用命令

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

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

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

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

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

【3】安装Portainer

(1)拉取最新的Portainer镜像

docker pull portainer/portainer

(2)运行镜像

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,可以查看宿主机配置信息、查看容器、镜像、网络、卷等相关信息。

【Docker】完整的搭建和发布过程_第1张图片
(2)创建登录账号和密码
【Docker】完整的搭建和发布过程_第2张图片
【Docker】完整的搭建和发布过程_第3张图片
【Docker】完整的搭建和发布过程_第4张图片

(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)

【4】安装redis

(1)准备好redis.conf

下载地址:redis.conf

(2)修改的内容

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

(3)SFTP上传redis.conf

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

把修改后的 redis.conf 文件通过 SFTP 上传到 /data/redis 文件夹下
【Docker】完整的搭建和发布过程_第5张图片

(4)启动redis

docker run -p 6379:6379 --name redis -v /data/redis/redis.conf:/etc/redis/redis.conf  -v /data/redis/data:/data -d redis 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 redis

【Docker】完整的搭建和发布过程_第6张图片
没有报错,启动成功

(5)查看Portainer的页面

【Docker】完整的搭建和发布过程_第7张图片

(6)使用本地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
【Docker】完整的搭建和发布过程_第8张图片
测试redis
【Docker】完整的搭建和发布过程_第9张图片

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

docker exec -it redis /bin/bash

【Docker】完整的搭建和发布过程_第10张图片

【5】安装redis集群

(1)面试题

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

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

(1)哈希取余分区
在这里插入图片描述在这里插入图片描述(2)一致性哈希算法分区
【Docker】完整的搭建和发布过程_第11张图片(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

【Docker】完整的搭建和发布过程_第12张图片
【Docker】完整的搭建和发布过程_第13张图片
(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节点


【Docker】完整的搭建和发布过程_第14张图片
(3)链接进入6381作为切入点,查看节点状态

redis-cli -p 6381
cluster info

【Docker】完整的搭建和发布过程_第15张图片
在这里插入图片描述
【Docker】完整的搭建和发布过程_第16张图片

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

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

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

单机模式连接

redis-cli -p 6381

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

redis-cli -p 6381 -c

【Docker】完整的搭建和发布过程_第17张图片(2)容错切换迁移(测试主从切换)
首先在6381主机中查看集群信息
在这里插入图片描述停掉6381主机
【Docker】完整的搭建和发布过程_第18张图片重新进入6382

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

查看集群信息,可以看到原来的6386从机已经变成了主机
【Docker】完整的搭建和发布过程_第19张图片把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表示结束
【Docker】完整的搭建和发布过程_第20张图片
(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

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

(3)启动kafka

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】完整的搭建和发布过程_第21张图片【Docker】完整的搭建和发布过程_第22张图片在 Docker 容器中可以点击 Kafka 进入日志查看和控制台操作

(6)Kafka 控制台操作

【Docker】完整的搭建和发布过程_第23张图片
在 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

(1)拉取镜像:docker pull mysql:5.7
(2)查看本地镜像:docker images
(3)创建一个mysql容器,首先在根目录下创建好一个文件夹allenuse
【Docker】完整的搭建和发布过程_第24张图片

(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 mysql mysql:5.7

如果报错的话,可能是端口3306被占用了,就用下面的命令解决
1-先查看当前占用端口:netstat -tanlp
2-杀死对应的进程:kill 1330
【Docker】完整的搭建和发布过程_第25张图片(5)查看是否创建成功
1-查看容器:docker ps 或者 docker ps -a
2-查看启动日志:docker logs mysql

(6)新建my.cnf,通过容器卷同步给mysql容器实例(解决中文乱码问题)
【Docker】完整的搭建和发布过程_第26张图片

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

(7)重启mysql容器实例,再重新进入并查看字符编码
1-重启:docker restart mysql
2-查看字符编码:docker exec -it mysql /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 mysql mysql:5.7

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

(11)本地连接
【Docker】完整的搭建和发布过程_第27张图片
【Docker】完整的搭建和发布过程_第28张图片
(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

【Docker】完整的搭建和发布过程_第29张图片

[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;

【Docker】完整的搭建和发布过程_第30张图片

(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;

【Docker】完整的搭建和发布过程_第31张图片

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

start slave;

【Docker】完整的搭建和发布过程_第32张图片

(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 文件
【Docker】完整的搭建和发布过程_第33张图片

(2)安装xxl-job

(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)查看日志
【Docker】完整的搭建和发布过程_第34张图片
(4)打开xxl-job的后台
http://你的ip:7397/xxl-job-admin/
【Docker】完整的搭建和发布过程_第35张图片

(3)配置任务

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

(4)工程配置xxl-job

(1)查看xxl-job启动参数
【Docker】完整的搭建和发布过程_第38张图片
(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

(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
【Docker】完整的搭建和发布过程_第39张图片
(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

(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
【Docker】完整的搭建和发布过程_第40张图片
(4)启动
http://39.96.73.167:9200
【Docker】完整的搭建和发布过程_第41张图片

【12】安装Kibana

(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
【Docker】完整的搭建和发布过程_第42张图片

【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

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

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

【Docker】完整的搭建和发布过程_第43张图片

(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/

【Docker】完整的搭建和发布过程_第44张图片

(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)结果检测

【Docker】完整的搭建和发布过程_第45张图片
然后访问一下网址试试
【Docker】完整的搭建和发布过程_第46张图片
成功

(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镜像中安装和配置需要的软件构建出来的。
【Docker】完整的搭建和发布过程_第47张图片
从上图可以看到,新镜像是从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

【2】Dockerfile 常用指令

(1)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”]
指定容器挂载点到宿主机自动生成的目录或其他容器。一般的使用场景为需要持久化存储数据时

【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
【Docker】完整的搭建和发布过程_第48张图片

(3)登录账号
通过docker login命令输入账号密码登录DockerHub
【Docker】完整的搭建和发布过程_第49张图片
(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)查看仓库
【Docker】完整的搭建和发布过程_第50张图片

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

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

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

【1】案例一:包括mysql和Redis

(1)准备项目代码进行本地测试
(2)修改项目代码的配置
包括mysql和redis,连接信息等等要改成对应的数据

(3)项目打成war包
如果达成jar包的话会报错找不到jsp文件
项目打成war包,clean+package
【Docker】完整的搭建和发布过程_第51张图片
找到war包的位置,package点击完后,控制台输出打包结果,复制路径找到war包
【Docker】完整的搭建和发布过程_第52张图片

(4)启动各个容器
包括docker、mysql、redis
注意的是:
1-要么把redis的密码设置上,要么把把保护机制设置为no
2-配置文件里的port是6379,那么创建容器的时候对应的端口就要也是6379,项目配置文件里也是

(5)导入项目的数据到mysql
可以通过外网的工具navicat连接服务器的mysql,然后方便操作

(6)上传springboot项目到服务器,防火墙开放端口
可以使用sftp工具实现往服务器上传文件

(7)编写dockerfile文件

#定义父镜像
FROM java:8
#定义作者信息
MAINTAINER AllenSun<>
#VOLUME指定临时文件目录为tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
#ADD 文件名 app.jar (我到时打算把jar包和Dockerfile文件放在同一级目录文件)
ADD ./group5-0.0.1-SNAPSHOT.jar allen_docker.jar
#运行jar包
RUN bash -c ‘touch /allen_docker.jar’
ENTRYPOINT [“java”,-jar”,/allen_docker.jar”]
#暴露6001端口作为项目端口
EXPOSE 7777

(8)用dockerfile构建镜像

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

【Docker】完整的搭建和发布过程_第53张图片

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

【Docker】完整的搭建和发布过程_第54张图片

(9)使用镜像创建容器
暴露的端口号是7777

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

(10)本地测试
首先通过docker logs 容器ID来查看springboot是不是真的启动成功了
docker run -p 6379:6379 --name myredis3 --privileged=true -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf

【七】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),每个服务中定义了创建容器时所需的镜像、参数、依赖等。

示例

# 描述 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

(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

【5】compose的实战安装和配置过程

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

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

【九】k8s学习笔记

你可能感兴趣的:(docker,容器,运维)