Docker Note [vaynexiao]

概念

Docker核心思想
打包装箱!每个箱子是互相隔离的。

镜像(image):
镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很
多容器。 就好似 Java 中的 类和对象,类就是镜像,容器就是对象!

容器(container):
Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的.
启动,停止,删除,基本命令
目前就可以把这个容器理解为就是一个简易的 Linux系统。

仓库(repository):
仓库就是存放镜像的地方!分为公有仓库和私有仓库。(很类似git)
DockerHub(国外)、阿里云 都是容器仓库

Docker和虚拟机技术的不同

  • 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
  • 容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
  • 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响

为什么Docker比VM快
新建一个 容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。然而避免引导、加载操作系统内核是个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载GuestOS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了这个复杂的过程,因此新建一个docker容器只需要几秒钟

简单说就是vm新建虚拟机要连同系统硬件的底层系统一起新建,这个过程很慢,但Docker新建的容器是直接利用宿主机的内核系统,就快了很多。

卸载 安装 启动

# 确定你是CentOS7及以上版本
cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

# yum安装gcc相关(需要确保可以上外网 )
yum -y install gcc
yum -y install gcc-c++

#################################### 卸载 #######################################
systemctl stop docker # 先停止服务

yum list installed | grep docker # 列出已安装的docker程序
containerd.io.x86_64              1.3.7-3.1.el7                  @docker-ce-stable
docker-ce.x86_64                  3:19.03.13-3.el7               @docker-ce-stable
docker-ce-cli.x86_64              1:19.03.13-3.el7               @docker-ce-stable
yum remove   docker-ce.x86_64    docker-ce-cli.x86_64 -y    # 卸载已安装的2个程序
rm -rf /var/lib/docker # 还要删除镜像/容器等

# 这也是卸载和上面啥区别呢
yum -y remove docker docker-common docker-selinux docker-engine
# 这也是卸载,,天哪
yum -y remove docker-ce docker-ce-cli containerd.io 
# 这又是卸载和上面啥区别呢
yum remove docker \
          docker-client \
          docker-client-latest \
          docker-common \
          docker-latest \
          docker-latest-logrotate \
          docker-logrotate \
          docker-engine
          
#################################### yum安装 (推荐) ############################
# 官网安装参考手册:https://docs.docker.com/install/linux/docker-ce/centos/
# 安装需要的环境
yum install -y yum-utils device-mapper-persistent-data lvm2

# 设置stable镜像仓库/设置yum源
# /etc/yum.repos.d 文件夹下会生成 CentOS-Base.repo
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo #官网,速度慢
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #推荐使用aliyun,速度快

yum makecache fast  # 更新yum软件包索引

# 查看所有仓库中所有docker版本,并选择特定版本安装
yum list docker-ce --showduplicates | sort -r # 有很多版本

# 安装 Docker CE
yum -y install docker-ce-17.12.0.ce # 指定版本安装:特别注意docker-ce-17.12.0.ce是怎么组合的
yum -y install docker-ce docker-ce-cli containerd.io # 默认下载最新版本Docker CE 且安装

systemctl start docker   # 启动docker,但只是当下临时启动
systemctl enable docker # 设置为开机启动
docker version # 有client和service两部分表示docker安装启动成功
systemctl status docker # 查看docker启动状态
ps -ef|grep -i docker  # 查看正在进行的docker进程
yum list installed | grep docker # 查看已安装的docker程序
docker run hello-world # 优先本地找hello-world,在取gockerhub找,找到启动,找不到报错
docker images # 列出所有镜像
#################################### tar安装 ??(待补充)  ######################################

#################################### 配置镜像加速  ######################################
# 这是阿里云控台制生成的,直接去复制,每个人都是不一样的
sudo mkdir -p /etc/docker 

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

sudo systemctl daemon-reload 

sudo systemctl restart docker
################################ 其他命令 ######################################
docker version # 显示 Docker 版本信息。 
docker info # 显示 Docker 系统信息,包括镜像和容器数。。 
docker --help # 帮助
docker xxx --help ## 

命令

docker images  # 列出本地镜像
		-a: 列出本地镜像+历史镜像 
		-q: 只显示镜像id 
		--digests: 显示镜像的digests信息(sha256)
		--no-truc:不截取image id,完全显示
		docker images mycentos # 单独查看某一个镜像

docker search mysql # 搜索镜像  对应DockerHub仓库中的镜像
		--no-truc: 显示完整 DESCRIPTION
		-s 30  列出stars不小于指定值的镜像。
		--filter=stars=50 : 也是列出stars不小于指定值的镜像

