docker进阶
容器数据卷什么是容器数据卷docker的理念回顾将应用和环境打包成一个镜像!数据。如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化MySQL,容器删了,相当于删库跑路!需求:mysql数据可以存储在本地!容器有一个数据共享的技术!Docker容器中产生的数据,同步到本地!这就是卷技术!相当于目录的挂载,将容器内的目录。挂载到linux上面。总结:容器的持久化和同步操作!容器
容器数据卷
什么是容器数据卷
docker的理念回顾
将应用和环境打包成一个镜像!
- 数据。如果数据都在容器中,那么我们容器删除,数据就会丢失!
需求:数据可以持久化 - MySQL,容器删了,相当于删库跑路!
需求:mysql数据可以存储在本地!
容器有一个数据共享的技术!Docker容器中产生的数据,同步到本地!这就是卷技术!相当于目录的挂载,将容器内的目录。挂载到linux上面。
总结:容器的持久化和同步操作!容器间也是可以数据共享的!即使容器没有运行,当然容器被干掉就不行了
面试可能会问的小问题:
挂载之后,容器的目录与宿主机的目录同步,那么实际上是同一个目录么?这时数据存储是之前的一倍还是没有变化?
个人理解,实际上并不是同一个目录,只是映射的关系,因为有两个目录了,那数据当然是之前的一倍!
使用数据卷
注意:
目录挂载有时候会出现宿主机和容器内挂载目录都被清空,那么只需要先启动容器,把容器内需要挂载的目录拷贝到宿主机,再进行挂载,具体原因暂时不清楚
方式一:直接用命令来挂载 -v
我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们修改宿主机中的内容就相当于修改了容器中的内容。
# 多个-v 可以挂载多个目录
# 主机目录:容器内目录
docker run -di -v /usr/local/guazaiceshi/:/usr/local/guazaiceshi --name=guazaiceshi --privileged=true b6973f169077 /bin/bash
# 权限不足的时候使用
--privileged=true
# 查看是否挂载成功
docker inspect 容器id
# 找Mounts,source为主机目录,Destination为容器目录
实战,同步Mysql数据
mysql数据都是在data文件夹下,只需要对data目录挂载即可
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root mysql
# 测试,连接Mysql新建一个数据库,就会发现data目录下多了一个文件夹
匿名挂载和具名挂载
# 匿名挂载,这个目录是容器内的目录
docker run -d -P -v /etc/nginx nginx
# 查看所有卷(挂载)列表
docker volume ls
# 参数
inspect # 查看卷信息 # 单个卷信息需要在后面写卷名
DRIVER VOLUME NAME
local 4aed9b3a9616da9a1cf9decefd435062f9d74f5c34f0ff173cb4741fc1531775
local 238fd52ee900ee9be78d93cf437e265611a3438909f90c1e2ce30db84e4f97e9
local 31536dd6d44083b10e9b57df32c1124a3a4463528e65531f5103e70b86b1e96b
# 这就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!
# 具名挂载,/代表根目录,不带/则代表配置卷的名字
docker run -d -P -v juming-nginx:/etc/nginx nginx
# local juming-nginx
所有docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/卷名/data_
下,这也就是同步容器内的文件夹
通过具名挂载可以方便的找到我们的一个卷,大多数情况使用具名挂载
如何确定是具名挂载还是匿名挂载,还是指定路径挂载?
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
读写权限
# ro readonly 只读
# 一旦设置了容器权限,容器内就不可更改了,只能从宿主机改变
docker run -d -P -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P -v juming-nginx:/etc/nginx:rw nginx
方式二Dockerfile
DockerFile就是用来构建docker镜像的构建文件!实际上就是一个命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个一个的命令,每个命令都是一层!
# dockerfile 文件中的内容,名字为 Dockerfile
# 指令大写
FROM centos
VOLUME["volume01","volume02"]
CMD echo "---end---"
CMD /bin/bash
# 启动命令
# -f Dockerfile文件
# -t 镜像名
docker build -f dockerfile1 -t kuangshen/centos .
# 完成之后会生成一个 kuangshen/centos 的镜像,启动镜像,容器中会有volume01 volume02两个文件夹,这两个目录就是我们生成镜像的时候自动挂载的,数据卷目录
# 宿主机挂载目录,找mounts
docker inspect 容器id
这种方式我们未来使用的很多,因为我们通常会构建自己的镜像!
假设构建镜像的时候没有挂载,就要手动镜像挂载 -v 卷名:容器内路径!
数据卷容器,–volumes-from
多个mysql同步数据!
# 先用正常方式run docker01
# docker01 与 docker02 实现同步,因为构建镜像时同步的文件只有volume01 volume02,所以同步的也就只有这两个文件夹
docker run -it --name docker02 --volumes-from docker01 kuangshen/centos
# 此时三个容器对应宿主机的挂载目录是同一目录,所以宿主机的这一目录,也同步这三个容器
docker run -it --name docker03 --volumes-from docker01 kuangshen/centos
# 即使docker01容器被删除,docker02,03和宿主机的同步文件依旧存在
结论:数据卷的生命周期一直持续到没有容器使用为止!
Dockerfile
介绍
dockerfile是用来构建docker镜像的文件!命令参数脚本!
构建步骤:
- 编写一个dockerfile文件
- docker build 构建成为一个镜像
- docker run运行镜像
- docker push 发布镜像(docker hub、阿里云镜像仓库!)
基础知识:
- 每个保留关键字(指令)都必须是大写字母
- 从上到下顺序执行
- ‘#’ 表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交!
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
docker镜像逐渐成为企业交付的标准,必须要掌握!
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品!
Docker容器:容器就是镜像运行起来提供服务器!
DockerFile的指令
以前的话我们就是使用别人的,现在我们知道了这些指令后,我们来练习自己写一个镜像!
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的linux命令
ADD # 步骤:例如要添加tomcat镜像,就添加tomcat这个压缩包!
COPY # 类似ADD,将我们文件拷贝到镜像中
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 暴露端口,和-p是一个道理
CMD # 指定容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令。触发指令
ENV # 构建的时候设置环境变量
CMD和ENTRYPOINT的区别
# dockerfile 内容
FROM centos
CMD ["ls","-a"]
# 构建镜像
docker build -f dockerfile-cmd-test -t cmdtest .
# 运行容器
docker run 113e028fd125
# 运行容器后显示
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 此时追加一个-l命令,期望返回ls -al,
# 但是报错了,是因为CMD的情况下,-l 替换了 CMD ["ls","-a"],而 -l 并不是命令,就报错了
[root@localhost dockerfile]# docker run 113e028fd125 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
# 正确的命令,略显麻烦,ENTRYPOINT就会避免这个错误
docker run 113e028fd125 ls -al
实战测试
Docker Hub 中99% 镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行构建
构建一个自己的centos
下载vim的时候有可能网络延迟下载失败,重新下载就好了
FROM centos
MAINTAINER kuangshen<24736743@11.com>
ENV MYPATH /usr/local
# 启动容器进入的就是这个目录
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
# 构建镜像
# -f dockerfile文件
# -t 生成的镜像名字
docker build -f mydockerfile -t mycentos:0.1 .
查看官方构建步骤
docker history 镜像名/id
[root@localhost dockerfile]# docker history mysql
IMAGE CREATED CREATED BY SIZE COMMENT
c8562eaf9d81 6 weeks ago /bin/sh -c #(nop) CMD ["mysqld"] 0B
<missing> 6 weeks ago /bin/sh -c #(nop) EXPOSE 3306 33060 0B
<missing> 6 weeks ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
<missing> 6 weeks ago /bin/sh -c ln -s usr/local/bin/docker-entryp… 34B
<missing> 6 weeks ago /bin/sh -c #(nop) COPY file:a209112a748b68e0… 13.1kB
<missing> 6 weeks ago /bin/sh -c #(nop) COPY dir:2e040acc386ebd23b… 1.12kB
<missing> 6 weeks ago /bin/sh -c #(nop) VOLUME [/var/lib/mysql] 0B
<missing> 6 weeks ago /bin/sh -c { echo mysql-community-server m… 411MB
<missing> 6 weeks ago /bin/sh -c echo 'deb http://repo.mysql.com/a… 55B
<missing> 6 weeks ago /bin/sh -c #(nop) ENV MYSQL_VERSION=8.0.23-… 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ENV MYSQL_MAJOR=8.0 0B
<missing> 7 weeks ago /bin/sh -c set -ex; key='A4A9406876FCBD3C45… 2.61kB
<missing> 7 weeks ago /bin/sh -c apt-get update && apt-get install… 52.2MB
<missing> 7 weeks ago /bin/sh -c mkdir /docker-entrypoint-initdb.d 0B
<missing> 7 weeks ago /bin/sh -c set -eux; savedAptMark="$(apt-ma… 4.17MB
<missing> 7 weeks ago /bin/sh -c #(nop) ENV GOSU_VERSION=1.12 0B
<missing> 7 weeks ago /bin/sh -c apt-get update && apt-get install… 9.34MB
<missing> 7 weeks ago /bin/sh -c groupadd -r mysql && useradd -r -… 329kB
<missing> 7 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ADD file:422aca8901ae3d869… 69.2MB
实战tomcat镜像
- 准备镜像文件 tomcat 压缩包(tomcat官网的包下core的),jdk的压缩包!
- 编写dockerfile文件,官方命名为
Dockerfile
,build会自动寻找这个文件,不需要 -f 指定了
# 下载centos镜像,本地有的话直接提取
FROM centos
MAINTAINER kuangshen<24736743@qq.com>
COPY readme.txt /usr/local/readme.txt
# 添加到该目录,ADD命令是会解压的
ADD jdk-8u171-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.43.tar.gz /usr/local/
# 安装vim,-y 同意
RUN yum -y install vim
# 工作目录,进入容器就是这个目录,默认是/
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 配置环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.43
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.43
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
# 暴露端口
EXPOSE 8080
# 输出日志
CMD /usr/local/apache-tomcat-9.0.43/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.43/bin/logs/catalina.out
- 构建镜像、运行容器
# 构建镜像,注意别忘了最后那个 .
docker build -t diytomcat .
docker run -d -p 9090:8080 --name kuangshentomcat -v /home/tomcat/test:/usr/local/apache-tomcat-9.0.43/webapps/test -v /home/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.43/logs diytomcat
# 就可以访问tomcat了
发布自己的镜像
Dockerhub
因为是国外的,所以会很慢,虚拟机几乎不会成功,涉及到翻墙了
docker login -u 账号 -p 密码
# 自己发布的镜像,尽量带版本
docker push kuangshen/镜像名:版本
# 如果上面的报错,改一下镜像名和版本试试
docker tag 镜像id kuangshen/镜像名:版本
阿里云镜像
- 在阿里云找容器镜像服务
- 创建命名空间,相当于一个大文件夹,镜像仓库就是放命名空间的文件
$ sudo docker login --username=林夕qazokmzjl registry.cn-beijing.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-beijing.aliyuncs.com/lxstudy/dockertest:[镜像版本号]
$ sudo docker push registry.cn-beijing.aliyuncs.com/lxstudy/dockertest:[镜像版本号]
阿里云镜像参考官方文档,很详细https://cr.console.aliyun.com/cn-beijing/instances/repositories
Jenkins下用DockerFile自动部署Java(SpringBoot)项目
FROM java:8 #java1.8基础镜像
VOLUME /tmp #创建/tmp目录并持久化到Docker数据文件夹,因为Spring Boot使用的内嵌Tomcat容器默认使用/tmp作为工作目录
MAINTAINER test #作者名称
ADD web-0.0.1-SNAPSHOT.jar test/test_web0.jar #复制jar到test下且重命名为test_web0.jar
EXPOSE 8506 #容器开放端口
ENTRYPOINT ["java","-jar","-Djava.security.egd=file:/dev/.urandom","test/test_web0.jar"].
#容器执行命令
删除、重载镜像容器等操作shell,这样做感觉不是太好,以后有更好的办法在解决
#!/bin/bash -l
docker stop test_web0; #停止容器
docker rm test_web0; #删除容器
docker rmi test/test_web0; #删除镜像
cd /usr/local/wwwroot/test_web/test_web0; #进入目录
docker build -t test/test_web0.; #构建镜像 .为当前目录的dockerfile
docker run -t -d --name test_web0-p 192.168.2.1:8506:8506 test/test_web0; #创建容器
下面这个更专业看起来
这个jar包应该是Jenkins自动会打成jar包的,然后放到本地,也可以选择上传到服务器
d1=$(date "+%Y%m%d%H%M")
name="robot-test"
appName=$name$d1
port=29000
mkdir -p /home/$name
cd /home/$name
cp /usr/local/soft/jenkins/jenkins-data/workspace/robot-test/robot-api/target/robot-api-yskj0.01-releases.jar app.jar
docker rm -f $(docker ps | grep $name | awk '{print $1}')
docker rmi -f $(docker images | grep $name | awk '{print $3}')
cat > Dockerfile << EOF
FROM java:8
EXPOSE $port
#复制代码包到镜像内
ADD app.jar /app.jar
ENV TZ=Asia/Shanghai
RUN bash -c 'touch /app.jar'
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ENTRYPOINT ["java","-jar","-D user.timezone=GMT+08","/app.jar"]
EOF
docker build -t $name:${ImageVersion} .
mkdir -R /logs/robotApi
docker run --name $appName -d -v /logs/robotApi/:/logs/robotApi/ -p $port:$port $name:${ImageVersion}
docker网络
理解Docker 0
如果发现docker 0 没有ip地址的话
# 执行下面命令时需要关闭所有容器
vi /etc/docker/daemon.json
# 添加,bip就是docker0启动后的IP地址
# 这个ip为什么这么配,不太懂
{
"bip": "192.168.200.1/24"
}
systemctl restart docker
lo是本地回环地址
docker0是docker0地址
docker是如何处理容器网络访问的
发现容器启动的时候会得到一个 eht0@if60 ip地址,docker分配的!
思考:linux 能不能ping通容器内部
可以的
两个容器之间是否可以ping通
可以,
这其实就是个 桥接模式 ,都是通过 “路由器” 来联通的
结论:tomcat01 和 tomcat02 都是公用的一个路由器,docker 0
所有容器不指定网络的情况下,都是docker 0路由的,docker会给我们的容器分配一个默认的可用ip
计算机原理
255.255.0.1/16
二进制
00000000.00000000.00000000.00000000
转换为十进制
255.255.255.255
16位截止到第二个255,固定也就是255.255
255.255.0.0
IP共有 255 * 255 - 0.0.0.0(回环地址) - 255.255.255.255
大约65535
原理
- 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡 docker 0
桥接模式,使用的技术是 evth-pair 技术!
启动tomcat容器之后,发现又多了一个网卡
我们发现容器带来的网卡,都是一对对的,例如上面的59和60
evth-pair
就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
openStac,Docker容器之间的连接,都是使用 evth-pair
技术
小结
只要容器删除,对应网桥一对就没了!
– link(不推荐使用)
我们需要的是自定义网络!而不是docker 0!
docker 0问题:不支持容器名连接访问!
思考一个场景,我们编写了一个微服务,访问数据库的时候是ip+什么什么,此时数据库ip重启ip变化了,我们希望可以处理这个问题,就像springCloud的feign访问服务是用的服务的名字,并不是服务的Ip。
# 如果正常启动tomcat01 tomcat02是ping不通的
docker run -d -P --name tomcat03 --link tomcat02 tomcat
# 此时是可以ping通的,但是反向是不通的
docker exec -it tomcat03 ping tomcat02
[root@localhost ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 f903762057df
172.17.0.4 602851931fe2
# 当你访问 tomcat02 它就会去找172.17.0.3
自定义网络
docker网络模式
bridge:桥接 docker(默认,自己创建也使用bridge模式)
none:不配置网络
host:主机模式,和宿主机共享网络
container:容器内网络连通!(用的少!局限很大)
# 我们之前启动的默认是有这个命令的 --net bridge,而这个就是我们的docker01
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0特点:默认的,域名不能访问,--link可以打通连接!
# 我们可以自定义一个网络!
# --driver bridge 默认的,桥接
# --subnet 子网掩码
# --gateway 网关
[root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
1e8941d2482253013134cc77cd8c9d3d181ba32d24b9cc174479388d5e903fcf
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
10959e1aeab4 bridge bridge local
69e0e0ea8669 docker-compose_default bridge local
db0129761cb6 host host local
1e8941d24822 mynet bridge local
2389fd756942 none null local
8b28db849e71 somenetwork bridge local
# 到这为止我们的网络就创建好了
[root@localhost ~]# docker inspect mynet
[
{
"Name": "mynet",
"Id": "1e8941d2482253013134cc77cd8c9d3d181ba32d24b9cc174479388d5e903fcf",
"Created": "2021-03-11T10:02:19.687427947+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
测试
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
docker inspect mynet
"Containers": {
"85f3fb81e713650c33d9ba8c8e3b42eb8cdf2232927007d4016dc144f8af8289": {
"Name": "tomcat-net-01",
"EndpointID": "e6c21f9d150b1491273388c78e6f6dd766726d1de27cb02d8c26526ecd964d57",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"a4d1b0c70f463b1741c95e191893c713d1dfd74cb0a1d7ac83e72a89012a9c70": {
"Name": "tomcat-net-02",
"EndpointID": "652eb7795d357179ffef341fe51d6b02a837ad2edf60fa0dfba02ac06ff7a1b4",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
# 以下都是可以ping通的
docker exec -it tomcat-net-01 ping 192.168.0.3
docker exec -it tomcat-net-01 ping tomcat-net-02
docker exec -it tomcat-net-02 ping tomcat-net-01
我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!
好处:
不同的集群使用不同的网络,保证集群是安全和健康的
例如mysql集群的网络是192.161.0.0
redis集群的网络是192.162.0.0
网络连通(不同网段)
tomcat-01是ping不通tomcat-net-01的,因为它们不在同一网段。
Docker0 和 mynet 两个网卡之间也是不可能被打通的。
但是tomcat-01可以加入到mynet的网段中,也就是一个容器两个ip地址!
# 默认就是docker0 的桥接模式
docker run -d -P --name tomcat02 tomcat
# 自定义网络 mynet
docker run -d -P --name tomcat-net-01 --net mynet tomcat
# 将tomcat01加入到mynet网段中
docker network connect mynet tomcat01
[root@localhost ~]# docker inspect mynet
"Containers": {
"85f3fb81e713650c33d9ba8c8e3b42eb8cdf2232927007d4016dc144f8af8289": {
"Name": "tomcat-net-01",
"EndpointID": "e6c21f9d150b1491273388c78e6f6dd766726d1de27cb02d8c26526ecd964d57",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"a4d1b0c70f463b1741c95e191893c713d1dfd74cb0a1d7ac83e72a89012a9c70": {
"Name": "tomcat-net-02",
"EndpointID": "652eb7795d357179ffef341fe51d6b02a837ad2edf60fa0dfba02ac06ff7a1b4",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"c2fdeff32c042f0b53aff9f3dfd582ff6fb48aa8b15bb20d2cafe117e486f6ac": {
"Name": "tomcat01",
"EndpointID": "46beeb303272d7ec0de96a413f85f1aba182c33081a7b016aad81c3574e24f1a",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
}
},
结论:
假设要跨网络操作别人,就需要使用 docker network connect 连通!
实战:部署redis集群
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建6个redis配置
# 通过for循环,循环6次
for port in $(seq 1 6); \
do \
# 创建redis配置文件
mkdir -p /mydata/redis/node-${port}/conf
# 创建redis config 配置
touch /mydata/redis/node-${port}/conf/redis.conf
# 集群的配置
cat << EOF >> /mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
# 开启集群
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
# 按照这个修改规律启动6个节点
docker run -p 6371:6379 -p 16371:16379 --name redis-1 -v /mydata/redis/node-1/data:/data -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6372:6379 -p 16372:16379 --name redis-2 -v /mydata/redis/node-2/data:/data -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 进去是/data目录,有appendonly.aof nodes.conf
docker exec -it 13 sh
# 创建集群
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
# 连接集群
redis-cli -c
# 查看集群节点,都正常
127.0.0.1:6379> cluster nodes
c116ed5ba6643ddb5bff08a1dc3c30bf5ac66876 172.38.0.14:6379@16379 slave 4f252038c097cd6266a3f811c49ba9b42f30b428 0 1615433327000 4 connected
9757ebf1f6417508647756f6b37c40bf6b4a7493 172.38.0.11:6379@16379 myself,master - 0 1615433326000 1 connected 0-5460
79265c600c7893f337ccd70ce067f703f9e26852 172.38.0.15:6379@16379 slave 9757ebf1f6417508647756f6b37c40bf6b4a7493 0 1615433327000 5 connected
890099a84f443c2b58bdfce60b3b70441dc75553 172.38.0.16:6379@16379 slave 6fcf5d2fe9f16d626e7ed0273b97d06bc3f8d0ed 0 1615433327000 6 connected
4f252038c097cd6266a3f811c49ba9b42f30b428 172.38.0.13:6379@16379 master - 0 1615433327241 3 connected 10923-16383
6fcf5d2fe9f16d626e7ed0273b97d06bc3f8d0ed 172.38.0.12:6379@16379 master - 0 1615433328270 2 connected 5461-10922
# 设置key value,get a会看到是哪个节点,然后去把该节点的docker stop,
127.0.0.1:6379> set a b
172.38.0.13:6379> get a
# crtl + c退出
redis-cli -c
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"
172.38.0.14:6379> cluster nodes
6fcf5d2fe9f16d626e7ed0273b97d06bc3f8d0ed 172.38.0.12:6379@16379 master - 0 1615433676076 2 connected 5461-10922
c116ed5ba6643ddb5bff08a1dc3c30bf5ac66876 172.38.0.14:6379@16379 myself,master - 0 1615433675000 7 connected 10923-16383
890099a84f443c2b58bdfce60b3b70441dc75553 172.38.0.16:6379@16379 slave 6fcf5d2fe9f16d626e7ed0273b97d06bc3f8d0ed 0 1615433674537 6 connected
4f252038c097cd6266a3f811c49ba9b42f30b428 172.38.0.13:6379@16379 master,fail - 1615433499124 1615433497065 3 connected
79265c600c7893f337ccd70ce067f703f9e26852 172.38.0.15:6379@16379 slave 9757ebf1f6417508647756f6b37c40bf6b4a7493 0 1615433675259 5 connected
9757ebf1f6417508647756f6b37c40bf6b4a7493 172.38.0.11:6379@16379 master - 0 1615433674229 1 connected 0-5460
# 此时主节点挂掉,数据仍然可以在从节点获取,实现了高可用
docker 搭建redis集群完成!
我们使用了docker之后,所有的技术都会慢慢的变得简单起来!
springboot微服务打包Docker镜像
- 构建springboot项目并打包
构建好之后写个hello world本地测试成功并打包,再用java -jar jar包名.jar 来进行测试jar包
idea -> settings -> plugins 安装docker,写Dockerfile的时候会有提示
2. 编写dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
# 容器启动时要运行的命令
ENTRYPOINT ["java","-jar","/app.jar"]
- 构建镜像并发布运行
# --net是因为默认的docker 0网卡启动后,
# 用inspect查询 docker 0,其中的container并没有启动的kuangshen666,原因未知
# 看网上有两种解决方式,一种是重新配置网卡
# 这里使用更简单的,使用自定义网络
docker run -d -P --net mynet kuangshen666
curl localhosT:49165/test
以后我们使用了docker之后,给别人交付的就是一个镜像即可!
到这儿,如果只是一个单纯的开发者,docker的知识其实掌握的差不多了,后面就是企业级开发,更偏向运维一些,例如k8s,不过暂时不打算接触,远没到那个级别
到这儿已经比大多数市面上的教程要更详细更多了,这是狂神在视频里说的,我自己就是培训班出来的,他说的是真的,感谢狂神
转载自:
https://www.bilibili.com/video/BV1og4y1q7M4?from=search&seid=18423066343999250308
部分内容参考自:
https://www.cnblogs.com/liyuchuan/p/13435883.html
https://www.jb51.net/article/194333.htm
刘十三懂了,小学同学最多愚蠢,大学同学很有可能猥琐。
云边有个小卖部
张嘉佳
更多推荐
所有评论(0)