首页
关于
推荐
CSDN
Search
1
文件上传下载-io-流的理解-笔记
128 阅读
2
vue循环指令el-table-column展示图片src路径拼接
121 阅读
3
正则表达式,将字符串分割两部分
111 阅读
4
MySQL数据库练习【一】
109 阅读
5
MySQL数据库练习【三】
92 阅读
默认分类
Mysql
Java基础
一天一练
Mongodb
Nginx
Docker
FastDFS
面试题
云计算基础
linux基础
shell脚本
实验
工具
基础命令
redis
zookeeper
部署
案例
登录
Search
标签搜索
vue
Mysql
IO
面试题
良辰美景好时光
累计撰写
67
篇文章
累计收到
0
条评论
首页
栏目
默认分类
Mysql
Java基础
一天一练
Mongodb
Nginx
Docker
FastDFS
面试题
云计算基础
linux基础
shell脚本
实验
工具
基础命令
redis
zookeeper
部署
案例
页面
关于
推荐
CSDN
搜索到
2
篇与
的结果
2024-10-08
Docker搭建部署Typecho博客【详细版】
@TOC一、环境准备1.1.准备阿里云服务器【新用户免费使用三个月】阿里云服务器链接专享:https://www.aliyun.com/daily-act/ecs/activity_selection?userCode=yu4fhct71.2.准备远程工具【FinalShell】官网:http://www.hostbuf.com/下载链接:http://www.hostbuf.com/t/988.html1.3.系统信息# 查看版本信息,内核信息 cat /etc/redhat-release uname -r1.4.安装所需软件包# 安装gcc环境 yum -y install gcc yum -y install gcc-c++ # 工具虚拟机联网,安装yum工具包 yum install -y yum-utils device-mapper-persistent-data lvm2 --skip-broken # 升级yum工具 yum update -y # 安装unzip解压软件 yum -y install unzip # 安装必要的软件 yum install -y git vim wget tree yum install -y pcre pcre-devel zlib zlib-devel openssl openssl-devel1.5.设置docker镜像源# 设置docker镜像源,国内aliyun,加快访问速度 yum-config-manager \ --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo1.6.更新yum软件包索引# 更新yum软件包索引 yum makecache fast1.7.确认停用selinuxselinux(security-enhanced linux),美国安全局对于强制访问控制的实现,在linux2.6内核以后的版本中,selinux已经成功内核中的一部分。可以说selinux是linux史上最杰出的新安全子系统之一。虽然有了selinux,我们的系统会更安全,但是对于我们的学习Nginx的历程中,会多很多设置,所以这块建议大家将selinux进行关闭。# 查看状态 sestatus如果查看不是disabled状态,我们可以通过修改配置文件来进行设置,修改SELINUX=disabled,然后重启下系统即可生效。vim /etc/selinux/config # 重启系统 reboot二、安装Docker2.1.安装Docker-Ceyum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin2.2.查看是否安装成功# 查看安装版本信息 docker -v docker version2.3.启动Docker启动docker: systemctl start docker 停止docker: systemctl stop docker 重启docker: systemctl restart docker 查看docker状态: systemctl status docker 开机启动: systemctl enable docker2.4.docker镜像相关操作命令# 列出本地主机上的镜像 docker images #列出本地所有的镜像(含历史映像层) docker images -a #只列出5个redis镜像 docker search --limit 5 redis # 下载镜像 docker pull 镜像名字[:TAG] {TAG:镜像的标签版本号} #没有TAG就是最新版本 docker pull 镜像名字 docker pull 镜像名字:latest #删除某个镜像 docker rmi 某个镜像名字ID #强制删除某个镜像 docker rmi -f 某个镜像名字ID2.5.docker容器相关操作命令#列出当前所有正在运行的容器 docker ps docker ps [OPTIONS] OPTIONS说明(常用): -a :列出当前所有正在运行的容器+历史上运行过的 -l :显示最近创建的容器。 -n :显示最近n个创建的容器。 -q :静默模式,只显示容器编号。#启动已停止运行的容器 docker satrt 容器ID或者名字 #重启容器 docker resatrt 容器ID或者名字 #停止容器 docker stop 容器ID或者名字 #删除已停止的容器 docker rm 容器ID docker rm -f 容器ID三、Typecho安装与部署【方式一】3.1.拉取typecho镜像# 查询镜像 docker search typecho --limit 5 # 拉取镜像 docker pull 80x86/typecho #查看本地镜像 docker images3.2.实例化容器docker run -d \ --name=typecho \ --restart always \ -e PHP_TZ=Asia/Shanghai \ -e PHP_MAX_EXECUTION_TIME=600 \ -p 80:80 80x86/typecho:latest3.3.阿里云开放80端口3.4.访问测试3.5.进入容器安装Mysql服务# 进入容器内部 docker exec -it typecho sh # 安装数据库客户端 apk add mysql mysql-client # 初始化数据库 mysql_install_db --user=mysql --datadir=/var/lib/mysql # 安装openrc apk add openrc # 启动mariadb服务 rc-service mariadb start # 设置mysql数据库密码 mysql_secure_installation # 进入数据库 mysql -u root -p 自己的密码 # 创建数据库 create database typecho; 3.6.配置typecho3.7.查看网站3.8.下载并导入新主题# 创建文件夹用于本地保存主题 mkdir -p /app/typecho/themes cd /app/typecho/themes # 克隆安装Joe主题 git clone https://github.com/HaoOuBa/Joe.git # 手动下载并解压缩 unzip Joe-master.zip # 向容器导入新主题 docker cp Joe-master typecho:/data/themes3.9.查看新主题3.10.将容器导出,方便我们在其他Docker环境部署安装mkdir -p /docker/container cd /docker/container docker ps # be6788016e06为自己容器的ID,按实际情况 docker export be6788016e06 > typecho-1.1.tar3.11.缺点无法连接数据库,进行数据备份必须进入容器,才能操作数据库主题不方便导入3.12.总结使用docker部署搭建typecho博客非常简单,将数据库和博客放在同一个容器内,方便导出,处处DOCKER环境可部署,方便备份,导入导出容器。四、Typecho安装与部署【方式二】4.1.拉取镜像docker pull 80x86/typecho # 不加版本号5.7,默认拉取的是最新版 docker pull mysql:5.74.2.实例化typecho容器docker run -d \ --name=typecho \ --restart always \ -v /app/typecho/themes:/data/themes \ -e PHP_TZ=Asia/Shanghai \ -e PHP_MAX_EXECUTION_TIME=600 \ -p 80:80 80x86/typecho:latest# 上面保存的主题路径为:/app/typecho/themes,自然同步,以后所有的主题都可以在此目录下,自动同步 -v 挂载文件用的,表示将服务器的themes写到你docker宿主机的/app/typecho/themes下面,实现同步4.3.实例化mysql容器# 安装mysql,启动数据卷,使得将docker内的数据保留进宿主机的磁盘中,设置mysql密码为123456 docker run \ --name mysql \ --privileged=true \ -e MYSQL_ROOT_PASSWORD=123456 \ -p 3306:3306 \ -d \ mysql:5.7--name : 起名字 --privilege=true : 容器数据卷权限开启 -p : 端口映射 -d : 后台运行4.4.进入到mysql容器创建数据库# 进入容器 docker exec -it mysql /bin/bash # 进入数据库 mysql -u root -p 自己的密码 # 创建数据库 create database typecho;4.5.使用第三方工具Navicat连接数据库4.6.进行访问网站配置【和上面步骤一样】4.7.配置主题4.8.查看数据库4.9.首页文章数量默认5条,改成10条# 操作数据库 use typecho; update typecho_options set value = 10 where name = 'pageSize';4.10.总结数据库数据可进行备份也可以直接在linux下安装mysql数据库;本次使用的docker容器数据库占用比较小也可以直接将容器导出可以随时更改主题内容五、joe主题好久不见之底部网站样式5.1.修改Joe主题的footer.php文件vi /app/typecho/themes/Joe-master/public/footer.php在文件最底部添加如下内容<!-- 好久不见 --> <div class="chenyuyc"> <div class="footer-fav"> <div class="container"> <div class="fl site-info"> <h2><a href="https://itbunan.xyz" target="_blank">IT技术家园</a></h2> <div class="site-p"> <p>IT不难【白茶清欢无别事,我在等风也等你】</p> <!--<p><a href="javascript:;" id="chenyutime">风风雨雨N年,你是第N位相遇的小伙伴</a></p>--> <p><?php if ($this->options->JBirthDay) : ?> <div class="item run"> <span>风风雨雨 <strong class="joe_run__day">00</strong> 天 <strong class="joe_run__hour">00</strong> 时 <strong class="joe_run__minute">00</strong> 分,你是第<?php echo theAllViews();?>位相遇的小伙伴</span> </div> <?php endif; ?> </p> </div> </div> <div class="fr site-fav"> <a href="https://itbunan.xyz" class="btn btn-fav btn-orange">Ctrl+D收藏本站</a></div> <div class="site-girl"> <div class="girl fl"> <i class="thumb " style="background-image:url(https://cdn.jsdelivr.net/gh/cy-j/chenyu/img/cyxy.png);"></i> </div> <div class="girl-info hide_md"> <h4>绿水本无忧,因风皱面</h4> <h4>青山原不老,为雪白头</h4> </div> </div> </div> </div> </div>endl
2024年10月08日
3 阅读
0 评论
0 点赞
2024-10-03
Docker与微服务实战(基础篇与实战篇)
基础篇@TOC编码开发微服务上线部署容器化时时刻刻要监控devops一、Docker简介1.1.官网docker官网:https://www.docker.com/Docker Hub仓库官网:https://hub.docker.com/Docker hub 安装docker镜像的仓库Docker中有几个重要的概念:1.2.镜像和容器镜像(Image):Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像。容器(Container):镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器进程做隔离,对外不可见。一切应用最终都是代码组成,都是硬盘中的一个个的字节形成的文件。只有运行时,才会加载到内存,形成进程。而镜像,就是把一个应用在硬盘上的文件、及其运行环境、部分系统函数库文件一起打包形成的文件包。这个文件包是只读的。容器呢,就是将这些文件中编写的程序、函数加载到内存中允许,形成进程,只不过要隔离起来。因此一个镜像可以启动多次,形成多个容器进程。1.3.Docker架构我们要使用Docker来操作镜像、容器,就必须要安装Docker。Docker是一个CS架构的程序,由两部分组成:服务端(server):Docker守护进程,负责处理Docker指令,管理镜像、容器等客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令。如图:二、Docker安装步骤Docker必须部署在Linux内核的系统上,如果其他系统想部署Docker就必须安装一个Linux环境2.1.Centos7及以上的版本uname命令用于打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)[root@192 ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [root@192 ~]# [root@192 ~]# uname -r 3.10.0-1160.el7.x86_64Docker的基本组成:镜像(image)、容器(container)、仓库(repository)2.2.卸载旧版本https://docs.docker.com/engine/install/centos/sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-enginesudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine \ docker-ce2.3.yum安装gcc相关Centos7能上网 yum -y install gcc yum -y install gcc-c++2.4.安装需要的软件包# 国外网址,容易报错,建议不要照着国外安装 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 报错: 1[Errno 14] curl#35 -TCP connection reset by peer 2 [Errno 12] curl#35 -Timeout虚拟机联网,安装yum工具yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 --skip-broken2.5.设置stable镜像仓库【国内aliyun】然后更新本地镜像源:# 设置docker镜像源 yum-config-manager \ --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo2.6.更新yum软件包索引--以后安装更快捷# 更新yum软件包索引 yum makecache fast2.7.安装Docker-Ce然后输入命令:sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin或者yum install -y docker-cedocker-ce为社区免费版本。稍等片刻,docker即可安装成功。2.8.启动DockerDocker应用需要用到各种端口,逐一去修改防火墙设置。非常麻烦,因此建议大家直接关闭防火墙!# 关闭 systemctl stop firewalld # 禁止开机启动防火墙 systemctl disable firewalldsystemctl start docker # 启动docker服务 systemctl stop docker # 停止docker服务 systemctl restart docker # 重启docker服务2.9.测试[root@192 docker]# ps -ef | grep docker root 2001 1 7 13:40 ? 00:00:01 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock root 2291 1475 0 13:41 pts/0 00:00:00 grep --color=auto docker [root@192 docker]# [root@192 docker]# docker -v Docker version 24.0.7, build afdd53b [root@192 docker]# [root@192 docker]# docker version 2.10.卸载# 关闭docker sudo systemctl stop docker sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras # 卸载第三方库包 sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd2.11.配置阿里云镜像加速docker官方镜像仓库网速较差,我们需要设置国内镜像服务:参考阿里云的镜像加速文档:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrorshttps://promotion.aliyun.com/ntms/act/kubernetes.htmlsudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://hjisj8si.mirror.aliyuncs.com"] } EOF # 查看文件内容 cat /etc/docker/daemon.json sudo systemctl daemon-reload # 重启docker sudo systemctl restart docker三、Docker常用命令3.1.docke帮助启动类命令启动docker: systemctl start docker 停止docker: systemctl stop docker 重启docker: systemctl restart docker 查看docker状态: systemctl status docker 开机启动: systemctl enable docker 查看docker概要信息: docker info 查看docker总体帮助文档: docker --help 查看docker命令帮助文档: docker 具体命令 --help3.2.【镜像命令】3.2.1.列出本地主机上的镜像# 列出本地主机上的镜像 docker images #列出本地所有的镜像(含历史映像层) docker images -a # 只显示镜像ID docker images -q #只列出N个镜像,默认是25个 docker search --limit #只列出5个redis镜像 docker search --limit 5 redis3.2.2.查找镜像# 查找镜像 docker search [POTIONS]镜像名字3.2.3.下载镜像# 下载镜像 docker pull 镜像名字[:TAG] {TAG:镜像的标签版本号} #没有TAG就是最新版本 docker pull 镜像名字 docker pull 镜像名字:latest docker pull ubuntu docker pull redis:6.0.83.2.4.查看镜像/容器/数据卷所占的空间# 查看镜像/容器/数据卷所占的空间 docker system df3.2.5.保存镜像# 保存镜像 docker save -o [保存的目标文件名称] [镜像名称] docker save -o nginx.tar nginx:latest3.2.5.加载本地镜像# 加载本地镜像 docker load -i nginx.tar3.2.6.删除某个镜像#删除某个镜像 docker rmi 某个镜像名字ID #强制删除某个镜像 docker rmi -f 某个镜像名字ID #强制删除多个镜像 docker rmi -f 镜像名1:TAG 镜像名2:TAG #强制删除多个镜像 docker rmi -f $(docker images -qa)3.2.7.面试题:谈谈虚悬镜像是什么,怎么删除?仓库名、标签都是<none>的镜像,俗称虚悬镜像dangling image对于这样的虚悬镜像一定要删除。查看虚悬镜像命令docker images ls -f dangling=true命令结果:这种虚悬镜像已经失去了存在价值,可以删除。删除虚悬镜像命令:docker image prune3.3.容器命令【演示用ubuntu】下载一个ubuntu或者Centos镜像演示3.3.1.拉取镜像#拉取镜像 docker pull centos docker pull ubuntu3.3.2.新建+启动容器#新建+启动容器 docker run [OPTIONS] IMAGE [COMMAND][ARG...] OPTIONS说明(常用):有些是一个减号,有些是两个减号 --name="容器新名字" 为容器指定一个名称; -d : 后台运行容器并返回容器ID,也即启动守护式容器(后台运行); -i : 以交互模式运行容器,通常与-t同时使用; -t : 为容器重新分配一个伪输入终端,通常与-i同时使用;也即启动交互式容器(前台有伪终端,等待交互);3.3.3.启动交互式容器(前台命令行)#启动交互式容器(前台命令行) docker run -it ubuntu bash docker run -it ubuntu /bin/bash docker run -it --name=myu1 ubuntu bash3.3.4.列出当前所有正在运行的容器#列出当前所有正在运行的容器 docker ps docker ps [OPTIONS] OPTIONS说明(常用): -a :列出当前所有正在运行的容器+历史上运行过的 -l :显示最近创建的容器。 -n :显示最近n个创建的容器。 -q :静默模式,只显示容器编号。3.3.5.退出容器--两种退出方式#退出容器--两种退出方式 exit run进去容器,exit退出,容器停止 ctrl+p+q run进去容器,ctrl+p+q退出,容器不停止3.3.6.启动已停止运行的容器#启动已停止运行的容器 docker satrt 容器ID或者名字3.3.7.重启容器#重启容器 docker resatrt 容器ID或者名字3.3.8.停止容器#停止容器 docker stop 容器ID或者名字3.3.9.强制停止容器#强制停止容器 docker kill 容器ID或者名字3.3.10.删除已停止的容器#删除已停止的容器 docker rm 容器ID docker rm -f 容器ID #一次性删除多个容器实例 docker rm -f $(docker ps -a -q) docker ps -a -q | xargs docker rm3.4.下载一个Redis6.0.8镜像演示3.4.1.启动守护式容器(后台服务器)docker pull redis:6.0.8 #启动守护式容器(后台服务器) -d : 表示服务后台运行模式 docker run -d 容器名3.4.2.前台交互式启动【不建议】#前台交互式启动【不建议】 docker run -it redis:6.0.8 #启动后台守护式启动(后台运行) docker run -d redis:6.0.83.4.3.查看容器日志#查看容器日志 docker logs 容器ID3.4.4.查看容器内运行的进程#查看容器内运行的进程 docker top 容器ID3.4.5.查看容器内部细节#查看容器内部细节 docker inspect 容器ID3.4.6.进入正在运行的容器并以命令交互#进入正在运行的容器并以命令交互 docker exec -it 容器ID bashShell 或者重新进入【不建议】: docker attach 容器ID attach : 直接进入容器启动命令的终端,不会启动新的进程,用exit退出,会导致容器的停止 exec : 是在容器中打开新的终端,并且可以启动新的进程,用exit退出,不会导致容器的停止 推荐大家使用docker exec命令,因为退出容器终端,不会导致容器的停止[root@192 soft]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e58709da98ef redis "docker-entrypoint.s…" 14 minutes ago Up 14 minutes 6379/tcp vigilant_williams [root@192 soft]# docker exec -it e58709da98ef /bin/bash root@e58709da98ef:/data# root@e58709da98ef:/data# redis-cli -p 6379 127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> exit root@e58709da98ef:/data# exit exit [root@192 soft]# 3.4.7.从容器内拷贝文件到主机上#从容器内拷贝文件到主机上 容器->主机 docker cp 容器ID:容器内路径 目的主机路径[root@192 soft]# docker run -it ubuntu /bin/bash root@38933ab36249:/# ls bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var root@38933ab36249:/# pwd / root@38933ab36249:/# cd /tmp root@38933ab36249:/tmp# touch a2024.txt root@38933ab36249:/tmp# ll total 0 drwxrwxrwt. 1 root root 23 Jan 7 10:11 ./ drwxr-xr-x. 1 root root 17 Jan 7 10:08 ../ -rw-r--r--. 1 root root 0 Jan 7 10:11 a2024.txt root@38933ab36249:/tmp# [root@192 soft]# [root@192 soft]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 38933ab36249 ubuntu "/bin/bash" 3 minutes ago Up 3 minutes boring_brahmagupta e58709da98ef redis "docker-entrypoint.s…" 27 minutes ago Up 27 minutes 6379/tcp vigilant_williams [root@192 soft]# docker cp 38933ab36249:/tmp/a2014.txt /app/soft Error response from daemon: Could not find the file /tmp/a2014.txt in container 38933ab36249 [root@192 soft]# docker cp 38933ab36249:/tmp/a2024.txt /app/soft Successfully copied 1.54kB to /app/soft [root@192 soft]# [root@192 soft]# ll 总用量 2761172 -rw-r--r--. 1 root root 0 1月 7 18:11 a2024.txt [root@192 soft]# docker exec -it 38933ab36249 /bin/bash root@38933ab36249:/# ls bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var root@38933ab36249:/# exit exit [root@192 soft]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 38933ab36249 ubuntu "/bin/bash" 6 minutes ago Up 6 minutes boring_brahmagupta e58709da98ef redis "docker-entrypoint.s…" 31 minutes ago Up 31 minutes 6379/tcp vigilant_williams [root@192 soft]# 3.4.8.导入和导出容器#导入和导出容器 export 导出容器的内容留作为一个tar归档文件[对应import命令] docker export 容器ID > 文件名.tar import 从tar包中的内容创建一个新的文件系统再导入为镜像[对应export] cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号 cat ubuntu-001.tar | docker import - user/ubuntu:001[root@192 soft]# docker rm -f 38933ab36249 38933ab36249 [root@192 soft]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e58709da98ef redis "docker-entrypoint.s…" 39 minutes ago Up 39 minutes 6379/tcp vigilant_williams [root@192 soft]# [root@192 soft]# cat ubuntu-001.tar | docker import - user/ubuntu:001 sha256:d7ff238c9005c659f4c5819554181bf5c5e56e15c2ad36db66af1acb347423fe [root@192 soft]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE user/ubuntu 001 d7ff238c9005 15 seconds ago 72.8MB redis latest 7614ae9453d1 2 years ago 113MB ubuntu latest ba6acccedd29 2 years ago 72.8MB redis 6.0.8 16ecd2772934 3 years ago 104MB [root@192 soft]# docker run -it d7ff238c9005 /bin/bash root@493bd15c2a4c:/# cd /tmp root@493bd15c2a4c:/tmp# ll total 0 drwxrwxrwt. 2 root root 23 Jan 7 10:11 ./ drwxr-xr-x. 1 root root 18 Jan 7 10:26 ../ -rw-r--r--. 1 root root 0 Jan 7 10:11 a2024.txt root@493bd15c2a4c:/tmp# [root@192 soft]# 3.5.常用命令小结attach Attach to a running container #当前shell 下 attach 连接指定运行镜像 build Build an image from a Dockerfile #通过Dockerfile定制镜像 commit Create a new image from a container changes #提交当前容器为新的镜像 Copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中 create Create a new container #创建一个新的容器,同run,但不启动容器 diff Inspect changes on a container's filesystem #查看docker容器变化 events Get real time events from the server #从docker服务获取容器实时事件 exec Run a command in an existing container #在已存在的容器上运行命令 export Stream the contents of a container as a tar archive #导出容器的内容流作为一个tar归档文件[对应import] history Show the history of an image #展示一个镜像形成历史 images List images #列出系统当前镜像 import Create a new filesystem image from the contents of a tarball #从tar包中的内容创建一个新的文件系统映像[对应expor] info Display system-wide information #显示系统相关信息 inspect Return low-level information on a container #查看容器详细信息 kill Kill a running container # kill指定docker容器 load Load an image from a tar archive #从一个tar包中加载一个镜像[对应save] login Register or Login to the docker registry server #注册或者登陆一个docker源服务器logout Log out from a Docker registry server #从当前Docker registry退出 logs Fetch the logs of a container #输出当前容器日志信息 port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT #查看映射端口对应的容器内部源端口 pause Pause all processes within a container #暂停容器 ps List containers#列出容器列表 pull Pull an image or a repository from the docker registry server #从docker镜像源服务器拉取指定镜像或者库镜像 push Push an image or a repository to the docker registry server #推送指定镜像或者库镜像至docker源服务器 restart Restart a running container #重启运行的容器 rm Remove one or more containers #移除一个或者多个容器 rmi Remove one or more images #移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或-f强制删除] run Run a command in a new container #创建一个新的容器并运行一个命令 save Save an image to a tar archive #保存一个镜像为一个tar包[对应load] search Search for an image on the Docker Hub #在docker hub中搜索镜像 start Start a stopped containers #启动容器 stop Stop a running containers #停止容器 tag Tag an image into a repository #给源中镜像打标签 top Lookup the running processes of a container #查看容器中运行的进程信息 unpause Unpause a paused container #取消暂停容器 version Show the docker version information #查看docker版本号 wait Block until a container stops, then print its exit code #截取容器停止时的退出状态值四、Docker镜像镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。4.1.分层的镜像以我们的pu为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载>4.2.UnionFS联合文件系统UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录4.3.Docker镜像加载原理docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。bootfs(boot fle system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是引导文件系统bootfs。这一层与我们典型的LinuxUnix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。rootfs (root fle system),在bootfs之上。包含的就是典型Linux系统中的/dev, /proc, bin, letc等标准目录和文件。roots就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M? 对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别,因此不同的发行版可以公用bootfs。4.4.为什么Docker镜像采用这种分层结构呢?镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。比如说有多个镜像都从相同的 base镜像构建而来,那么Docker Host只需在磁盘上保存一份base镜像;同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。4.5.重点理解Docker镜像层都是只读的,容器层是可写的当容器启动时一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层"之下的都叫“镜像层”。当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。4.6.docker镜像commit操作案例--演示ubuntu安装vim4.6.1.提交镜像docker commit 提交容器副本使之成为一个新的镜像 docker commit -m="提交的描述信息" -a="作者" 容器ID要创建的目标镜像名:[标签名]4.6.2.从Hub上下载ubuntu镜像到本地并成功运行docker pull ubuntu4.6.3.原始的默认ubuntu镜像是不带着vim命令的[root@192 soft]# docker run -it ubuntu /bin/bash root@7878b5ae864f:/# root@7878b5ae864f:/# ls bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var root@7878b5ae864f:/# vim a.txt bash: vim: command not found4.6.4.外网连通的情况下,安装vim#先更新我们的包管理工具 apt-get update # 然后安装我们需要的vim apt-get install vimroot@7878b5ae864f:/# cd /tmp root@7878b5ae864f:/tmp# vim a.txt root@7878b5ae864f:/tmp# cat a.txt this is a docker4.6.5.安装完成后,commit我们自己的新镜像docker commit -m="vim cmd add ok" -a="lb" 139727b83d29 itcast/myubuntu:1.1-a: 指定镜像作者-m: 自定义的提交描述信息-139727b83d29: 容器名字,这里也可以用容器ID代替-itcast/myubuntu:1.1: 指定要创建目标镜像的自定义名字(这里为itcast/myubuntu)和自定义版本(1.1)[root@192 soft]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 139727b83d29 ubuntu "/bin/bash" 3 minutes ago Up 3 minutes flamboyant_hellman [root@192 soft]# docker commit -m="vim cmd add ok" -a="ldy" 139727b83d29 itcast/myubuntu:1.1 sha256:1fd9ce6dfd6992d8c7033dccb9d2898e4dc2b99f1babf631db620474e11e2336 [root@192 soft]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE itcast/myubuntu 1.1 1fd9ce6dfd69 58 seconds ago 189MB ubuntu latest ba6acccedd29 2 years ago 72.8MB4.6.6.启动我们的新镜像并和原来的对比原来72.8MB 现在189MB4.7.总结Docker中的镜像分层,支持通过扩展现有镜像,创建新的镜像。类似Java继承于一个Base基础类,自己再按需扩展。新镜像是从base镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。五、本地镜像发布到阿里云5.1.本地镜像发布到阿里云流程5.2.镜像的生成方法基于当前容器创建一个新的镜像,新功能增强 docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]]commit我们自己的新镜像docker commit -m="vim cmd add ok" -a="lb" 139727b83d29 -a: 提交的镜像作者-m: 提交的说明文字5.3.将本地镜像推送到阿里云阿里云开发者平台:https://promotion.aliyun.com/ntms/act/kubernetes.html创建仓库镜像:选择控制台,进入容器镜像服务;选择个人实例;命名空间;仓库名称;进入管理界面获得脚本5.4.将阿里云的镜像下载本地六、CentOS7安装DockerCompose6.1.下载Linux下需要通过命令下载:# 安装 curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose如果下载速度较慢,或者下载失败,可以使用课前资料提供的docker-compose文件:上传到/usr/local/bin/目录也可以。6.2.修改文件权限修改文件权限:# 修改权限 chmod +x /usr/local/bin/docker-compose6.3.Base自动补全命令:# 补全命令 curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose如果这里出现错误,需要修改自己的hosts文件:echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts七、本地镜像发布到私有库--Docker Registry搭建镜像仓库可以基于Docker官方提供的DockerRegistry来实现。官网地址:https://hub.docker.com/_/registry7.1.下载镜像--创建registry容器并开放端口docker pull registry运行私有库Registry,相当于本地有个私有Docker hubDocker官方的Docker Registry是一个基础版本的Docker镜像仓库,具备仓库管理的完整功能,但是没有图形化界面。搭建方式比较简单,命令如下:docker run -d \ --restart=always \ --name registry \ -p 5000:5000 \ -v registry-data:/var/lib/registry \ --privileged=true \ registry # -p指定端口,一内一外 # -v表示挂载,前者是宿主机,后者是容器 # Docker挂载主机目录访问如果出现cannot open directory .: Permission denied解决办法:在挂载目录后多加一个--privileged=true参数即可如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用--prvileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。命令中挂载了一个数据卷registry-data到容器内的/var/lib/registry 目录,这是私有镜像库存放数据的目录。访问http://YourIp:5000/v2/_catalog 可以查看当前私有镜像服务中包含的镜像7.2.案例演示创建一个新镜像,ubuntu安装ifconfig命令[root@192 soft]# docker run -it ubuntu /bin/bash root@e65d61ff09d8:/# ifconfig root@e65d61ff09d8:/# apt-get -y install net-tools root@e65d61ff09d8:/# ifconfig[root@192 soft]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e65d61ff09d8 ubuntu "/bin/bash" 3 minutes ago Up 3 minutes objective_leakey daafa6a212e1 registry "/entrypoint.sh /etc…" 7 minutes ago Up 7 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp registry 98d2c389f54a 1fd9ce6dfd69 "/bin/bash" 26 minutes ago Up 26 minutes objective_meninsky [root@192 soft]# [root@192 soft]# docker commit -m="ifconfig cmd add" -a="ldy" e65d61ff09d8 ubuntu:1.2 sha256:811d655579989129269df684b6f4f1fcda542f69988de2005e19a9b610bfd050 [root@192 soft]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 1.2 811d65557998 5 seconds ago 122MB registry.cn-hangzhou.aliyuncs.com/dockerk8speed/myubuntu1.1 1.1 1fd9ce6dfd69 2 hours ago 189MB ubuntu latest ba6acccedd29 2 years ago 72.8MB 7.3.curl验证私服库上有什么镜像指令格式如下所示:curl -XGET http://主机映射的网络地址:主机映射网络端口/v2/_catalog防踩坑:如果记得自己映射的主机Registy网络地址就可以直接输入;如果不记得,可以使用docker ps -a查看私服库Registry的网络映射信息(映射网络地址和映射端口)。[root@192 soft]# curl -XGET http://192.168.229.129:5000/v2/_catalog {"repositories":[]} [root@192 registry-ui]# curl -XGET http://192.168.229.129:8080/v2/_catalog {"repositories":["nginx"]}可以看到,目前私服库http://192.168.229.129:5000/v2/_catalog没有任何镜像上传过。。。。。。。【空的】如下图所示,我的本地私有库Registry的网络地址为0.0.0.0,映射端口为5000。7.4.将新镜像ubuntu;修改符合私服规范的Tag推送镜像到私有镜像服务必须先tag,步骤如下: 重新tag本地镜像,名称前缀为私有仓库的地址:192.168.229.129:5000 docker tag nginx:latest 192.168.229.129:5000/nginx:1.0 使用命令docker tag 将 tag nginx:latest 这个镜像修改为 192.168.229.129:5000/nginx:1.0 #自己host主机ip地址 按照公式:docker tag 镜像ID或镜像名:Tag Host:Port/Repository:Tag上面代码的参数含义如下所示:(1)镜像ID或镜像名:要上传到私有库Registry的镜像ID或名字;(2)Tag:要上传的镜像版本号;(3)Host:本地私有库的映射网址(本文为0.0.0.0);(4)Post:本地私有库的映射端口(本文为5000);(5)Repository:Tag:上传到私有库Registry后自定义的镜像名字、版本号。[root@192 soft]# docker tag ubuntu:1.2 192.168.229.129:5000/ubuntu:1.2 [root@192 soft]# [root@192 soft]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.229.129:5000/ubuntu 1.2 811d65557998 7 minutes ago 122MB ubuntu 1.2 811d65557998 7 minutes ago 122MB registry.cn-hangzhou.aliyuncs.com/dockerk8speed/myubuntu1.1 1.1 1fd9ce6dfd69 2 hours ago 189MB ubuntu latest ba6acccedd29 2 years ago 72.8MB [root@192 soft]# 7.5.修改配置文件使之支持http-配置Docker信任地址安装的docker只支持阿里云镜像加速网址的http连接,为了实现镜像上传到私有库Registry,我们还要配置支持本地安装私有库Registry的http连接我们的私服采用的是http协议,默认不被Docker信任,所以需要做一个配置:# 打开要修改的文件 vi /etc/docker/daemon.json # registry-mirrors配置的是国内阿里提供的镜像加速地址,不用加速的话访问官网的会很慢。 # vim命令添加内容:http://192.168.229.129:8080为自己设置的私服库地址 "insecure-registries":["http://192.168.229.129:8080"] #上述理由: docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。====>修改完后如果不生效.建议重启docker # 重新加载 systemctl daemon-reload # 重启docker systemctl restart docker7.6.带有图形化界面版本--更改私有库使用DockerCompose部署带有图象界面的DockerRegistry,命令如下:version: '3.0' services: registry: image: registry volumes: - ./registry-data:/var/lib/registry ui: image: joxit/docker-registry-ui:static ports: - 8080:80 environment: - REGISTRY_TITLE=个人私有仓库 - REGISTRY_URL=http://registry:5000 depends_on: - registry[root@192 soft]# mkdir registry-ui [root@192 soft]# cd registry-ui/ [root@192 registry-ui]# ll 总用量 0 [root@192 registry-ui]# touch docker-compose.yml [root@192 registry-ui]# vim docker-compose.yml [root@192 registry-ui]# [root@192 registry-ui]# cat docker-compose.yml version: '3.0' services: registry: image: registry volumes: - ./registry-data:/var/lib/registry ui: image: joxit/docker-registry-ui:static ports: - 8080:80 environment: - REGISTRY_TITLE=个人私有仓库 - REGISTRY_URL=http://registry:5000 depends_on: - registry [root@192 registry-ui]# ll 总用量 4 -rw-r--r--. 1 root root 322 1月 8 07:27 docker-compose.yml [root@192 registry-ui]# docker-compose up -d Creating network "registry-ui_default" with the default driver Pulling ui (joxit/docker-registry-ui:static)... static: Pulling from joxit/docker-registry-ui 540db60ca938: Pull complete 197dc8475a23: Pull complete 39ea657007e5: Pull complete 37afbf7d4c3d: Pull complete 0c01f42c3df7: Pull complete d590d87c9181: Pull complete 3333c94ae44f: Pull complete 33d7cca6fc9f: Pull complete 076b2dd9bdd1: Pull complete b70198f04ee7: Pull complete 1fb6c5acc953: Pull complete Digest: sha256:b0657b6be748173583516e411bd71552e54cb7d5dda94964726297ce8774415c Status: Downloaded newer image for joxit/docker-registry-ui:static Creating registry-ui_registry_1 ... done Creating registry-ui_ui_1 ... done [root@192 registry-ui]# [root@192 registry-ui]# [root@192 registry-ui]# docker-compose logs -f Attaching to registry-ui_ui_1, registry-ui_registry_1 ui_1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration ui_1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ ui_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh ui_1 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf ui_1 | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version ui_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh ui_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh ui_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/90-docker-registry-ui.sh ui_1 | /docker-entrypoint.sh: Configuration complete; ready for start up registry_1 | time="2024-01-07T23:31:22.196329571Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.11.2 instance.id=513135ab-7e70-40dc-8e08-70a6164afe97 service=registry version=v2.7.1 registry_1 | time="2024-01-07T23:31:22.196463852Z" level=info msg="redis not configured" go.version=go1.11.2 instance.id=513135ab-7e70-40dc-8e08-70a6164afe97 service=registry version=v2.7.1 registry_1 | time="2024-01-07T23:31:22.200039301Z" level=info msg="Starting upload purge in 12m0s" go.version=go1.11.2 instance.id=513135ab-7e70-40dc-8e08-70a6164afe97 service=registry version=v2.7.1 registry_1 | time="2024-01-07T23:31:22.203727763Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.11.2 instance.id=513135ab-7e70-40dc-8e08-70a6164afe97 service=registry version=v2.7.1 registry_1 | time="2024-01-07T23:31:22.20447663Z" level=info msg="listening on [::]:5000" go.version=go1.11.2 instance.id=513135ab-7e70-40dc-8e08-70a6164afe97 service=registry version=v2.7.1 7.7.push推送到私服库命令格式为:docker push 符合私服规范的Tag的镜像名称或ID:版本号docker tag nginx:1.0 192.168.229.129:8080/nginx:1.0 docker push 192.168.229.129:8080/nginx:1.0 docker tag ubuntu:1.2 192.168.229.129:8080/ubuntu:1.2 docker push 192.168.229.129:8080/ubuntu:1.27.8.curl验证私服库上有什么镜像上传私服库完成,在终端输入命令curl -XGET http://192.168.229.129:8080/v2/_catalog查看私服库上是否有推送的镜像 [root@192 soft]# curl -XGET http://192.168.229.129:8080/v2/_catalog {"repositories":["nginx","ubuntu"]}7.9.pull到本地并运行使用docker pull命令从私有库拉取镜像到docker中:docker pull Registry的网络映射:Registry的端口映射/私有库中的镜像名字:版本号docker pull 192.168.229.129:8080/nginx:1.0 防踩坑:上面的curl指令只显示了私服库上的镜像名字,如为了获得版本号,需要如下指令,需要注意的ubuntu-advanced是要拉取的镜像名字:curl -XGET http://192.168.229.129:8080/v2/nginx/tags/list八、Docker容器数据卷将docker容器内的数据保存进宿主机的磁盘中8.1.运行一个带有容器卷存储功能的实例docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名将运用与运行的环境打包镜像,run后形成容器实例运行,但是我们对数据的要求希望是持久化的Docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了。为了能保存数据在docker中我们使用卷。特点:数据卷可在容器之间共享或重用数据卷中的更改可以直接实时生效,爽数据卷中的更改不会包含在镜像的更新中数据卷的生命周期一直持续到没有容器使用它为止8.2.宿主vs容器之间映射添加容器卷8.2.1.绑定映射目录#读写默认 docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名docker run \ -it --name myubt \ --privileged=true \ -v /tmp/myHostData:/tmp/myDockerData \ ubuntu /bin/bash8.2.2.查看数据卷是否挂载成功docker inspect 容器ID8.2.3.容器和宿主机之间数据共享1 docker修改,主机同步获得2 主机修改,docker同步获得3 docker容器stop,主机修改,docker容器重启看数据成功同步。8.3.容器数据卷读写规则映射添加说明# 可读可写 docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名# 容器实例内部被限制,只能读取不能写 docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名ro = read only此时如果宿主机写入内容,可以同步给容器内,容器可以读取到。8.4.卷的继承和共享8.4.1.容器1完成和宿主机的映射docker run -it --privileged=true -v /tmp/myHostData:/tmp/myDockerData --name u1 ubuntu /bin/bash8.4.2.容器2继承容器1的卷规则 docker run -it --privileged=true --volumes-from 父类 --name u2 ubuntu docker run -it --privileged=true --volumes-from u1 --name u2 ubuntu九、Docker常规安装简介9.1.总体步骤搜索镜像拉取镜像查看镜像启动镜像 - 服务端口映射停止容器移除容器9.2.安装Tomcat【新版本webapps已改为webapps.dist】https://hub.docker.com/9.2.1.docker hub上面查找tomcat镜像9.2.2.从docker hub上拉取tomcat镜像到本地9.2.3.docker images查看是否有拉取到的tomcat9.2.4.使用tomcat镜像创建容器实例(也叫运行镜像)docker run -it -p 8080:8080 tomcat -p :小写,主机端口:docker容器端口 -P :大写,随机分配端口 -i :交互 -t :终端 -d :后台9.2.5.访问猫首页可能没有映射端口或者没有关闭防火墙把webapps.dist目录转成webapps9.2.6.免修改版说明docker pull billygoo/tomcat8-jdk8 docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk89.3.安装mysql:5.79.3.1.简单版9.3.1.1.查询拉取mysql镜像docker search mysql # 不加版本号5.7,默认拉取的是最新版 docker pull mysql:5.7 docker images mysql:5.79.3.1.2.使用mysql镜像docker run -p 3306:3306 --name mq -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7 docker ps docker exec -it 容器ID /bin/bash mysql -u root -p9.3.1.3.建库建表插入数据9.3.1.4.外部win10连接运行在docker上的Mysql容器实例服务9.3.1.5.中文字符集问题show variables like 'character%';mysql> show variables like 'character%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 8 rows in set (0.01 sec) 9.3.2.实战版本9.3.2.1.新建mysql容器实例docker run \ --name mysql \ --privileged=true \ -e MYSQL_ROOT_PASSWORD=123456 \ -p 3306:3306 \ -v /app/mysql/log:/var/log/mysql \ -v /app/mysql/data:/var/lib/mysql \ -v /app/mysql/conf:/etc/mysql/conf.d \ -d \ mysql:5.7--name : 起名字 --privilege=true : 容器数据卷权限开启 -p : 端口映射 -d : 后台运行或者docker run \ --name mysql \ --privileged=true \ -e MYSQL_ROOT_PASSWORD=123456 \ -p 3306:3306 \ -v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \ -v /tmp/mysql/data:/var/lib/mysql \ -d \ mysql:5.7.25编写hmy.cnf[mysqld] skip-name-resolve character_set_server=utf8 datadir=/var/lib/mysql server-id=10009.3.2.2.新建my.cnf--通过容器卷同步给mysql容器实例[client] default_character_set=utf8 [mysqld] collation_server = utf8_general_ci character_set_server = utf89.3.2.3.重新启动mysql容器实例再重新进入并查看字符编码9.3.2.4.再新建库新建表再插入中文测试show databases; create database db01; use db01; create table t1(id int,name varchar(20)); insert into t1 values(1,'zs'),(2,'lisi'),(3,'王五'); select * from t1; show variables like 'character%'; drop database db01;9.4.安装redis9.4.1.下载redis镜像到本地标签为6.0.8docker search redis --limit 5 docker pull redis docker images redis9.4.2.入门命令9.4.3.命令提醒:容器卷记得加入 --privileged=true9.4.4.在Centos宿主机下新建目录/app/redismkdir -p /app/redis9.4.5.将一个redis.conf文件模板拷贝进/app/redis开启redis验证requirepass 123456允许redis外地连接,必须注释掉 #bind 127.0.0.1daemonize no 后台启动设置为no将daemonize yes注释起来或者daemonize no设置,因为该配置和docker run中-d参数冲突,会导致容器一直启动失败开启redis数据持久化appendonly yes可选9.4.6. /app/redis目录下修改redis.conf文件默认出厂的原始redis.conf9.4.7.使用redis6.0.8镜像创建容器(也叫运行镜像)docker run \ --name mr \ --privileged=true \ -p 6379:6379 \ -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 run \ --name mr \ # 给容器起个名称 --privileged=true \ # Docker会赋予容器几乎与主机相同的权限,即root --cluster-enabled yes \ # 是否开启集群 --appendonly yes \ # 开启AOF持久化功能 -p 6380:6379 \ #宿主机端口号:容器端口 端口映射 -v /app/redis/redis.conf:/etc/redis/redis.conf \ #宿主机目录:容器目录 redis配置文件挂载 -v /app/redis/data:/data \ #redis数据文件挂载 --net host \ # 指定网络类型为host,即与宿主机使用同一网络 -d redis:6.0.8 \ # 后台运行 redis-server /etc/redis/redis.conf \ #运行容器 并使用配置文件启动容器内的 redis-server # --requirepass 123456 设置密码 (如果你是通过docker 容器内部连接的话,就随意,可设可不设。但是如果想向外开放的话,一定要设置,不然容易中病毒)9.4.8.测试redis-cli连接上来9.4.9.请证明docker启动使用了我们自己指定的配置文件9.4.10.测试redis-cli连接上来第2次9.5.安装Nginx9.5.1.基础拉取、下载、运行docker search nginx --limit 5 docker pull nginx docker run --name mn -p 80:80 -d nginx # docker run 启动一个镜像 # -d 表示后台允许 # --name mn 表示为当前容器起一个别名 # -p 80:80 表示将本机的80端口映射到nginx镜像的80端口9.5.2.进入Nginx容器当中进入Nginx容器当中 docker exec -it nginx /bin/bash 命令详解: # docker exec 在运行的容器中执行命令 # -i 以交互模式运行容器,通常与 -t 同时使用;例如-it # -t 为容器重新分配一个伪输入终端,通常与 -i 同时使用;例如-it # nginx 容器名 # /bin/bash 其实就是表示载入容器后运行bash(命令语言解释程序), 因为docker中必须要保持一个进程(运行的程序)的运行,要不然整个容器就会退出,所以说,bash就担任起了docker中运行的那个进程的角色! #而/bin/bash则是bash在linux下的位置9.5.3.创建并运行nginx容器的命令解读docker run --name containerName -p 80:80 -d nginx命令解读:docker run :创建并运行一个容器--name : 给容器起一个名字,比如叫做mn-p :将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口-d:后台运行容器nginx:镜像名称,例如nginx这里的-p参数,是将容器端口映射到宿主机端口。默认情况下,容器是隔离环境,我们直接访问宿主机的80端口,肯定访问不到容器中的nginx。现在,将容器的80与宿主机的80关联起来,当我们访问宿主机的80端口时,就会被映射到容器的80,这样就能访问到nginx了:9.5.4.nginx容器挂载配置文件启动nginx# 生成容器 docker run --name mn -p 80:80 -d nginx在/app/nginx目录下建立3个以下文件夹# 在/app/nginx目录下建立3个以下文件夹 mkdir -p /app/nginx/{log,conf,html}复制到宿主机# 将容器nginx.conf文件复制到宿主机 docker cp mn:/etc/nginx/nginx.conf /app/nginx/nginx.conf # 将容器conf.d文件夹下内容复制到宿主机 docker cp mn:/etc/nginx/conf.d /app/nginx/conf.d # 将容器中的html文件夹复制到宿主机 docker cp mn:/usr/share/nginx/html /app/nginx配置文件文件备份docker exec -it mn /bin/bash cd /etc/nginx #cp default.conf default.bak.conf cp nginx.conf nginx.bak.conf # 配置文件文件外部备份 #docker cp mn:/etc/nginx/default.conf /app/nginx/default.bak.conf docker cp mn:/etc/nginx/nginx.conf /app/nginx/nginx.bak.conf9.5.5.nginx容器挂载配置文件解读挂载配置文件,就是把装有docker宿主机上面的nginx.conf配置文件映射到启动的nginx容器里面,这需要你首先准备好nginx.conf配置文件,如果你应经准备好了,下一步是启动nginx。docker run --name nginx -p 8080:80 \ -v /app/nginx/nginx.conf:/etc/nginx/nginx.conf \ -v /app/nginx/log:/var/log/nginx \ -v /app/nginx/html:/usr/share/nginx/html \ -v /app/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf \ --restart=always \ -d \ nginx解释下上面的命令:-name 给你启动的容器起个名字,以后可以使用这个名字启动或者停止容器-p 映射端口,将docker宿主机的80端口和容器的80端口进行绑定-v 挂载文件用的第一个-v表示将你本地的nginx.conf覆盖你要起启动的容器的nginx.conf文件第二个表示将日志文件进行挂载,就是把nginx服务器的日志写到你docker宿主机的/home/docker-nginx/log/下面第三个-v 表示的和第一个-v意思一样的-d 表示启动的是哪个镜像endl高级篇@TOC一、Docker复杂安装详说1.1 Mysql主从复制--原理-【尚硅谷Mysql高级篇】1.2 Mysql主从复制--【一主一从】搭建步骤1.2.1新建--【主服务器】--容器实例--3307# 安装mysql,启动数据卷,使得将docker内的数据保留进宿主机的磁盘中,设置mysql密码为123456 docker run \ --name mysql-master \ --privileged=true \ -e MYSQL_ROOT_PASSWORD=123456 \ -p 3307:3306 \ -v /app/mysql-master/log:/var/log/mysql \ -v /app/mysql-master/data:/var/lib/mysql \ -v /app/mysql-master/conf:/etc/mysql \ -d \ mysql:5.71.2.2.进入/app/mysql-master/conf目录下新建my.cnfcd /app/mysql-master/conf pwd vim my.cnf粘贴以下内容[client] default_character_set=utf8 [mysql] default-character-set=utf8 [mysqld] ## 设置server-id,同一局域网中需要唯一 server-id=101 ## binlog-do-db=数据库名 //同步的数据库名称,如果不配置,表示同步所有的库 ## 指定不需要同步的数据库名称,忽略mysql库 binlog-ignore-db=mysql ## 开启二进制日志功能 log-bin=mall-mysql-bin ## 设置二进制日志使用内存大小(事务) binlog_cache_size=1M ## 设置使用的二进制日志格式(binlog格式:mixed,statement,row) ## ROW(行模式,记录所有变动的行,存入binlog,缺点:当遇到批量修改的sql时,容易导致日志sql过多) ## STATEMENT(记录每条修改的SQL,存入binlog,缺点:当遇到now()这些函数时,会导致主从出现数据误差) ## MIXED(实现ROW和STATMENT切换,缺点:无法识别@@的系统变量,比如@@hostname) binlog_format=mixed ## 二进制日志过期清理时间。默认值为0,表示不自动清理。 expire_logs_days=7 ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。 ## 如:1026错误是指一些主键重复,1032错误是因为主从数据库数据不一致 slave_skip_errors=1062 collation_server=utf8_general_ci character_set_server=utf81.2.3.修改完配置后重启master实例docker restart mysql-master1.2.4.进入mysql-master容器# 进入master容器 & 进入数据库 docker exec -it mysql-master /bin/bash mysql -uroot -p1234561.2.5.master容器实例内创建数据同步用户# 在主库中添加账号slave,密码为123456并赋予权限 create user 'slave'@'%' identified by '123456'; # 授予权限 grant replication slave,replication client on *.* to 'slave'@'%';1.2.6.新建---【从服务器】---容器实例--3308docker run \ --name mysql-slave \ --privileged=true \ -e MYSQL_ROOT_PASSWORD=123456 \ -p 3308:3306 \ -v /app/mysql-slave/log:/var/log/mysql \ -v /app/mysql-slave/data:/var/lib/mysql \ -v /app/mysql-slave/conf:/etc/mysql \ -d \ mysql:5.71.2.7.进入/app/mysql-slave/conf目录下新建my.cnfcd /app/mysql-slave/conf pwd vim my.cnf粘贴以下内容[client] default_character_set=utf8 [mysql] default-character-set=utf8 [mysqld] ## 设置server-id,同一局域网中需要唯一 server-id=102 ## binlog-do-db=数据库名 //同步的数据库名称,如果不配置,表示同步所有的库 ## 指定不需要同步的数据库名称,忽略mysql库 binlog-ignore-db=mysql ## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用 log-bin=mall-mysql-slave1-bin ## 设置二进制日志使用内存大小(事务) binlog_cache_size=1M ## 设置使用的二进制日志格式(binlog格式:mixed,statement,row) ## ROW(行模式,记录所有变动的行,存入binlog,缺点:当遇到批量修改的sql时,容易导致日志sql过多) ## STATEMENT(记录每条修改的SQL,存入binlog,缺点:当遇到now()这些函数时,会导致主从出现数据误差) ## MIXED(实现ROW和STATMENT切换,缺点:无法识别@@的系统变量,比如@@hostname) binlog_format=mixed ## 二进制日志过期清理时间。默认值为0,表示不自动清理。 expire_logs_days=7 ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。 ## 如:1026错误是指一些主键重复,1032错误是因为主从数据库数据不一致 slave_skip_errors=1062 ## relay_log配置中继日志 relay_log=mall-mysql-relay-bin ## log_slave_updates表示slave将复制事件写进自己的二进制文件 log_slave_updates=1 ## 这个配置项可以设置从库的只读模式,将其值设置为 1 表示只读,设置为 0 表示读写。 ## slave设置为只读(具有super权限的用户除外) read_only=1 collation_server=utf8_general_ci character_set_server=utf81.2.8.修改完配置后重启slave实例docker restart mysql-slave1.2.9.在主【数据库中】查看主从同步状态show master status;1.2.10.进入mysql-slave容器docker exec -it mysql-slave /bin/bash mysql -uroot -p1234561.2.11.在【从数据库】中配置主从复制记住File和Position,后面需要用到。此时一定不要操作Master库,否则将会引起Master状态的变化,File和Position字段也将会进行变化。查看主机ip(mysql-master)docker inspect mysql-master# 设置从库读取主库的服务器配置,分别为:主机IP、账号、密码、MASTER_LOG_FILE是上面查询的File,MASTER_LOG_POS是上面查询的Position change master to master_host='宿主机ip', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.00001', master_log_pos=617, master_connect_retry=30;主从复制命令参数说明: master_host : 主数据库的IP地址; master_port : 主数据库的运行端口; master_user : 在主数据库创建的用于同步数据的用户账号; master_password : 在主数据库创建的用于同步数据的用户密码; master_log_file : 指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数; master_log_pos : 指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数; master_connect_retry : 连接失败重试的时间间隔,单位为秒。change master to master_host='192.168.229.133', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;使用start slave 开启主从复制过程后,如果 SlavelORunning一直是Connecting,则说明主从复制一直处于连接状态,这种情况一般是下面几种原因造成的,我们可以根据Last_IO_Error提示予以排除。1、网络不通: 检查ip、端口2、密码不对 : 检查是否创建用于同步的用户和用户密码是否正确3、pos不对 : 检查Master的Position正常启动后如下:1.2.12.在mysql主从复制的时候,使用change to改变主从信息的时候,却发现change不了mysql创建从节点出现如下报错提示ERROR 3021 (HY000): This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first. ERROR 3021 (HY000):此操作不能在运行的从io线程中执行;运行停止slave 原因很简单,我们需要,先stop slave;先把slave stop掉 然后再使用change就可以了。 change完之后,记得start slave; 开启slave因为之前已经创建过主节点,需停掉之前的配置 再重新配置 # 停止主从复制 stop slave; # 重置主机配置 reset master; # 再次配置主从即可,查看从节点状态 show slave status\G;1.2.13.在【从数据库】中查看主从同步状态#查看主从同步状态[Slave_IO_Running列 和 Slave_SQL_Running列 是否开启主从同步] show slave status \G;Slave_lO_Running和Slave_SQL_Running是查看主从是否运行的关键字段,默认为NO,表示没有进行主从复制。1.2.14.在【从数据库】中开启主从同步# 开启主从复制 start slave;1.2.15.【查看从数据库】状态发现已经同步show slave status \G;1.2.16.主从复制测试1.2.16.1.主机新建库--使用库--新建表--插入数据1.2.16.2.从机使用表--查看记录1.2.17. 遇见的异常配置好my.conf启动成功后登录时异常:[ERROR] unknown variable 'server-id=1' 将新增的所有主从配置往上移就解决了执行重启命令systemctl restart mysqld;时异常:Failed to restart mysqld.service: Unit not found MySQL在安装时没有创建名为mysqld的服务,cd /etc/init.d查看mysql映射的服务名。 我这里是mysql,所以修改重启命令为:systemctl restart mysql在从库设置主库配置时异常:ERROR 3021 (HY000): This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first. 这是因为从库已经启动了主从复制,先执行STOP SLAVE;停止主从复制,再执行配置即可MySQL8.0在从库设置主库配置时异常:Last_IO_Error: error connecting to master 'slave@111.11.11.111:3306' - retry-time: 60 retries: 18 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection. 修改主库slave账号的密码加密方式:alter user 'slave'@'%' identified with mysql_native_password by '123456';二、安装Redis集群(大厂面试第4季--分布式存储案例真题)cluster(集群)模式-docker版哈希槽分区进行亿级数据存储2.1 面试题---【1~2亿条数据需要缓存,请问如何设计这个存储案例】1~2亿条数据需要缓存,请问如何设计这个存储案例单机单台100%不可能,肯定是分布式存储,用redis如何落地?2.2 哈希取余分区哈希取余分区: 节点映射、数据变动、容易出错2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式 : hash(key)%N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。 优点:简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。缺点:原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key)/? 。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。2.3 一致性哈希算法分区 一致性哈希算法分区一致性Hash算法背景一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不OK了。提出一致性Hash解决方案。目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系。算法构建一致性哈希环 一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集, 这个集合可以成为一个hash空间[0.,2^32-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(O=2^32), 这样让它逻辑上形成了一个环形空间。 它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数量进行取模。而一致性Hash算法是对2^32取模,简单来说 ,`一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环`,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形), 整个哈希环如下图:整个空间`按顺时针方向组织`,圆环的正上方的点代表0,O点右侧的第一个点代表1,以此类推,2、3、4、……直到2^32-1, 也就是说0点左侧的第一个点代表2^32-1,0和2^32-1在零点中方向重合,我们把这个由2^32个点组成的圆环称为Hash环。服务器IP节点映射将集群中各个IP节点映射到环上的某一个位置。 将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。 假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:key落到服务器的落键规则当我们需要存储一个kv键值对时,首先计算key的hash值, hash(key)将这个key使用相同的函数Hash计算出哈希值并确定此数据在 环上的位置,`从此位置沿环顺时针“行走”`,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。 如我们有Qbject A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一致性Hash算法 ,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。一致性哈希算法的容错性假设Node C宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。 一般的,在一致性Hash算法中,如果一台服务器不可用,则`受影响的数据仅仅是此服务器到其环空间中前一台服务器 (即沿着逆时针方向行走遇到的第一台服务器)之间数据`,其它不会受到影响。 简单说,就是C挂了,受到影响的只是B、C之间的数据,并且这些数据会转移到D进行存储。 一致性哈希算法的扩展性数据量增加了,需要增加一台节点Node X,X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可, 不会导致hash取余全部数据重新洗牌。一致性哈希算法的数据倾斜问题`Hash环的数据倾斜问题` 一致性Hash算法在服务`节点太少`时,容易因为节点分布不均匀而造成`数据倾斜`(被缓存的对象大部分集中缓存在某一台服务器上)问题, 例如系统中只有两台服务器:为了在节点数目发生改变时尽可能少的迁移数据 将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会`顺时针`找到临近的存储节点存放。 而当有节点加入或退出时仅影响该节点在Hash环上`顺时针相邻的后续节点。` `优点` 加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。 `缺点` 数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。2.4 哈希槽分区为了解决一致性哈希算法的`数据倾斜问题`,哈希槽实质就是一个数组,数组[0,2^14-1]形成hash slot空间。`能干什么` 解决均匀分配的问题,`在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,` 现在就相当于节点上放的是槽,槽里放的是数据。槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。 哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。 `多少个hash槽` 一个集群只能有16384个槽,编号0-16383(0-2^14-1)。`这些槽会分配给集群中的所有主节点`,分配策略没有要求。可以指定哪些编号的槽分配给 哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对 应的槽里。slot =CRC16(key)% 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。2.5 哈希槽计算三、3主3从redis集群扩缩容配置案例架构说明3.1 架构图3.2 关闭防火墙+启动docker后台服务systemctl start docker systemctl start docker3.3 redis集群配置【3主3从】3.3.1.docker运行redis--命令参数--分步解释命令说明 docker run \ # 创建并运行docker 容器实例 --name mr \ # 给容器起个名称 --privileged=true \ # Docker会赋予容器几乎与主机相同的权限,即获取宿主机root用户权限 --appendonly yes \ # 开启AOF持久化功能 -v /app/redis/redis.conf:/etc/redis/redis.conf \ #容器卷,宿主机地址:docker容器内部地址 redis配置文件挂载 -v /app/redis/data:/data \ #redis数据文件挂载 --net host \ # 使用宿主机的ip和端口,指定网络类型为host,即与宿主机使用同一网络,默认 -d redis:6.0.8 \ # 后台运行 redis镜像和版本号 redis-server /etc/redis/redis.conf \ #运行容器 并使用配置文件启动容器内的 redis-server --cluster-enabled yes \ # 是否开启redis集群 --port 6386 \ # redis端口号 # -p 6380:6379 \ #宿主机端口号:容器端口 端口映射 # --requirepass 123456 设置密码 (如果你是通过docker 容器内部连接的话,就随意,可设可不设。但是如果想向外开放的话,一定要设置,不然容易中病毒)3.3.2.新建6个docker容器实例docker run -d --name redis-node-1 --net host --privileged=true -v /app/share/redis-node-1:/data redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --port 6381 docker run -d --name redis-node-2 --net host --privileged=true -v /app/share/redis-node-2:/data redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --port 6382 docker run -d --name redis-node-3 --net host --privileged=true -v /app/share/redis-node-3:/data redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --port 6383 docker run -d --name redis-node-4 --net host --privileged=true -v /app/share/redis-node-4:/data redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --port 6384 docker run -d --name redis-node-5 --net host --privileged=true -v /app/share/redis-node-5:/data redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --port 6385 docker run -d --name redis-node-6 --net host --privileged=true -v /app/share/redis-node-6:/data redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --port 63863.3.3.进入容器redis-node-1并为6台机器构建集群关系docker exec -it redis-node-1 /bin/bash ifconfig注意,进入docker容器后才能执行一下命令,且注意自己的真实IP地址redis-cli \ --cluster create \ 192.168.229.133:6381 \ 192.168.229.133:6382 \ 192.168.229.133:6383 \ 192.168.229.133:6384 \ 192.168.229.133:6385 \ 192.168.229.133:6386 \ --cluster-replicas 1 # -a 000415 验证密码--cluster create: 构建集群--cluster-replicas 1 :表示为每个master创建一个slave节点-a 000415:表示设置的密码3.3.4.链接进入6381作为切入点,查看集群状态# 查看集群信息 cluster info # 本集群有哪些节点 cluster nodes本次实际主从节点对应情况主服务器Master从服务器Slave6381638463826385638363863.4 主从容错切换迁移案例3.4.1.数据读写存储# 启动1机构成的集群并通过exec进入 docker exec -it redis-node-1 /bin/bash # 对6381新增两个key redis-cli -p 6381 # 防止路由失效加参数-c并新增两个key redis-cli -p 6381 -c # 查看集群信息 redis-cli --cluster check 192.168.229.133:63813.4.1.1.启动1机构成的集群并通过exec进入3.4.1.2.防止路由失效加参数-c,并新增两个key3.4.1.3.查看集群状态3.4.2.容错切换迁移3.4.2.1. 主6381和从机切换,先停止主机6381docker stop redis-node-13.4.2.2. 再次查看集群信息3.4.2.3. 先还原之前的3主3从# 先开启6381 docker restart redis-node-1 # 在停止6384 docker stop redis-node-4 # 再开启6384 docker restart redis-node-4 # 主从机器分配情况以实际情况为准3.4.2.5. 查看集群状态【redis-cli --cluster check 自己ip:6381】redis-cli --cluster check 自己ip:6381redis-cli --cluster check 192.168.229.133:63813.4.2.6.虚拟机自动关机,重启恢复原样3.5 主从扩容案例3.5.1.分析图3.5.2.实操步骤新建6387、6388两个节点+新建后启动+查看是否8节点 进入6387容器实例内部--docker exec -it redis-node-7 /bin/bash 将新增的6387节点(空槽号)作为master节点加入原集群 检查集群情况第1次 重新分派槽号 检查集群情况第2次 为主节点6387分配从节点6388 检查集群情况第3次3.5.3.新建6387、6388两个节点+新建后启动+查看是否8节点docker run -d --name redis-node-7 --net host --privileged=true -v /app/share/redis-node-7:/data redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --port 6387 docker run -d --name redis-node-8 --net host --privileged=true -v /app/share/redis-node-8:/data redis:6.0.8 redis-server --cluster-enabled yes --appendonly yes --port 63883.5.4.进入6387容器实例内部--docker exec -it redis-node-7 /bin/bashdocker exec -it redis-node-7 /bin/bash3.5.5.将新增的6387节点【空槽号】作为master节点加入原集群将新增的6387作为master节点加入集群 redis-cli --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381 redis-cli --cluster add-node 192.168.229.133:6387 192.168.229.133:6381 6387就是将要作为master新增节点 6381就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群3.5.6.检查集群情况第1次3.5.7.重新分派槽号--命令【redis-cli --cluster reshard IP地址:端口号】# 重新分派槽号 redis-cli --cluster reshard 192.168.229.133:63813.5.8.检查集群情况第2次--【槽号分派说明】redis-cli --cluster check 192.168.229.133:6381槽号分派说明:为什么6387是3个新的区间,以前的还是连续?重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点63873.5.9.为主节点6387分配从节点6388命令:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID265b4d87bf36015ff8e491a2994753c590ee3d85 -------这个是6387的编号,按照自己实际情况 redis-cli --cluster add-node 192.168.229.133:6388 192.168.229.133:6387 \ --cluster-slave --cluster-master-id 265b4d87bf36015ff8e491a2994753c590ee3d853.5.10.检查集群情况第3次redis-cli --cluster check 192.168.229.133:63873.6 主从缩容案例3.6.1 分析图3.6.2 实操步骤# 目的:6387和6388下线 # 检查集群情况1获得6388的节点ID redis-cli --cluster check 192.168.229.133:6382 ad001acdd52a4484c63c8c6c8d3c9f0de173cd4b # 将6388删除--从集群中将4号从节点6388删除 redis-cli --cluster del-node 192.168.229.133:6388 ad001acdd52a4484c63c8c6c8d3c9f0de173cd4b redis-cli --cluster check 192.168.229.133:6382 # 将6387的槽号清空,重新分配,本例将清出来的槽号都给6381 redis-cli --cluster reshard 192.168.229.133:6381 4096 1ce24a697196e2f225204fa664d65d7800b07d06 ---6381槽号ID 265b4d87bf36015ff8e491a2994753c590ee3d85 ---6387槽号ID done # 检查集群情况第二次 redis-cli --cluster check 192.168.229.133:6381 4096个槽位都给了6381,它变成了8192个槽位,相当于全部都给6381;不然要输入3次,一锅端 # 将6387删除 redis-cli --cluster del-node ip:从机端口 6387节点ID redis-cli --cluster del-node 192.168.229.133:6387 265b4d87bf36015ff8e491a2994753c590ee3d85 # 检查集群情况第三次 redis-cli --cluster check 192.168.229.133:63813.6.3 检查集群情况1获得6388的节点IDredis-cli --cluster check 192.168.229.133:6382 ad001acdd52a4484c63c8c6c8d3c9f0de173cd4b3.6.4 将6388删除--从集群中将4号从节点6388删除命令:redis-cli --cluster del-node ip:从机端口 从机6388节点IDredis-cli --cluster del-node 192.168.229.133:6388 ad001acdd52a4484c63c8c6c8d3c9f0de173cd4b redis-cli --cluster check 192.168.229.133:63823.6.5 将6387的槽号清空,重新分配,本例将清出来的槽号都给6381redis-cli --cluster reshard 192.168.229.133:6381 4096 1ce24a697196e2f225204fa664d65d7800b07d06 ---6381槽号ID 265b4d87bf36015ff8e491a2994753c590ee3d85 ---6387槽号ID done3.6.6 检查集群情况第二次redis-cli --cluster check 192.168.229.133:6381 4096个槽位都给了6381,它变成了8192个槽位,相当于全部都给6381;不然要输入3次,一锅端3.6.7 将6387删除命令:redis-cli --cluster del-node ip:从机端口 6387节点IDredis-cli --cluster del-node ip:从机端口 6387节点ID redis-cli --cluster del-node 192.168.229.133:6387 265b4d87bf36015ff8e491a2994753c590ee3d853.6.8 检查集群情况第三次3.7 总结四、DockerFile解析4.1 DockerFile介绍dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。官网:https://docs.docker.com/engine/reference/builder/构建三步骤:编写Dockerfile文件 docker build 命令构建镜像 docker run 依镜像运行容器实例FROM scratch ADD centos-7-x86_64-docker.tar.xz / LABEL \ org.label-schema.schema-version="1.0" \ org.label-schema.name="CentOS Base Image" \ org.label-schema.vendor="CentOS" \ org.label-schema.license="GPLv2" \ org.label-schema.build-date="20201113" \ org.opencontainers.image.title="CentOS Base Image" \ org.opencontainers.image.vendor="CentOS" \ org.opencontainers.image.licenses="GPL-2.0-only" \ org.opencontainers.image.created="2020-11-13 00:00:00+00:00" CMD ["/bin/bash"]4.2 DockerFile构建过程解析4.2.1.镜像结构镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。我们以MySQL为例,来看看镜像的组成结构:简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件。4.2.2.DockerFile基础知识1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数 2:指令按照从上到下,顺序执行 3: #表示注释 4:每条指令都会创建一个新的镜像层并对镜像进行提交4.2.3.docker执行DockerFile的大致流程(1) docker从基础镜像运行一个容器 (2)执行一条指令并对容器作出修改 (3)执行类似docker commit的操作提交一个新的镜像层 (4) docker再基于刚提交的镜像运行一个新容器 (5)执行dockerfile中的下一条指令直到所有指令都执行完成4.2.4.小总结从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段:Dockerfile是软件的原材料Docker镜像是软件的交付品Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例 Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系 的基石。 1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。 Dockerile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;2 Docker镜像,在用Dockerfle定义一个文件之后,docker buid时会产生一个Docker镜像,当运行Docker镜像时会真正开始提供服务;3 Docker容器,容器是直接提供服务的。4.3 DockerFile常用保留字指令参考tomcat8的dockerfile入门:https://github.com/docker-library/tomcatDockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。4.3.1 FROM:定义基于哪个镜像构建新的镜像。Dockerfile的第一条必须是FROM。指定一个已经存在的基础镜像作为模板,表示新镜像是基于哪个镜像构建的例如:FROM centos4.3.2 MAINTAINER:为镜像添加作者信息:姓名和邮箱地址指定新镜像的创建者名字和邮箱例如:MAINTAINER bulut<bulut123@163.com>4.3.3 RUN:在容器构建时需要运行的命令。新镜像构建时在容器上运行的指令。RUN在docker build时运行。shell格式:RUN <命令行命令>RUN <命令行命令> 等同于,在终端操作的shell命令。例如:RUN yum -y install vimexec格式:RUN [“可执行文件”, “参数1”, “参数2”]例如:RUN ["./test.php", "param1", "param2"],等同于RUN ./test.php param1 param2 RUN ["./test.php", "dev", "offline"],等同于RUN ./test.php dev offline4.3.4 EXPOSE:当前容器对外暴露的端口EXPOSE 80804.3.5 WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点当容器运行时,通过docker exec -it 容器ID bash进入容器的工作目录4.3.6 USER: 指定该镜像以什么样的用户去执行,如果都不指定默认是root4.3.7 ENV:用来在构建镜像过程中设置环境变量ENV MY_PATH /app/test这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量,比如 : WORKDIR $MY_PATH例如定义了ENV MY_WORKDIR /app,则可以这样定义WORKDIR:WORKDIR $MY_WORKDIR例如定义了ENV JAVA_HOME /app/java,则通过新镜像启动的容器中,可以执行命令echo $JAVA_HOMEENV CATALINA_HOME /usr/local/tomcat ENV PATH $CATALINA_HOME/bin:$PATH RUN mkdir -p "$CATALINA_HOME" WORKDIR $CATALINA_HOME4.3.8 ADD:将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包ADD centos-6-docker.tar.xz / 4.3.9 COPY:类似ADD,拷贝文件和目录到镜像中类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置COPY src dest COPY ["src" "dest"] <src源路径>:源文件或者源目录 <dest目标路径>:容器内的指定路径,该路径不用事先建好,会自动创建4.3.10 VOLUME:容器数据卷,用于数据保存和持久化工作定义容器卷,和参数-v一样# 将mycat的配置文件的地址暴露出映射地址,启动时直接映射宿主机的文件夹VOLUME /usr/local/mycat4.3.11 CMD:设置容器默认要运行的命令及参数。指定通过新镜像启动容器时,需要执行的指令。CMD在docker run时运行。CMD指令的格式和RUN相似,语法有两种:shell格式 : CMD <命令>exec格式 : CMD [“可执行文件”, “参数1”, “参数2”, …]参数列表格式:CMD [ “参数1”, “参数2”, …]。在指定了ENTRYPOINT指令后,用CMD指定具体的参数。Dockerfile可以有多个CMD指令,但是只有最后一个有效。CMD会被docker run之后的参数替换。如果docker run后面指定了容器运行的命令,则CMD指令无效,CMD会被docker run之后的参数替换。EXPOSE 8080 CMD ["catalina.sh", "run"]CMD 在docker run时运行。RUN 在docker build时运行。4.3.12 ENTRYPOINT:指定通过新镜像启动容器时,需要执行的指令。ENTRYPOINT在docker run时运行ENTRYPOINT也是用来指定一个容器启动时要运行的命令类似于CMD指令,但是ENTRYPOINT不会被docker run后面的命令覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序命令格式: ENTRYPOINT ["<excuteable>","<param1>","<param2>",...]ENTRYPOINT可以和CMD一起用,一般是变参才会使用CMD,这里的CMD等于是在给ENTRYPOINT传参。当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变成 <ENTRYPOINT> "<CMD>"例如:通过如下Dockerfile构建nginx:test镜像FROM nginx ENTRYPOINT ["nginx", "-c"] # 定参 CMD ["/etc/nginx/nginx.conf"] # 变参效果如下是否传参按照dockerfile编写执行docker run传参运行Docker run命令docker run -nginx:testdocker run nginx:test - c /etc/nginx/new.conf衍生出来的实际命令nginx -c /etc/nginx/nginx.confnginx -c /etc/nginx/new.conf4.3.13 CMD与ENTRYPOINTCMD# dockerfile01 FROM centos CMD ["ls", "-a"] docker bulid -f dockerfile01 -t cmd:1.0 . docker run 镜像id # 会执行ls -a命令 # 如果执行docker run cmd:1.0 -l, 本来是想执行ls -al,但是 CMD命令会被-l所替代,由于没有-l命令,所以会报错ENTRYPOINT# dockerfile02 FROM centos ENTRYPOINT ["ls", "-a"] docker bulid -f dockerfile01 -t cmd:2.0 . docker run 镜像id # 会执行ls -a命令 # 如果执行docker run cmd:2.0 -l, 执行正常,命令为ls -al4.3.14 小总结BUILDBothRUNFROMWORKDIRCMDMAINTAINERUSERENVCOPY EXPOSEADD VOLUMERUN ENTRYPOINTONBUILD .dockerignore FROM: 表示基础镜像,就是我们的镜像从这里开始构建m MAINTAINER: 表示维护者信息,就是这个镜像是谁创建的,一般需要写姓名和邮箱 RUN:表示镜像构建时需要运行的命令 ADD: 表示为了构建镜像需要添加的压缩等文件,例如要构建tomcat镜像,那么肯定要将tomcat压缩包放进去 WORKDIR: 表示镜像的工作目录 VOLUME: 表示挂载数据卷的目录位置,如果没有设置,就需要在运行run命令时通过-v进行设置 EXPOSE: 表示要暴露的端口,如果没有设置,就需要在运行run命令时通过-p进行设置 CMD:指定容器启动时需要运行的命令,只有最后一个会生效,可以被替代 ENTRYPOINT: 指定容器启动时需要运行的命令,可以追加命令 ONBUILD:当创建一个被继承(--volumes-from)的dockerfile时,就会运行这个指令,属于触发指令 COPY:类似ADD,将文件拷贝到镜像中 ENV:构建的时候设置环境变量4.4 案例4.4.1 自定义镜像mycentosjava84.4.1.1 要求:Centos7镜像具备vim+ifconfig+jdk8docker search centos # 建议下载8版本以下的 # 从官方仓库拉取最新的 CentOS 7 镜像作为基础镜像 docker pull centos:7 docker images centos:7 docker run -it eeb6ee3f44bd /bin/bash4.4.1.2 下载JDK8下载地址:https://www.oracle.com/java/technologies/downloads/#java84.4.1.3 编写Dockerfile文件DockerfileFROM centos:7 MAINTAINER dy<dy@163.com> ENV MYPATH /usr/local WORKDIR $MYPATH RUN yum install -y yum-utils # 安装vim编辑器 RUN yum -y install vim # 安装ifconfig命令查看网络IP RUN yum -y install net-tools # 安装java8 及 lib 库 RUN yum -y install glibc.i686 RUN mkdir /usr/local/java # ADD 是相对路径jar,把jdk-8u391-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置 ADD jdk-8u391-linux-x64.tar.gz /usr/local/java # 配置java环境变量 ENV JAVA_HOME /usr/local/java/jdk1.8.0_391 ENV JRE_HOME $JAVA_HOME/jre ENV CLASSPATH $JAVA_HOME/lib/dt.tar:$JAVA_HOME/lib/tools.jar$JRE_HOME/lib:$CLASSPATH ENV PATH $JAVA_HOME/bin/:$PATH EXPOSE 80 CMD echo $PATH CMD echo "success--------------------ok" CMD /bin/bash参数说明:FROM centos:7:指定基础镜像为 CentOS,版本号为7MAINTAINER:指定镜像的维护者和联系方式。ENV MYPATH /usr/local:定义一个环境变量 MYPATH,并设置其值为 /usr/local。WORKDIR $MYPATH:将工作目录切换到 $MYPATH,即 /usr/local。RUN yum -y install vim:在容器内运行命令,安装 Vim 编辑器。RUN yum -y install net-tools:在容器内运行命令,安装 net-tools,包括常用的网络工具。EXPOSE 80:声明容器将监听的端口号为 80,但这并不会自动映射到主机端口。CMD echo $MYPATH:在容器启动时运行的命令,输出环境变量 $MYPATH 的值。CMD echo "success--------------------ok":在容器启动时运行的命令,输出固定的字符串 "success--------------------ok"。CMD /bin/bash:在容器启动时运行的命令,启动一个交互式的 Bash 终端。4.4.1.4 构建# -t:是target的缩写 docker build -t 新镜像名字:TAG . docker build -t mycentosjava8:1.1 . # 注意:TAG后面有个空格,有个点 # 最后的小数点:就表明是当前目录。 docker build -f /app/myfile/Dockerfile -t mycentosjava8:1.1 . -f:后面跟随的是Dockerfile 文件 -t :后面跟随的镜像名和版本号。4.4.1.5 运行run -it 39ad01e4fa5e /bin/bash run -it 39ad01e4fa5e /bin/bash4.4.1.6. 构建报错【centos8及8版本以上缺乏中文语言包和地址vault.centos.org需更改】4.4.1.6.1.Error: Failed to download metadata for repo ‘appstream‘: Cannot prepare internal mirrorlist在学习使用 docker 技术过程中,基于 centos 镜像自定义新的镜像,其中基础镜像 centos 需要提前安装好 vim 和 net-tools,然而在刚开始通过 yum -y install vim 安装 vim 时,便出现了错误提示信息:Error: Failed to download metadata for repo ‘appstream‘: Cannot prepare internal mirrorlist[root@192 myfile]# docker build -t centosjava8:1.1 . [+] Building 60.9s (7/11) docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 836B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/centos:latest 0.0s => [1/7] FROM docker.io/library/centos 0.0s => [internal] load build context 0.0s => => transferring context: 107B 0.0s => CACHED [2/7] WORKDIR /usr/local 0.0s => ERROR [3/7] RUN yum -y install vim 60.9s ------ > [3/7] RUN yum -y install vim: 60.78 CentOS Linux 8 - AppStream 0.0 B/s | 0 B 01:00 60.78 Errors during downloading metadata for repository 'appstream': 60.78 - Curl error (6): Couldn't resolve host name for http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=AppStream&infra=container [Could not resolve host: mirrorlist.centos.org] 60.79 Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: Curl error (6): Couldn't resolve host name for http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=AppStream&infra=container [Could not resolve host: mirrorlist.centos.org] ------ Dockerfile:8 -------------------- 6 | 7 | # 安装vim编辑器 8 | >>> RUN yum -y install vim 9 | # 安装ifconfig命令查看网络IP 10 | RUN yum -y install net-tools -------------------- ERROR: failed to solve: process "/bin/sh -c yum -y install vim" did not complete successfully: exit code: 1:one:上面的报错信息意思是,从仓库 ‘appstream’ 下载元数据失败:由于镜像列表中没有 URL,不能准备内部镜像列表。:two: 问题分析::three: 第一种可能的情况便是网络连接问题。检查是否可以连接外部网络,可以使用 ping baidu.com 查看是否有丢包情况。如果丢包,则进一步检查网络连接是否正常;如果没有丢包,继续阅读下文:four:那么第二种情况,便是 CentOS 已经停止维护的问题。2020 年 12 月 8 号,CentOS 官方宣布了停止维护 CentOS Linux 的计划,并推出了 CentOS Stream 项目,CentOS Linux 8 作为 RHEL 8 的复刻版本,生命周期缩短,于 2021 年 12 月 31 日停止更新并停止维护(EOL),更多的信息可以查看 CentOS 官方公告。如果需要更新 CentOS,需要将镜像从 mirror.centos.org 更改为 vault.centos.org:five:报错信息那么针对上面提到的第二种情况,给出的解决方法如下:首先,进入到 yum 的 repos 目录cd /etc/yum.repos.d/其次,修改 centos 镜像内容,需要将镜像从 mirror.centos.org 更改为 vault.centos.orgsed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*https://vault.centos.org/centos/8/AppStream/x86_64/os/repodata/然后,生成缓存更新(第一次更新,速度稍微有点慢,耐心等待 2min 左右)yum makecache4.4.1.6.2.CentOS 8 中执行命令,出现报错:Failed to set locale, defaulting to C.UTF-8报错原因:1、没有安装相应的语言包。2、没有设置正确的语言环境。RUN yum install glibc-langpack-zh解决方法1:安装语言包设置语言环境需使用命令 localelocale -a 命令,查看目前系统已安装的语言包安装中文语言包,命令yum install glibc-langpack-zh安装英文语言包,命令 dnf install glibc-langpack-en 或 dnf install langpacks-en glibc-all-langpacks -y解决方法2:设置正确的语言环境echo "export LC_ALL=en_US.UTF-8" >> /etc/profile source /etc/profile或使用命令locale -gen en_US.UTF-8yum -y install vim4.4.1.6.3.总结编写Dockerfile,centos8添加以下内容FROM centos:latest # 更改镜像,需要将镜像从 mirror.centos.org 更改为 vault.centos.org 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 -y install glibc-langpack-zhcentos8--Dockerfile完整版FROM centos:latest MAINTAINER dy<dy@163.com> ENV MYPATH /usr/local WORKDIR $MYPATH # 更改镜像,需要将镜像从 mirror.centos.org 更改为 vault.centos.org 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 -y install glibc-langpack-zh RUN yum install -y yum-utils # 安装vim编辑器 RUN yum -y install vim # 安装ifconfig命令查看网络IP RUN yum -y install net-tools # 安装java8 及 lib 库 RUN yum -y install glibc.i686 RUN mkdir /usr/local/java # ADD 是相对路径jar,把jdk-8u391-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置 ADD jdk-8u391-linux-x64.tar.gz /usr/local/java # 配置java环境变量 ENV JAVA_HOME /usr/local/java/jdk1.8.0_391 ENV JRE_HOME $JAVA_HOME/jre ENV CLASSPATH $JAVA_HOME/lib/dt.tar:$JAVA_HOME/lib/tools.jar$JRE_HOME/lib:$CLASSPATH ENV PATH $JAVA_HOME/bin/:$PATH EXPOSE 80 CMD echo $PATH CMD echo "success--------------------ok" CMD /bin/bash4.4.1.6.4.再次测试centos8以上版本镜像DockerfileFROM centos:latest MAINTAINER dy<dy@163.com> ENV MYPATH /usr/local WORKDIR $MYPATH # 更改镜像,需要将镜像从 mirror.centos.org 更改为 vault.centos.org 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 -y install glibc-langpack-zh RUN yum install -y yum-utils # 安装vim编辑器 RUN yum -y install vim # 安装ifconfig命令查看网络IP RUN yum -y install net-tools # 安装java8 及 lib 库 RUN yum -y install glibc.i686 EXPOSE 80 CMD echo "success--------------------ok" CMD /bin/bash docker pull centos:latest mkdir -p /app/myfile cd /app/myfile vi Dockerfile docker build -t centos8:1.1 .4.4.2 虚悬镜像:仓库名、标签都是的镜像,俗称dangling imageDockerfile# 测试用的 from ubuntu CMD echo 'action is success'docker build# 查看虚悬镜像 docker image ls -f dangling=true # 删除虚悬镜像 docker image prune4.4.3 自定义镜像myubuntu4.4.3.1 编写DockerfileDockerfileFROM ubuntu MAINTAINER dy<dy@163.com> ENV MYPATH /usr/local WORKDIR $MYPATH RUN apt-get update RUN apt-get install net-tools RUN apt-get install -y iproute2 RUN apt-get install -y inetutils-ping EXPOSE 80 CMD echo $MYPATH CMD echo "install inconfig cmd into ubuntu success--------ok" CMD /bin/bash4.4.3.2 构建新镜像docker build -t 新镜像名字:TAG .4.4.3.3 运行新镜像docker run -it 新镜像名字:TAG4.4.4.案例-自定义镜像-DockerfileDockerfile# 指定基础镜像 FROM ubuntu:16.04 # 配置环境变量,JDK的安装目录 ENV JAVA_DIR=/usr/local # 拷贝jdk和java项目的包 COPY ./jdk8.tar.gz $JAVA_DIR/ COPY ./docker-demo.jar /tmp/app.jar # 安装JDK RUN cd $JAVA_DIR \ && tar -xf ./jdk8.tar.gz \ && mv ./jdk1.8.0_144 ./java8 # 配置环境变量 ENV JAVA_HOME=$JAVA_DIR/java8 ENV PATH=$PATH:$JAVA_HOME/bin # 暴露端口 EXPOSE 8090 # 入口,java项目的启动命令 ENTRYPOINT java -jar /tmp/app.jar4.5 小总结五、Docker微服务实战5.1.在IDEA新建一个普通微服务模块5.1.1.建Moudle--spring-boot-docker-demo5.1.2.改POM<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.6</version> <relativePath/> </parent> <groupId>com.itcast</groupId> <artifactId>spring-boot-docker-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.complier.source>1.8</maven.complier.source> <maven.complier.target>1.8</maven.complier.target> <juint.version>4.12</juint.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.18.16</lombok.version> <mysql.version>5.1.47</mysql.version> <druid.version>1.1.16</druid.version> <mapper.version>4.1.5</mapper.version> <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version> <java.version>1.8</java.version> </properties> <dependencies> <!--SpringBoot 通用依赖模版--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--test--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.1.0</version> </plugin> </plugins> </build> </project>5.1.3.写ymlserver.port=60015.1.4.主启动@SpringBootApplication public class SpringBootDockerDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDockerDemoApplication.class, args); } }5.1.5.业务类import java.util.UUID; @RestController @RequestMapping("/order") public class OrderController { @Value("${server.port}") private String port; @RequestMapping("/docker") public String helloDocker() { return "hell docker" + "\t" + port + "\t" + UUID.randomUUID().toString().replace("-", ""); } @RequestMapping(value = "/index", method = RequestMethod.GET) public String index() { return "服务端口号:" + "\t" + port + "\t" + UUID.randomUUID().toString().replace("-", ""); } }5.1.6.测试5.1.7.打包成一个jar包并上传5.2.通过Dockerfile发布到微服务部署到docker容器5.2.1.IDEA工具将微服务打包成jar包并上传5.2.2.编写Dockerfile5.2.2.1.Dockerfile内容# 基础镜像使用java FROM java:8 # 作者 MAINTAINER DY # volume 指定临时文件为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp VOLUME /tmp # 将jar包添加到容器中并更名为 dy_docker.jar ADD spring-boot-docker-demo-0.0.1-SNAPSHOT.jar /dy_docker.jar # 运行jar包 RUN bash -c 'touch /dy_docker.jar' ENTRYPOINT ["java","-jar","/dy_docker.jar"] # 暴露6001端口作为微服务 EXPOSE 60015.2.2.2.将微服务jar包和Dockerfile文件上传到同一个目录下/app/mydocker5.2.3.构建镜像docker build -t dy_docker.jar:1.1 .5.2.4.运行容器docker run -d -p 6001:6001 dy_docker.jar:1.15.2.5.访问测试curl 192.168.229.134:6001/order/docker curl 192.168.229.134:6001/order/index curl http://192.168.229.134:6001/order/docker curl http://192.168.229.134:6001/order/index六、Docker网络Docker网络作用:容器间的互联和通信以及端口映射容器lP变动时候可以通过服务名直接网络通信而不受到影响6.1.分析图6.2.Docker 不启动,默认的网络情况virbr0 在CentDS7的安装过程中如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的virbr0网卡 (virbr0网卡:它还有一个固定的默认IP地址192.168.122.1),是做虚拟机网桥的使用的,其作用是为连接其上的虚机网卡提供NAT访问外网的功能。 我们之前学习Linux安装,勾选安装系统的时候附带了libvirt服务才会生成的一个东西,如果不需要可以直接将libvirtd服务卸载。yum remove libvirt-libs.x86_646.3.Docker 启动,网络情况Docker 启动,会产生一个名为docker0的虚拟网桥6.4.查看Docker 的网络命令模式6.4.1.docker网络命令大全# 查看Docker网络 docker network ls # 查看网络数据源 docker network inspect XXXX网络名字 # 删除网络 docker network rm XXXX网络名字 docker network --help docker network COMMAND Commands: connect Connect a container to a network create Create a network disconnect Disconnect a container from a network inspect Display detailed information on one or more networks ls List networks prune Remove all unused networks rm Remove one or more networks 6.4.2.查看Docker网络# 查看Docker网络 docker network ls6.4.3.查看网络数据源# 查看网络数据源 docker network inspect XXXX网络名字6.4.4.创建网络# 创建网络 docker network create XXXX网络名字6.4.5.删除网络# 删除网络 docker network rm XXXX网络名字6.5.Docker网络作用Docker网络作用:容器间的互联和通信以及端口映射容器lP变动时候可以通过服务名直接网络通信而不受到影响6.6.Docker网络模式6.6.1.总体介绍网络模式简介bridge为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,默认为该模式。host容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。none容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,IP等。container新创建的容器不会创建自己的网卡和配置自己的lP而是和—个指定的容器共享IP、端口范围等。命令:bridge模式:使用--network bridge指定,默认使用dockerO host模式:使用--network host指定 none模式:使用--network none指定 container模式:使用--network container:NAME或者容器ID指定6.6.2.网络实例内默认网络IP生产规则docker inspect 容器ID or 容器名字# 查看数据源倒数20行 docker inspect u1 | tail -n 206.6.2.1.先启动两个ubuntu实例6.6.2.2.:docker inspect 容器ID or 容器名字6.6.2.3.关闭u2实例,新建u3,查看ip变化6.6.2.4.结论:docker容器内部的ip是有可能会发生改变的6.6.3.案例说明【bridge】6.6.3.1.bridge是什么Docker服务默认会创建一个docker0网桥(其上有一个docker0内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。# 查看bridge 网络的详细信息,并通过grep获取名额 docker network inspect bridge | grep name ifconfig | grep docker6.6.3.2.说明1 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容 器一个IP地址,称为Container-lP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-lP直接通信。2 docker run的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机ifconfig,就可以看到doc ker0和自己create的network(后面讲)eth0,eth1,eth……代表网卡一,网卡二,网卡三…… lo代表127.0.0.1,即localhost, inet addr用来表示网卡的IP地址3 网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配。 3.1 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair); 3.2 每个容器实例内部也有一块网卡,每个接口叫eth0; 3.3 docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一 一匹配。 3.4 通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。 6.6.3.3.代码docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8 docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk86.6.3.4.两两匹配验证6.6.4.案例说明【host】6.6.4.1.host是什么直接使用宿主机的IP地址与外界进行通信,不再需要额外进行NAT转换。6.6.4.2.说明容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。6.6.4.3.代码警告:docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8问题: docke启动时总是遇见标题中的警告原因: docker启动时指定--network=host或-net=host,如果还指定了-p映射端口,那这个时候就会有此警告,并且通过-p设置的参数将不会起到任何作用,端口号会以主机端口号为主 ,重复时则递增。解决: 解决的办法就是使用docker的其他网络模式,例如--network=bridge,这样就可以解决问题,或者直接无视。正确代码:docker run -d --network host --name tomcat84 billygoo/tomcat8-jdk86.6.4.4.没有设置-p端口映射,如何启动访问tomcat84http://宿主机IP:8080/在CentOS里面用默认的火狐浏览器访问容器内的tomcat84看到访问成功,因为此时容器的IP借用主机的,所以容器共享宿主机网络IP,这样的好处是外部主机与容器可以直接通信。6.6.5.案例说明【none】none是禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)在none模式下,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo。需要我们自己为Docker容器添加网卡、配置IP等。docker run -d -p 8085:8080 --network none --name tomcat85 billygoo/tomcat8-jdk86.6.6.案例说明【container】container网络模式新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。6.6.6.1.Alpine操作系统是一个面向安全的轻型Linux发行版Apine Linux是一款独立的、非商业的通用Linux发行版,专为追求安全性、简单性和资源效率的用户而设计。可能很多人没听说过这个Linux发行版本,但是经常用Docker的朋友可能都用过,因为他小,简单,安全而著称,所以作为基础镜像是非常好的一个选择,可谓是麻雀虽小但五脏俱全,镜像非常小巧,不到6M的大小,所以特别适合容器打包。6.6.6.2.命令演示docker pull alpine docker run -it --name alpine1 alpine /bin/sh docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh6.6.6.3.运行结果,验证共用搭桥6.6.6.4.加入关闭alpine1,查看alpine26.6.7.案例说明【自定义网络】6.6.7.1.启动两个tomcat并进入容器内部docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8 docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8 #上述成功启动并运行docker exec 进入各自容器实例内部 docker exec -it tomcat81 bash docker exec -it tomcat82 bash6.6.7.2.按照ip地址ping【ok】6.6.7.3.按照服务名ping【error】6.6.7.4.自定义桥接网络,自定义网络默认使用的是桥接网络bridge6.6.7.5.新建自定义网络docker network ls docker network create p_network6.6.7.6.新建容器加入上一步新建的自定义网络docker run -d -p 8081:8080 --network p_network --name tomcat81 billygoo/tomcat8-jdk8 docker run -d -p 8082:8080 --network p_network --name tomcat82 billygoo/tomcat8-jdk8 #上述成功启动并运行docker exec 进入各自容器实例内部 docker exec -it tomcat81 bash docker exec -it tomcat82 bash6.6.7.7.互相ping测试6.6.7.8.问题结论:自定义网络本身就维护好了主机名和ip的对应关系( ip和域名都能通)七、Docker-compose容器编排7.1.Docker-compose由来Compose是Docker公司推出的一个工具软件,可以管理多个Docker容器组成一个应用。你需要定义一个YAML格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器。Docker-Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以最好是将每个服务单独的分割开来但是这样我们又面临了一个问题?如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfle然后在构建镜像,构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署的工具例如:要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端的数据库mysql服务容器,redis服务器,注册中心eureka,甚至还包括负载均衡容器等等......Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML格式)来定义一组相关联的应用容器为一个项目(project可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose解决了容器与容器之间如何管理编排的问题。7.2.下载、安装及卸载7.2.1.下载Docker Compose和Docker版本对应关系官网:https://docs.docker.com/compose/compose-file/compose-file-v3/官网下载:https://docs.docker.com/compose/install/Install Compose standalone: https://docs.docker.com/compose/install/standalone/Docker Compose下载地址:https://github.com/docker/compose/releases下载地址:https://docs.docker.com/compose/install/linux/#install-the-plugin-manually7.2.2.安装步骤命令下载或者手动下载:curl -SL https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose # 赋予执行权限,读写权限 chmod +x /usr/local/bin/docker-compose # 版本信息 docker-compose --version # 建立软连接: sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose7.2.3.卸载步骤# 如果您使用curl以下方式安装,则卸载 Docker Compose: sudo rm /usr/local/bin/docker-compose7.3.Compose核心概念文件docker-compose.yml服务 (service)一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器工程 (project)由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。7.4.Compose使用的三个步骤编写Dockerfile定义各个微服务应用并构建出对应的镜像文件使用docker-compose.yml定义一个完整业务单元,安排好整体应用中的各个容器服务。最后,执行docker-compose up命令来启动并运行整个应用程序,完成一键部署上线7.5.docker-compose.yml文件及常用命令7.5.1.docker-compose.yml文件解读内容如下:version: "3.2" services: nacos: image: nacos/nacos-server environment: MODE: standalone ports: - "8848:8848" mysql: image: mysql:5.7.25 environment: MYSQL_ROOT_PASSWORD: 123456 volumes: - "$PWD/mysql/data:/var/lib/mysql" - "$PWD/mysql/conf:/etc/mysql/conf.d/" userservice: build: ./user-service orderservice: build: ./order-service gateway: build: ./gateway ports: - "10010:10010"可以看到,其中包含5个service服务:nacos:作为注册中心和配置中心image: nacos/nacos-server: 基于nacos/nacos-server镜像构建environment:环境变量MODE: standalone:单点模式启动ports:端口映射,这里暴露了8848端口mysql:数据库image: mysql:5.7.25:镜像版本是mysql:5.7.25environment:环境变量MYSQL_ROOT_PASSWORD: 123:设置数据库root账户的密码为123volumes:数据卷挂载,这里挂载了mysql的data、conf目录,其中有我提前准备好的数据userservice、orderservice、gateway:都是基于Dockerfile临时构建的7.5.2.docker-compose.yml的编写规则介绍以mysql服务为例,说明下常用字段的含义:version: '3'#第一层:compose的版本号 services: #第二层:服务配置信息 mysql1: #服务名 image: mysql #该服务所基于的镜像名 environment: #该服务的环境变量 MYSQL_ROOT_PASSWORD: "ut.123456" ports: #该服务的暴露端口 - "3306:3306" container_name: "mysql1" #容器名 networks: #该服务所加入的网络段 - dev volumes: #挂载数据卷 - /platform/mysql/conf:/etc/my.cnf.d/my.cnf - /platform/mysql/data:/var/lib/mysql:rw" networks: #第三层:网络环境 dev: driver: bridge7.5.3.Compose命令格式docker compose 命令的基本格式为:docker-compose [-f …] [options] [COMMAND] [ARGS…]7.5.4.Compose常用命令命令作用docker-compose -h#查看帮助docker-compose up#启动所有docker-compose服务docker-compose up -d#启动所有docker-compose服务并后台运行docker-compose down#停止并删除容器、网络、卷、镜像。docker-compose exec yml里面的服务id#进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bashdocker-compose ps#展示当前docker-compose编排过的运行的所有容器docker-compose top#展示当前docker-compose编排过的容器进程docker-compose logs yml里面的服务id#查看容器输出日志dokcer-compose config#检查配置dokcer-compose config -q#检查配置,有问题才有输出docker-compose restart#重启服务docker-compose start#启动服务docker-compose stop#停止服务7.5.5.以nginx容器操作为例docker-compose ps 显示所有容器 docker-compose build nginx 构建nginx镜像 docker-compose up -d nginx 构建启动nignx容器 docker-compose exec nginx bash 登录到nginx容器中 docker-compose pause nginx 暂停nignx容器 docker-compose unpause nginx 恢复ningx容器 docker-compose start nginx 启动nignx容器 docker-compose stop nginx 停止nignx容器 docker-compose restart nginx 重新启动nginx容器 docker-compose rm nginx 删除nginx容器 docker-compose down 删除nginx容器和镜像 docker-compose logs -f nginx 查看nginx的实时日志DockerCompose的详细语法参考官网:https://docs.docker.com/compose/compose-file/7.6.Compose编排微服务7.6.1.改造升级微服务工程spring-boot-docker-demo7.6.1.1.SQL建库建表CREATE TABLE t_user ( id int unsigned NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL DEFAULT '' COMMENT '用户名', password varchar(50) NOT NULL DEFAULT '' COMMENT '密码', sex tinyint NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ', deleted tinyint unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除', update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=1114 DEFAULT CHARSET=utf8mb3 COMMENT='用户表';insert into t_user (id,username,password)values (1095,'xyz1',221462), (1096,'xyz2',221463), (1097,'xyz3',221464), (1098,'xyz4',221465), (1099,'xyz5',221466), (1100,'xyz6',221467), (1101,'xyz7',221468), (1102,'xyz8',221469), (1103,'xyz9',221470);7.6.1.2.改pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.6</version> <relativePath/> </parent> <groupId>com.itcast</groupId> <artifactId>spring-boot-docker-demo</artifactId> <version>1.2</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.complier.source>1.8</maven.complier.source> <maven.complier.target>1.8</maven.complier.target> <juint.version>4.12</juint.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.18.16</lombok.version> <mysql.version>5.1.47</mysql.version> <druid.version>1.1.16</druid.version> <mapper.version>4.1.5</mapper.version> <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version> </properties> <dependencies> <!--guava Google 开源的 Guava 中自带的布隆过滤器--> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency> <!-- redisson --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.13.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--swagger2--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <!--SpringBoot与Redis整合依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--springCache--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!--springCache连接池依赖包--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.1.0</version> </dependency> <!--Mysql数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--SpringBoot集成druid连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!--mybatis和springboot整合--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.spring.boot.version}</version> </dependency> <!-- 添加springboot对amqp的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency> <!--通用基础配置junit/devtools/test/log4j/lombok/hutool--> <!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.2.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <optional>true</optional> </dependency> <!--persistence--> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0.2</version> </dependency> <!--通用Mapper--> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>${mapper.version}</version> </dependency> <!--test--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.1.0</version> </plugin> </plugins> </build> </project> 7.6.1.3.写application.ymlserver.port=6001 # ========================alibaba.druid相关配置===================== spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.229.134:3306/db2024?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.druid.test-while-idle=false # ========================redis相关配置===================== spring.redis.database=0 spring.redis.host=192.168.229.134 spring.redis.port=6379 spring.redis.password= spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=-1ms spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0 # ========================mybatis相关配置=================== mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.itcast.entry # ========================swagger===================== spring.swagger2.enabled=true 7.6.1.4.主启动类SpringBootDockerDemoApplication.javapackage com.itcast; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import tk.mybatis.spring.annotation.MapperScan; @SpringBootApplication @MapperScan("com.itcast.mapper") //import tk.mybatis.spring.annotation.MapperScan; public class SpringBootDockerDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDockerDemoApplication.class, args); } }7.6.1.5.业务类7.6.1.5.1.config配置类RedisConfig.javapackage com.itcast.config; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.io.Serializable; @Configuration @Slf4j public class RedisConfig { /** * @param lettuceConnectionFactory * @return redis序列化的工具配置类,下面这个请一定开启配置 * 127.0.0.1:6379> keys * * 1) "ord:102" 序列化过 * 2) "\xac\xed\x00\x05t\x00\aord:102" 野生,没有序列化过 */ @Bean public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); //设置key序列化方式string redisTemplate.setKeySerializer(new StringRedisSerializer()); //设置value的序列化方式json redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } }7.6.1.5.2.config配置类SwaggerConfig.javapackage com.itcast.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.text.SimpleDateFormat; import java.util.Date; @Configuration @EnableSwagger2 public class SwaggerConfig { @Value("${spring.swagger2.enabled}") private Boolean enabled; @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .enable(enabled) .select() .apis(RequestHandlerSelectors.basePackage("com.itcast")) //你自己的package .paths(PathSelectors.any()) .build(); } public ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Api接口测试" + "\t" + new SimpleDateFormat("yyyy-MM-dd").format(new Date())) .description("docker-compose") .version("1.0") .termsOfServiceUrl("https://www.atguigu.com/") .build(); } }7.6.1.5.3.实体类User.javapackage com.itcast.entry; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import java.util.Date; @Table(name = "t_user") public class User { @Id @GeneratedValue(generator = "JDBC") private Integer id; private String username; //用户名 private String password; //密码 private Byte sex; //性别 0=女 1=男 private Byte deleted; //删除标志,默认0不删除,1删除 @Column(name = "update_time") private Date updateTime; //更新时间 @Column(name = "create_time") private Date createTime; //创建时间 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Byte getSex() { return sex; } public void setSex(Byte sex) { this.sex = sex; } public Byte getDeleted() { return deleted; } public void setDeleted(Byte deleted) { this.deleted = deleted; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } }7.6.1.5.4.实体类UserDTO.javapackage com.itcast.entry; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.Date; @NoArgsConstructor @AllArgsConstructor @Data @ApiModel(value = "用户信息") public class UserDTO implements Serializable { @ApiModelProperty(value = "用户ID") private Integer id; @ApiModelProperty(value = "用户名") private String username; @ApiModelProperty(value = "密码") private String password; @ApiModelProperty(value = "性别 0=女 1=男 ") private Byte sex; @ApiModelProperty(value = "删除标志,默认0不删除,1删除") private Byte deleted; @ApiModelProperty(value = "更新时间") private Date updateTime; @ApiModelProperty(value = "创建时间") private Date createTime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Byte getSex() { return sex; } public void setSex(Byte sex) { this.sex = sex; } public Byte getDeleted() { return deleted; } public void setDeleted(Byte deleted) { this.deleted = deleted; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", sex=" + sex + '}'; } }7.6.1.5.5.编写UserMapper.javapackage com.itcast.mapper; import com.itcast.entry.User; import tk.mybatis.mapper.common.Mapper; public interface UserMapper extends Mapper<User> {//tk.mybatis.mapper.common.Mapper }7.6.1.5.6.在src/main/resources目录下创建mapper文件夹,并编写UserMapper.xmlUserMapper.xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.itcast.mapper.UserMapper"> <resultMap id="BaseResultMap" type="com.itcast.entry.User"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="username" jdbcType="VARCHAR" property="username"/> <result column="password" jdbcType="VARCHAR" property="password"/> <result column="sex" jdbcType="TINYINT" property="sex"/> <result column="deleted" jdbcType="TINYINT" property="deleted"/> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> </resultMap> </mapper>7.6.1.5.7.新建UserService、UserServiceImplpublic interface UserService { void addUser(User user); User findUserById(Integer id); void deleteUser(Integer id); void updateUser(User user); }package com.itcast.service.impl; import com.itcast.entry.User; import com.itcast.mapper.UserMapper; import com.itcast.service.UserService; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service @Slf4j public class UserServiceImpl implements UserService { public static final String CACHE_KEY_USER = "user:"; @Resource private UserMapper userMapper; @Resource private RedisTemplate redisTemplate; @Override public void addUser(User user) { //1 先插入mysql并成功 int i = userMapper.insertSelective(user); if (i > 0) { //2 需要再次查询一下mysql将数据捞回来并ok user = userMapper.selectByPrimaryKey(user.getId()); //3 将捞出来的user存进redis,完成新增功能的数据一致性。 String key = CACHE_KEY_USER + user.getId(); redisTemplate.opsForValue().set(key, user); } } @Override public User findUserById(Integer id) { User user = null; String key = CACHE_KEY_USER + id; //1 先从redis里面查询,如果有直接返回结果,如果没有再去查询mysql user = (User) redisTemplate.opsForValue().get(key); if (user == null) { //2 redis里面无,继续查询mysql user = userMapper.selectByPrimaryKey(id); if (user == null) { //3.1 redis+mysql 都无数据 //你具体细化,防止多次穿透,我们规定,记录下导致穿透的这个key回写redis return user; } else { //3.2 mysql有,需要将数据写回redis,保证下一次的缓存命中率 redisTemplate.opsForValue().set(key, user); } } return user; } @Override public void deleteUser(Integer id) { String key = CACHE_KEY_USER + id; //1.从mysql里面删除 userMapper.deleteByPrimaryKey(id); //2.从redis里面删除 redisTemplate.delete(key); } @Override public void updateUser(User user) { String key = CACHE_KEY_USER + user.getId(); //1.从mysql更新数据 userMapper.updateByPrimaryKey(user); User user1 = findUserById(user.getId()); //2.从redis更新数据 redisTemplate.opsForValue().set(key, user1); } }7.6.1.5.8.新建UserControllerpackage com.itcast.controller; import cn.hutool.core.util.IdUtil; import com.itcast.entry.User; import com.itcast.entry.UserDTO; import com.itcast.service.impl.UserServiceImpl; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.Random; @Api(description = "用户User接口") @RestController @Slf4j @RequestMapping("/users") public class UserController { @Resource private UserServiceImpl userService; @ApiOperation("数据库新增3条记录") @PostMapping public void addUser() { for (int i = 1; i <= 3; i++) { User user = new User(); user.setUsername("lb" + i); user.setPassword(IdUtil.simpleUUID().substring(0, 6)); user.setSex((byte) new Random().nextInt(2)); userService.addUser(user); } } @ApiOperation("删除1条记录") @DeleteMapping("/{id}") public void deleteUser(@PathVariable Integer id) { userService.deleteUser(id); } @ApiOperation("修改1条记录") @PutMapping public void updateUser(@RequestBody UserDTO userDTO) { User user = new User(); BeanUtils.copyProperties(userDTO, user); userService.updateUser(user); } @ApiOperation("查询1条记录") @GetMapping("/{id}") public User findUserById(@PathVariable Integer id) { return userService.findUserById(id); } } 7.6.1.7.mvn package命令将微服务形成新的jar包,并上传到Linux服务器 /app/mydocker目录下7.6.1.8.编写Dockerfile# 基础镜像使用java FROM java:8 # 作者 MAINTAINER DY # volume 指定临时文件为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp VOLUME /tmp # 将jar包添加到容器中并更名为 docker-compose-test.jar ADD spring-boot-docker-demo-1.2.jar docker-compose-test.jar # 运行jar包 RUN bash -c 'touch /docker-compose-test.jar' ENTRYPOINT ["java","-jar","/docker-compose-test.jar"] # 暴露6001端口作为微服务 EXPOSE 60017.6.1.9.构建镜像docker build -t docker-compose-test:1.2 .7.6.2.不使用Compose7.6.2.1.单独的mysql容器7.6.2.1.1.新建mysql容器实例/app/mysql/conf/my.cnf[client] default_character_set=utf8 [mysqld] collation_server = utf8_general_ci character_set_server = utf8docker run \ -p 3306:3306 \ --name mysql57 \ --privileged=true \ -v /app/mysql/conf:/etc/mysql/conf.d \ -v /app/mysql/logs:/logs \ -v /app/mysql/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ -d mysql:5.77.6.2.1.2.进入mysql容器实例内并新建库db2024 + 新建表t_userdocker exec -it mysql57 bash create database db2024; use db2024;CREATE TABLE t_user ( id int unsigned NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL DEFAULT '' COMMENT '用户名', password varchar(50) NOT NULL DEFAULT '' COMMENT '密码', sex tinyint NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ', deleted tinyint unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除', update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=1114 DEFAULT CHARSET=utf8mb3 COMMENT='用户表';7.6.2.2.单独的redis容器docker run \ -p 6379:6379 \ --name redis \ --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 exec -it redis608 bash redis-cli -p 63797.6.2.3.微服务工程docker run -d -p 6001:6001 docker-compose-test:1.2 docker run -d -p 6001:6001 82901d53b6fd7.6.2.4.上面三个容器实例依次顺序启动成功7.6.2.5.swagger测试测试链接:http://192.168.229.134:6001/swagger-ui.html#/7.6.3.上面成功了,有哪些问题【痛点】先后顺序要求固定,先mysql+redis才能微服务访问成功多个run命令......容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错,要么生产IP写死(可以但是不推荐),要么通过服务调用7.6.4.使用Compose7.6.4.1.编写docker-compose.yml文件docker-compose.ymlversion: "3" services: microService: image: docker-compose-test:1.3 container_name: ms01 ports: - "6001:6001" volumes: - /app/microService:/data networks: - p_net depends_on: - redis - mysql redis: image: redis:6.0.8 ports: - "6379:6379" volumes: - /app/redis/redis.conf:/etc/redis/redis.conf - /app/redis/data:/data networks: - p_net command: redis-server /etc/redis/redis.conf mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: '123456' MYSQL_ALLOW_EMPTY_PASSWORD: 'no' MYSQL_DATABASE: 'db2024' MYSQL_USER: 'lb' MYSQL_PASSWORD: '123456' ports: - "3306:3306" volumes: - /app/mysql/db:/var/lib/mysql - /app/mysql/conf/my.cnf:/etc/my.cnf - /app/mysql/init:/docker-entrypoint-initdb.d networks: - p_net command: --default-authentication-plugin=mysql_native_password networks: p_net: 详解:version: "3" # 版本号 services: microService: # 定义服务名字,微服务microService image: docker-compose-test:1.3 # 镜像名字:版本号 container_name: ms01 ports: - "6001:6001" volumes: - /app/microService:/data networks: - p_net depends_on: - redis - mysql # docker run -d -p 6001:6001 -v /app/microService:/data --network p_net --name ms01 docker-compose-test:1.3 redis: image: redis:6.0.8 ports: - "6379:6379" volumes: - /app/redis/redis.conf:/etc/redis/redis.conf - /app/redis/data:/data networks: - p_net command: redis-server /etc/redis/redis.conf mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: '123456' MYSQL_ALLOW_EMPTY_PASSWORD: 'no' MYSQL_DATABASE: 'db2024' MYSQL_USER: 'lb' MYSQL_PASSWORD: '123456' ports: - "3306:3306" volumes: - /app/mysql/db:/var/lib/mysql - /app/mysql/conf/my.cnf:/etc/my.cnf - /app/mysql/init:/docker-entrypoint-initdb.d networks: - p_net command: --default-authentication-plugin=mysql_native_password #解决外部无法访问 # docker network create p_net networks: p_net: 7.6.4.2.第二次修改微服务工程两处修改将192.168.229.134换成对应的服务名称mysql,redis#spring.datasource.url=jdbc:mysql://192.168.229.134:3306/db2024?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.url=jdbc:mysql://mysql:3306/db2024?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.druid.test-while-idle=false # ========================redis相关配置===================== spring.redis.database=0 #spring.redis.host=192.168.229.134 spring.redis.host=redis spring.redis.port=6379 spring.redis.password= spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=-1ms spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0 # ========================mybatis相关配置=================== mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.itcast.entry # ========================swagger===================== spring.swagger2.enabled=true# 构建新镜像docker-compose-test:1.3 docker build -t docker-compose-test:1.3 .7.6.4.3.执行 docker-compose up 或者 docker-compose up -d# 检查配置,有问题才输出 docker-compose config -q7.6.4.4.进入mysql容器实例并新建库db2024+新建表t_userdocker exec -it d128363b77bc bash mysql -ulb -p123456 create database db2024; use db2024; CREATE TABLE t_user ( id int unsigned NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL DEFAULT '' COMMENT '用户名', password varchar(50) NOT NULL DEFAULT '' COMMENT '密码', sex tinyint NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ', deleted tinyint unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除', update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=1114 DEFAULT CHARSET=utf8mb3 COMMENT='用户表';7.6.4.5.测试通过测试链接:http://192.168.229.134:6001/swagger-ui.html#/7.6.4.6.Compose常用命令命令作用docker-compose -h#查看帮助docker-compose up#启动所有docker-compose服务docker-compose up -d#启动所有docker-compose服务并后台运行docker-compose down#停止并删除容器、网络、卷、镜像。docker-compose exec yml里面的服务id#进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bashdocker-compose ps#展示当前docker-compose编排过的运行的所有容器docker-compose top#展示当前docker-compose编排过的容器进程docker-compose logs yml里面的服务id#查看容器输出日志dokcer-compose config#检查配置dokcer-compose config -q#检查配置,有问题才有输出docker-compose restart#重启服务docker-compose start#启动服务docker-compose stop#停止服务以nginx容器操作为例,常见操作如下:docker-compose ps 显示所有容器 docker-compose build nginx 构建nginx镜像 docker-compose up -d nginx 构建启动nignx容器 docker-compose exec nginx bash 登录到nginx容器中 docker-compose pause nginx 暂停nignx容器 docker-compose unpause nginx 恢复ningx容器 docker-compose start nginx 启动nignx容器 docker-compose stop nginx 停止nignx容器 docker-compose restart nginx 重新启动nginx容器 docker-compose rm nginx 删除nginx容器 docker-compose down 删除nginx容器和镜像 docker-compose logs -f nginx 查看nginx的实时日志DockerCompose的详细语法参考官网:https://docs.docker.com/compose/compose-file/7.6.4.7.关停7.6.5.Redis总是连接失败总结7.6.5.1.can't connect to redis-serverRedis-Desktop-Manager连接需要四个参数介绍:Name:自定义连接名 Host:redis服务器地址,在CentOS终端中使用命令; ifconfig:该命令显示的,ens33中的inet后的地址即为redis-server host 端口:默认6379 Auth:数据库密码,通常是设置数据库config时自定义的密码7.6.5.2.将redis.conf文件下列参数更改#bind 127.0.0.1 # 注释掉,允许远程连接(注释或者改为bind 0.0.0.0) protected-mode no # 保护模式由yes改为no appendonly yes # 开启AOP持久化 daemonize no # 后台启动设置为no #requirepass 123456 # 开启redis验证# 查看redis服务进程是否正常开启 ps -ef|grep redis|grep -v grep ps -ef |grep redissystemctl stop firewalld # 关闭linux防火墙 systemctl status firewalld # 查看firewall的状态7.6.5.3.测试redis连接7.6.5.4.docker redis容器连接不上--可以自定义网络模式# 创建自定义网络 docker network create test_network # 启动Redis容器,并加入自定义网络 docker run \ -p 6380:6379 \ --network test_network \ --name redis6 \ --privileged=true \ -d redis:latest redis-server # 启动其他容器,并加入自定义网络7.6.5.5.Docker运行Redis容器总结在使用Docker运行Redis容器时,如果遇到连接不上的问题,可以先检查网络配置是否正确,包括IP地址冲突和防火墙设置。如果仍然无法解决,可以尝试修改Redis配置文件,并挂载到容器中。另外,如果需要容器间通信,可以选择合适的网络模式来解决问题。7.6.6.docker: Error response from daemon: driver failed programming external connectivity on endpoint redisdocker: Error response from daemon: driver failed programming external connectivity on endpoint redis (88aa3ee8adb07d3da901e2a53d4f086ea9eca3a686c3a0374745d272aff71495): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 6379 -j DNAT --to-destination 172.17.0.3:6379 ! -i docker0: iptables: No chain/target/match by that name.八、Docker轻量级可视化工具Portainer8.1.可视化工具Portainer简介Portainer是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。8.2.安装Portainer8.2.1.官网https://www.portainer.io/https://docs.portainer.io/v/ce-2.9/start/install/server/docker/linux8.2.2.docker命令安装8.2.2.1.搜索portainer镜像docker search portainer --limit 58.2.2.2.拉取portainer镜像docker pull portainer/portainer docker images portainer/portainer:latest8.2.2.3.启动portainer容器-restart=always:表示docker容器重启了,portainer容器也跟着重启,如影随形,实时监控# 启动镜像 docker run -d \ -p 8000:8000 \ -p 9000:9000 \ --name potainer \ --restart=always \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /dockerData/portainer_data:/data \ portainer/portainer:latest-p : 指定宿主机端口和容器端口 portainer默认端口是9000 -v : 目录映射,将/var/run/docker.sock映射到容器中,用于访问Docker的守护进程,控制Docker。 -v /dockerData/portainer_data保存Portainer的配置信息。 -restart=always: 代表在容器退出时总是重启容器,还有其他几种重启策略:no、on-failure、on-failuer:n、unless-stopped -p 9000:9000 端口映射默认为9000,映射为9000;9000为对外暴漏外部服务的端口号 --name portainer 镜像名字8.2.3.第一次登录需创建admin,访问地址:XXX.XXX.XXX.XXX:9000登录网址http://自己IP:9000用户名随便,默认admin密码随便12345678网址http:192.168.229.134:90008.2.4.设置admin用户和密码后首次登陆8.2.5.选择local选项卡后本地docker详细信息展示8.2.6.上一步的图形展示,对应命令--【docker system df】8.3.登录并演示介绍常用操作case8.4.Portainer安装niginx8.4.1.创建并运行nginx容器的命令:docker run --name containerName -p 80:80 -d nginx命令解读:docker run :创建并运行一个容器--name : 给容器起一个名字,比如叫做mn-p :将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口-d:后台运行容器nginx:镜像名称,例如nginx8.4.2.进入mynginx容器进入我们刚刚创建的mynginx容器的命令为:docker exec -it mynginx bash命令解读:docker exec :进入容器内部,执行一个命令-it : 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互mynginx :要进入的容器的名称bash:进入容器后执行的命令,bash是一个linux终端交互命令九、Docker容器监控之 CAdvisor+InfluxDB+Granfana9.1.docker命令存在的问题问题:通过docker stats命令可以很方便的看到当前宿主机上所有容器的CPU,内存以及网络流量等数据,一般小公司够用了。。。但是,docker stats统计结果只能是当前宿主机的全部容器,数据资料是实时的,没有地方存储、没有健康指标过线预警等功能9.2.CAdvisor监控收集+lnfluxDB存储数据+Granfana展示图表9.2.1.CAdvisor监控收集CAdvisor是一个容器资源监控工具,包括容器的内存,CPU,网络IO,磁盘IO等监控,同时提供了一个WEB页面用于查看容器的实时运行状态。CAdvisor默认存储2分钟的数据,而且只是针对单物理机。不过,CAdvisor提供了很多数据集成接口,支持InfluxDB,Redis,Kafka,Elasticsearch等集成,可以加上对应配置将监控数据发往这些数据库存储起来。CAdvisor功能主要有两点:展示Host和容器两个层次的监控数据。展示历史变化数据。9.2.2.lnfluxDB存储数据InfluxDB是用Go语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖。CAdvisor默认只在本机保存最近2分钟的数据,为了持久化存储数据和统一收集展示监控数据,需要将数据存储到InfluxDB中。InfluxDB是一个时序数据库,专门用于存储时序相关数据,很适合存储CAdvisor的数据。而且,CAdvisor本身已经提供了InfluxDB的集成方法,丰启动容器时指定配置即可。lnfluxDB主要功能:基于时间序列,支持与时间有关的相关函数(如最大、最小、求和等);可度量性:你可以实时对大量数据进行计算;基于事件:它支持任意的事件数据;9.2.3.Granfana展示图表Grafana是一个开源的数据监控分析可视化平台,支持多种数据源配置(支持的数据源包括InfluxDB,MySQL,Elasticsearch,OpenTSDB,Graphite等)和丰富的插件及模板功能,支持图表权限控制和报警。Grafan主要特性:灵活丰富的图形化选项可以混合多种风格。支持白天和夜间模式。多个数据源9.2.4.总结9.3.Compose容器编排9.3.1.新建目录/app/mydocker/cigmkdir -p /app/mydocker/cig cd /app/mydocker/cig pwd9.3.2.新建3件套docker-compose.yml文件version: '3.1' # 3.0以上的版本 volumes: grafana_data: {} # grafana数据的挂载 services: influxdb: image: tutum/influxdb:0.9 restart: always environment: - PRE_CREATE_DB=cadvisorr # 预先在cadvisor创建一个数据库 ports: - "8083:8083" # web端口 - "8086:8086" # 内部端口 volumes: - ./data/influxdb:/data cadvisor: image: google/cadvisor links: - influxdb:influxsrv command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086 restart: always ports: - "8080:8080" volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro grafana: user: "104" image: grafana/grafana user: "104" restart: always links: - influxdb:influxsrv ports: - "3000:3000" volumes: - grafana_data:/var/lib/grafana environment: - HTTP_USER=admin - HTTP_PASS=admin - INFLUXDB_HOST=influxsrv - INFLUXDB_PORT=8086 - INFLUXDB_NAME=cadvisor - INFLUXDB_USER=root - INFLUXDB_PASS=root9.3.3.启动docker-compose文件# 后台启动 docker-compose up -d # 查看日志 docker-compose logs9.3.4.查看三个服务器是否启动9.3.5.测试9.3.5.1.浏览cAdvisor收集服务,http://ip:8080/9.3.5.2.浏览influxdb存储服务,http://ip:8083/9.3.5.3.浏览grafana展现服务,http://ip:3000,默认账号密码admin/admin9.3.5.3.1. grafana配置步骤配置数据源选择influxdb数据源配置细节配置面板panelCAdvisor+InfluxDB+Granfana容器监控系统部署完成9.3.5.3.2. 配置数据源9.3.5.3.3. 点击Add data source选择influxdb数据源9.3.5.3.4. 配置细节9.3.5.3.5. 配置面板panel9.3.5.3.6. CAdvisor+InfluxDB+Granfana容器监控系统部署完成十、终结&总结--知识回顾简单串讲和总结进阶篇:雷丰阳老师的K8Sendl
2024年10月03日
8 阅读
0 评论
0 点赞