docker pull mysql # 下载最新镜像
		docker pull mysql:5.7 # 指定版本
		
docker rmi -f bc9a0695f571 # 根据id删除镜像
		docker rmi -f hello-world:latest mysql:5.7 # 根据名字和tag同时删除多个镜像
		docker rmi -f $(docker images -qa)  # 全部删除
		
docker run [OPTIONS] IMAGE [COMMAND][ARG...] # 使用到了镜像
		--name="Name" # 给容器指定一个名字 -d # 后台方式运行容器,并返回容器的id! 
		-i # 以交互模式运行容器,通过和 -t 一起使用 
		-t # 给容器重新分配一个终端,通常和 -i 一起使用 
		-P # 随机端口映射(大写) -p # 指定端口映射(小结),一般可以有四种写法 
			ip:hostPort:containerPort 
			ip::containerPort 
			hostPort:containerPort (常用) 
			containerPort
		docker run -it -d --name mycentos  centos /bin/bash # 启动centos,且分配一个终端
		
exit # 退出容器
ctrl+P+Q # 容器不停止退出

docker ps # 列出正在运行的容器
		-a # 列出正在运行的容器 + 历史运行过的容器 
		-l # 显示最近创建的1个容器 
		-n=? # 显示最近n个创建的容器 
		-q # 只显示容器id
		
docker rm 容器id # 删除指定容器 无法删除正在运行的容器就 -f
docker rm -f $(docker ps -a -q) # 删除所有容器

docker start/restart/stop/kill    (容器id or 容器名)

docker run -d centos # 启动centos,使用后台方式启动,但没有前台进程,会自动自杀
# 这里表示永不停歇的打印语句,这样有了进程这个容器就不会自动关闭 docker ps 才能查得到
docker run -d centos /bin/bash -c "while true;do echo kuangshen;sleep 1;done"

docker logs -f -t --tail 10  3c5bb777ad9c # 获取容器的日志 (此时容器中没有做任何事,所以日志为空)
		-f : 跟踪日志输出
		--since :显示某个开始时间的所有日志
		-t : 显示时间戳
		--tail 8   仅列出最新8条容器日志
		docker logs -tf --tail 10  39455ce3cd05 # 查看前十条日志
		
docker inspect 容器id # 查看容器/镜像的元数据(内容很多很多。。。)

docker top 容器id # 查看容器中运行的进程信息
UID 	PID 	PPID 	C 	STIME 	TTY 	TIME 	CMD 
root 	27437 	27421 	0 	16:43 	? 	00:00:00 	/bin/sh -c ....

docker exec -it 容器id /bin/bash # 进入正在运行的容器
docker attach 容器id # 也是进入容器
# exec 较强大,是在容器中打开新的终端,并且可以启动新的进程,追加ls 可以直接不进入cmd列出所有文件
docker exec -it 34hv34h234 ls -l /tmp
# attach 直接进入容器启动命令的终端,不会启动新的进程

docker cp 934e0a1c190c:容器路径  主机路径    # 从容器中复制文件到主机

docker stats id # 容器的cpu内存和网络状态

docker tag diytomcat diy2  # 给diytomcat 增加tag,其实时新生成一个image,命名为diy2

# 注意:commit的时候,容器的名字不能有大写,否则报错:invalid reference format 
docker commit -a="vaynexiao" -m="no tomcat docs" 容器id tomcat02:1.1

docker run -it --rm tomcat:9.0 # --rm:容器启动成功并退出以后容器就自动移除,一般测试用
docker run -d -p 8081:8080 --name tomcat9 tomcat # -P 大写p随机分配ip

docker run -d --name mynginx -p 81:80 nginx
curl localhost:81

# 发布镜像到Dockerhub
docker login -u [email protected]
docker push name:tag

# 部署Mysql 同步数据
docker run -d -p 3307:3306 -v /home/ceshi/mysql/conf:/etc/mysql/conf.d -v /home/ceshi/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
mysql -uroot -p

在这里插入图片描述

部署ES

docker run -d --name myes -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2 # es装了后很占内存

docker run -d --name minEs -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

curl localhost:9200

可视化portainer

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

Portainer是Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷
的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和
服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管
理的全部需求。
如果仅有一个docker宿主机,则可使用单机版运行,Portainer单机版运行十分简单,只需要一条语句即
可启动容器,来管理该机器上的docker镜像、容器等数据。

curl localhost:9001

镜像加载原理

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,
它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系
统下(unite several directories into a single virtual filesystem)。
Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,
基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件
系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, 
Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。
这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。
当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已
由bootfs转交给内核,此时系统也会卸载bootfs。 rootfs (root file system) ,
在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标
准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直
接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, 
bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

数据卷(时刻同步)

数据卷

# 主机和容器都会自动新建不存在的文件夹 (volumes)
docker run -it -v /home/ceshi:/home centos /bin/bash
# ro只读 rw读写 
# ro时:只能同步主机的文件查看,并不能vim
# 注意:如果访问出现了 cannot open directory: Permission denied
# 解决办法:在挂载目录后多加一个 --privileged=true参数即可
docker run -it -v /home/ceshi:/home:ro --privileged=true centos /bin/bash
# 查看Mounts挂载信息
docker inspect 09e7b35c4234
        "Mounts": [
            {
    
    
                "Type": "bind",
                "Source": "/home/ceshi", # 主机位置
                "Destination": "/home", # 容器位置
                "Mode": "",
                "RW": true, # 可读写
                "Propagation": "rprivate"
            }
        ],

数据卷容器

# 制作一个image 挂载目录设置为v1 v2,之后只有挂载目录中文件才会自动同步
FROM centos
# 容器的v1 v2目录,主机上会在对应默认地址生成目录
# /var/lib/docker/volumes/442f7aaf3f84b6b41d4cffc4e3e71a84ab1b89fe9dbe70b76e99f851ff1bf66e/_data
VOLUME ["/v1","/v2"] 
CMD echo "-------end------" 
CMD /bin/bash

docker run -it --name v1  mycentos

# 多创建几个容器,互相之间错综复杂的挂载
# 此时 v1 v2 v3 v4 都是互通的,不管哪个新建文件都会同步,删除其中一个,也不会影响其他3个的同步功能
# 当然只是之前挂载过得文件夹 v1 v2
docker run -it --name v2 --volumes-from v1 mycentos
docker run -it --name v3 --volumes-from v1 mycentos
docker run -it --name v4 --volumes-from v2 mycentos

匿名挂载 具名挂载

挂载一个本地Linux主机的目录到容器中去,实现容器内数据与本地互通

# 匿名挂载 
-v 容器内路径 
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 具名挂载 
-v 卷名:/容器内路径 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx

# 指定宿主机的挂载路径
不管匿名还是具名挂载,都会挂载到宿主机的默认路径下,也可以指定宿主机的挂载路径
-v /宿主机路径:/容器内路径

# 查看挂载的路径 
docker volume inspect nginxconfig 
[ 
	{
    
     
		"CreatedAt": "2020-05-13T17:23:00+08:00", 
		"Driver": "local", 
		"Labels": null, 
		"Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data", 
		"Name": "nginxconfig", 
		"Options": null, 
		"Scope": "local" 
	} 
]

# 怎么判断挂载的是卷名而不是本机目录名? 
不是/开始就是卷名,是/开始就是目录名 

# 改变文件的读写权限 
# ro: readonly 
# rw: readwrite 
# 指定容器对我们挂载出来的内容的读写权限 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx 
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

Dockerfile

1、指令必须为大写且后面要跟随至少一个参数
2、指令顺序执行
3、# 表示注释
4、每条指令都会创建新的镜像层,并提交镜像

FROM 		# 基础镜像,当前新镜像是基于哪个镜像的 
MAINTAINER	# 镜像维护者的姓名混合邮箱地址 
RUN 		# 容器构建时需要运行的命令 
EXPOSE 		# 当前容器对外保留出的端口 
WORKDIR 	# 指定在创建容器后,终端默认登录的进来工作目录,落脚点 
ENV 		# 用来在构建镜像过程中设置环境变量 
ADD 		# 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
LABEL       # 
COPY 		# 类似ADD,仅仅拷贝文件和目录到镜像中 
VOLUME 		# 容器数据卷,用于数据保存和持久化工作 
CMD 		# 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最后一个生效 
ENTRYPOINT 	# 指定一个容器启动时要运行的命令,和CMD一样 
ONBUILD 	# 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的 ONBUILD被触发
			# FROM mycentos # 继承mycentos镜像
实战:自己制作centos
需求:初始centos系统没有vim 没有ifconfig,

FROM centos 
MAINTAINER vaynexiao<[email protected]> 
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,固定的文件名
docker build -f Dockerfile -t mycentos:2.0 .  
docker history 镜像名字 # 列出镜像的生成容器历史记录
docker run -it --name rq-centos0.1  mycentos:2.0

CMD ENTRYPOINT

两个命令都是指定一个容器启动时要运行的命令
CMD:Dockerfile 中可以有多个CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换!
ENTRYPOINT:docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合!

FROM centos
CMD [ "ls", "-a" ]
CDM ls -l

docker build -f dockerfile-cmd-test -t cmdtest .
docker run 554bc6952657 # 会顺便执行ls -a
docker run cmdtest -l # 此时会报错

制作Tomcat镜像

mkdir -p /home/build/tomcat
cd /home/build/tomcat
# 将 JDK 和 tomcat 安装的压缩包拷贝进上一步目录
jdk-8u271-linux-x64.tar.gz
apache-tomcat-9.0.34.tar.gz
touch read.txt

FROM centos 
MAINTAINER vaynexiao<[email protected]> 
COPY read.txt /usr/local/readme.txt # 把宿主机当前上下文的read.txt拷贝到容器/usr/local/路径下 
ADD jdk-8u271-linux-x64.tar.gz /usr/local/ # 把java与tomcat添加到容器中 
ADD apache-tomcat-9.0.34.tar.gz /usr/local/ 
RUN yum -y install vim # 安装vim编辑器  
ENV MYPATH /usr/local 
WORKDIR $MYPATH # 设置工作访问时候的WORKDIR路径,登录落脚点 
# 配置java与tomcat环境变量 
ENV JAVA_HOME /usr/local/jdk1.8.0_271
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.34 
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.34 
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin 
# 容器运行时监听的端口 
EXPOSE 8080 
# 启动时运行tomcat 
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.34/bin/startup.sh" ] 
# CMD ["/usr/local/apache-tomcat-9.0.34/bin/catalina.sh","run"] 
CMD /usr/local/apache-tomcat-9.0.34/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.34/bin/logs/catalina.out

docker build -t diytomcat .

docker run -d -p 8081:8080 --name rongqi-diytomcat2 -v /home/build/tomcat/test:/usr/local/apache-tomcat-9.0.34/webapps/test -v /home/build/tomcat/tomcat9logs/:/usr/local/apache-tomcat-9.0.34/logs --privileged=true diytomcat

curl localhost:8081

在/home/build/tomcat/test下
vim index.jsp

重启访问
http://39.99.164.237:8081/
curl localhost:8081/test/index.jsp

发布镜像到aliyun

# 创建命名空间 - 创建仓库(选择本地仓库)
docker login --username=[email protected] registry.cn-zhangjiakou.aliyuncs.com # 这里星号要重写清楚
# registry.cn-zhangjiakou.aliyuncs.com/vaynxiao-docker/for-docker 是阿里固定的
docker tag [ImageId] registry.cn-zhangjiakou.aliyuncs.com/vaynxiao-docker/for-docker:[tag]
docker push registry.cn-zhangjiakou.aliyuncs.com/vaynxiao-docker/for-docker:[tag]
# 速度极慢啊啊。。。

Docker网络

通信原理

docker run -d -P --name tomcat01 tomcat #  容器1 tomcat01
docker run -d -P --name tomcat02 tomcat #  容器2 tomcat02
docker exec -it tomcat01 ip addr
docker可以ping通自己的容器

每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡,使用了veth-pair技术!

docker exec -it tomcat01 ip addr # 成对出现 514-515 516-517 这就是evth-pair技术
docker exec -it tomcat02 ip addr

[root@iZ8vb9yzkqg41m0qu0ix71Z]# ip addr 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3e:0d:5f:1d brd ff:ff:ff:ff:ff:ff
    inet 172.26.207.31/20 brd 172.26.207.255 scope global dynamic eth0
       valid_lft 315018187sec preferred_lft 315018187sec
515: veth180d89c@if514: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 96:f6:e4:e8:e0:56 brd ff:ff:ff:ff:ff:ff link-netnsid 0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:7a:5f:c7:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
517: vethbfc12c4@if516: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether a2:c0:7d:14:ac:29 brd ff:ff:ff:ff:ff:ff link-netnsid 1


[root@iZ8vb9yzkqg41m0qu0ix71Z]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
514: eth0@if515: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

[root@iZ8vb9yzkqg41m0qu0ix71Z]# docker exec -it tomcat02 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
516: eth0@if517: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# evth-pair负责连接容器与docker,所以容器之间也可以ping通

00000000.00000000.00000000.00000000
255.255.0.1/16 # 域  前16位是网段
255*255 - 0.0.0.0 - 255.255.255.255 = 6w多

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并
让他们彼此联通(这样一对接口叫veth pair),所以局域网传输速度极快。

在这里插入图片描述

–Link (过时)

# --link 过时 不推荐使用 使用自定义网络

微服务中通信需要设置ip:port,每次docker启动的服务ip自动分配,会变化,通过ip连接肯定不可行
[root@kuangshen ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known  # 发现ping不通

[root@kuangshen ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
a3a4a17a2b707766ad4f2bb967ce1d94f658cd4cccef3bb8707395cdc71fa1e7

--link是单向连接,用tomcat2是无法ping通tomcat3的

docker network ls # docker0的网络是bridge
docker inspect images-id/container-id # 查看网络信息

原理是什么呢?我们进入tomcat03中查看下host配置文件 (注意是设置了tomcat03 --link tomcat02)
[root@kuangshen ~]# 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.18.0.3 tomcat02 b80da266a3ad  # 发现tomcat2直接被写在这里
172.18.0.4 a3a4a17a2b70
# 所以这里其实就是配置了一个 hosts 地址而已!
# 原因:--link的时候,直接把需要link的主机的域名和ip直接配置到了hosts文件中了。

自定义网络

查看一个具体的网络的详细信息
docker network inspect 4eb2182ac4b2 # docker network inspect mynet

docker rm -f $(docker ps -aq)  删除原来的所有容器

# 默认我们不配置网络,也就相当于默认值 --net bridge 使用的docker0
docker run -d -P --name tomcat01 --net bridge tomcat

# docker0网络的特点
1.它是默认的
2.域名访问不通
3.--link 域名通了,但是删了又不行

# 自定义创建的默认default "bridge"
# 自定义创建一个网络网络
[root@kuangshen ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
09bd09d8d3a6b33e6d19f49643dab551e5a45818baf4d5328aa7320c6dcfc236

docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
# 同在一个网段,自然可以通信,此时通过容器面也可以通信
docker exec -it tomcat-net-01 ping tomcat-net-02

网络联通

在这里插入图片描述

# 要跨网络操作,比如tomcat1想要连接tomcat-net-01,先要加入mynet网络
docker network connect mynet tomcat01 # docker network connect net container
docker network inspect mynet # 发现tomcat01被加入mybet,tomcat01拥有了双ip

Redis集群

在这里插入图片描述

# 高可用 集群,master挂了,slave自动顶上(不知道slave顶不顶得住)

# 创建网卡
docker network create redis --subnet 172.38.0.0/16

# 通过脚本创建六个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
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个redis容器
docker run -p ${port}:6379 -p ${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server
/etc/redis/redis.conf; \

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

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

docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server

docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server

docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server

# 进入一个redis,注意这里是 sh命令
docker exec -it redis-1 /bin/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
## ???[ERR] Node 172.38.0.11:6379 is not configured as a cluster node.
cluster-enabled yes
appendonly yes
???这两个已经设置了

# 连接集群 (要在/data下执行,即docker exec进入的路径)
redis-cli -c

# 进入某一个redis 查看集群信息
cluster info

# 进入某一个redis 查看节点
cluster nodes # 会发现自动分配3主3从

set a b 
# 假设被存入3号容器,然后docker stop id
# 然后再次get a,发现从3号容器的slave容器中获取值
# 查看节点
3号 fail
slave 成为 master

部署Springboot微服务项目

# springboot 只有/hello请求 得到jar

# 1,IDEA安装插件docker 为了写Dockerfile语法高亮,
在项目下编写 Dockerfile 文件,将打包好的jar包拷贝到Dockerfile同级目录
FROM java:8
# 服务器只有dockerfile和jar在同级目录
COPY *.jar /app.jar
CMD ["--server.port=8080"]
# 指定容器内要暴露的端口
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

# 2、编写Dockerfile
[root@kuangshen]# pwd
/home/idea
[root@kuangshen]# ll     ftp上传至jar + Dockerfile
total 17228
-rw-r--r-- 1 root root 17634294 May 14 12:33 demo-0.0.1-SNAPSHOT.jar
-rw-r--r-- 1 root root    207 May 14 12:32 Dockerfile

docker build -t idea-ks .  # 构建镜像

docker images # 查看镜像

docker run -d -P --name rq-idea-ks idea-ks # 运行
[root@kuangshen ~]# docker ps
CONTAINER ID    IMAGE           PORTS                       NAMES
2366c960ba99    idea-ks         0.0.0.0:32779->8080/tcp     rq-idea-ks1

# 测试访问
[root@kuangshen ~]# curl localhost:32779
[root@kuangshen ~]# curl localhost:32779/hello

猜你喜欢

转载自blog.csdn.net/vayne_xiao/article/details/110563108
今日推荐