狂神说JAVA的哔哩哔哩主页

文章目录

  • 概念
  • 一、基础环境
  • 二、最新版19.03安装
  • 三、Docker常用命令
      • 帮助命令
      • 镜像命令
      • 容器命令
      • 常用其他命令
        • 后台启动容器
        • 查看日志
        • 查看容器中进程信息
        • 查看容器元数据
        • 进入当前正在运行的容器
        • 从容器内拷贝文件到主机
        • 查看镜像、容器、数据卷所占用的空间
  • 四、测试docker镜像运行各种环境
      • 1. 测试运行一个nginx容器,端口映射到主机的3344
      • 2. 测试运行一个tomcat的容器,端口映射到主机的3355
      • 3. 测试部署一套elasticsearch+kibana的日志监控的容器
  • 五、Docker可视化面板
  • 六、Docker镜像讲解
    • 1. Docker镜像加载原理
    • 2. Docker commit定制镜像
  • 七、Dokcer数据卷
    • 1. 使用数据卷
    • 2. 安装MySQL
    • 3. 容器数据持久化
    • 4. 具名和匿名挂载
    • 5. Dockerfile的基础操作
    • 6. 数据卷容器
  • 九、Dockerfile
    • 1. Dockerfile介绍
    • 2. Dockerfile构建
    • 3. Dockerfile的指令
    • 4. 自己写一个Dockerfile文件构建镜像
    • 5. RUN 执行命令
    • 6. CMD 和 ENTRYPOINT 区别
    • 7. 测试 Tomcat镜像(ADD COPY)
      • 1. 准备镜像文件,tomcat压缩包,jdk的压缩包
      • 2. 编写dockerfile文件
      • 3. 构建镜像
      • 4. 运行此镜像的容器
      • 5. 进入tomcat容器中查看
      • 6. 上传一个web站点的压缩包到test目录下进行测试
    • 8. 发布镜像到DockerHub
    • 9. 发布镜像到阿里云镜像仓库
    • 10. 发布镜像到私有仓库
  • 十、Docker网络
    • 1. Bridge模式
      • --link 容器互联
      • 自定义网络
    • 2. Host 模式
    • 3. Container 模式
    • 4. None模式
    • 5. 网络连通
    • 6. 部署一个Redis集群
  • 十一、 Docker Compose
  • 十二、 Docker Swarm

Docker 容器本质上是宿主机上的一个进程。Docker 通过 namespace 实现了资源隔离,通过 cgroups 实现了资源的限制,通过写时复制机制(copy-on-write)实现了高效的文件操作。

Docker有五个命名空间:进程、网络、挂载、宿主和共享内存,为了隔离有问题的应用,Docker运用Namespace将进程隔离,为进程或进程组创建已隔离的运行空间,为进程提供不同的命名空间视图。这样,每一个隔离出来的进程组,对外就表现为一个container(容器)。需要注意的是,Docker让用户误以为自己占据了全部资源,但这并不是”虚拟机”。

概念

Docker 中的三个概念:镜像,容器,仓库

镜像(image):

Docker 镜像就是一个只读的模板,镜像可以用来创建 Docker 容器。Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。镜像是一种文件结构。Dockerfile中的每条命令都会在文件系统中创建一个新的层次结构,文件系统在这些层次上构建起来,镜像就构建于这些联合的文件系统之上。Docker官方网站专门有一个页面来存储所有可用的镜像,网址是:index.docker.io。

例如:一个镜像可以包含一个完整的CentOS操作系统环境,里面仅安装了Nginx或用户需要的其他应用程序。镜像可以用来创建Docker容器。

容器( Container):

容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境,Docker 利用容器来运行应用。镜像是只读的,容器在启动的时候创建一层可写层作为最上层。

注意:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。

仓库:

仓库是集中存放镜像文件的场所,有时候把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。仓库注册服务器(Registry)上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。目前,最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

Docker仓库用来保存我们的images,当我们创建了自己的image之后我们就可以使用push命令将它上传到公有或者私有仓库,这样下次要在另外一台机器上使用这个image时候,只需要从仓库上pull下来就可以了。

注意:Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。

一、基础环境

基础配置

NAT
192.168.0.10	K8s-master
192.168.0.20	K8s-node01
192.168.0.30	K8s-node02LAN
172.16.0.10	K8s-master
172.16.0.20	K8s-node01
172.16.0.30	K8s-node02

基础优化配置三台环境

echo 'net.ipv4.ip_forward=1 ' >>/etc/sysctl.conf 
echo 'net.ipv4.tcp_tw_recycle=1 ' >>/etc/sysctl.conf
echo 'net.ipv4.tcp_tw_reuse=1 ' >>/etc/sysctl.conf 
sysctl -p
chmod +x /etc/rc.d/rc.local
yum install -y mlocate lrzsz tree vim nc nmap wget bash-completion bash-completion-extras htop iotop iftop lsof net-tools sysstat unzip bc psmisc ntpdate wc telnet-server bind-utils sshpass

配置yum源

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

在master节点上分发ssh秘钥

[root@K8s-master ~]# cat fenfa_pub.sh 
#!/bin/bash
ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''
for ip in 20 30 
dosshpass -p123456 ssh-copy-id -o StrictHostKeyChecking=no 172.16.0.$ip
donesh fenfa_pub.sh

在master节点上为其他node节点分发hosts文件

[root@k8s-master ~]# cat /etc/hosts
172.16.0.10	k8s-master
172.16.0.20	k8s-node01
172.16.0.30	K8s-node02for ip in 20 30 ;do scp -rp /etc/hosts 172.16.0.$ip:/etc/hosts ;done

二、最新版19.03安装

https://docs.docker.com/engine/install/centos/

注意:确保自己的linux系统内核版本高于3.10,并且系统是64位,才能体验Docker。

[root@k8s-master ~]# uname -r
3.10.0-957.el7.x86_64

官方帮助文档:

较旧的Docker版本称为dockerdocker-engine。如果已安装这些程序,请卸载它们以及相关的依赖项。

# 1. 卸载旧版本
yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine# 2. 使用存储库安装
yum install -y yum-utils# 3. 设置镜像仓库(修改为国内源地址)
yum-config-manager \--add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 5. 更新索引
yum makecache fast# 4. 安装docker相关的依赖 默认最新版(docker-ce:社区版 ee:企业版)
yum install docker-ce docker-ce-cli containerd.io -y#5. 安装特定docker版本(先列出列出可用版本)
yum list docker-ce --showduplicates | sort -r
yum install docker-ce-19.03.9 docker-ce-cli-19.03.9 containerd.io# 6. 启动docker
systemctl start docker
systemctl enable docker# 7. 查看版本
[root@k8s-master ~]# docker --version
Docker version 19.03.11, build 42e35e61f3

配置docker镜像加速器

镜像加速器:阿里云加速器,daocloud加速器,中科大加速器

Docker 中国官方镜像加速:https://registry.docker-cn.com

mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://registry.docker-cn.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker

卸载docker

# 1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io# 2. 删除资源(默认工作路径)
rm -rf /var/lib/docker

ansible命令部署多台docker环境(需要配置ssh免秘钥)

# 1. 安装ansible
yum install ansible -y# 2. 添加hosts文件列表(所有节点的IP地址)
[root@k8s-master ~]# vim /etc/ansible/hosts
...
[master]
172.16.0.10
[node]
172.16.0.20
172.16.0.30# 3. 测试连通性
[root@k8s-master ~]# ansible all -a 'hostname'
172.16.0.20 | CHANGED | rc=0 >>
k8s-node01
172.16.0.30 | CHANGED | rc=0 >>
k8s-node02
172.16.0.10 | CHANGED | rc=0 >>
k8s-master# 3.卸载旧版本(没有写playbook文件)
ansible all -m yum -a 'name=docker,docker-client,docker-client-latest.docker-common,docker-latest,docker-latest-logrotate,docker-logrotate,docker-engine state=absent'
# 4. 安装yum-utils
ansible all -m yum -a 'name=yum-utils state=installed'
# 5. 设置国内镜像仓库
ansible all -m shell -a 'yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo'
# 6. 更新yum
ansible all -m shell -a 'yum makecache fast'
# 7. 安装docker相关的依赖
ansible all -m yum -a 'name=docker-ce,docker-ce-cli,containerd.io state=installed'
# 8. 启动docker
ansible all -m service -a 'name=docker state=started enabled=yes'

三、Docker常用命令

帮助命令

官方命令文档

docker version		#显示docker版本信息
docker info				#显示docker系统信息,包括镜像和容器的数量
docker --help			#帮助

镜像命令

https://docs.docker.com/engine/reference/commandline/images/

[root@openvpn ~]# docker images
REPOSITORY          TAG     IMAGE ID      CREATED       SIZE
kylemanna/openvpn   2.4  c504c01ae011   2 years ago   15.6MB#解释
REPOSITORY  镜像的仓库源
TAG         镜像的标签 
IMAGE ID    镜像的id         
CREATED     镜像的创建时间 
SIZE        镜像的大小#可选参数
-a --all		#列出所有镜像
-q --quiet	#只显示镜像ID

搜索镜像命令

https://docs.docker.com/engine/reference/commandline/search/

[root@k8s-master ~]# docker search mysql --filter=stars=5000
NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql               MySQL is a widely used, open-source relation…   9636                [OK]    #可选参数
--filter=stars=5000		#显示至少x个星标的

下载镜像命令

https://docs.docker.com/engine/reference/commandline/pull/

#下载镜像 docker pull [镜像名:tag]
[root@k8s-master ~]# docker pull mysql
Using default tag: latest	#如果不写tag,默认下载latest
latest: Pulling from library/mysql
8559a31e96f4: Pull complete #分层下载,docker image的核心 联合文件系统
d51ce1c2e575: Pull complete 
c2344adc4858: Pull complete 
fcf3ceff18fc: Pull complete 
16da0c38dc5b: Pull complete 
b905d1797e97: Pull complete 
4b50d1c6b05c: Pull complete 
c75914a65ca2: Pull complete 
1ae8042bdd09: Pull complete 
453ac13c00a3: Pull complete 
9e680cd72f08: Pull complete 
a6b5dc864b6c: Pull complete 
Digest: sha256:8b7b328a7ff6de46ef96bcf83af048cb00a1c86282bfca0cb119c84568b4caf6
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest	#真实地址#等同的命令
docker pull mysql
docker pull docker.io/library/mysql:latest#通过tag下载
[root@k8s-master ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
8559a31e96f4: Already exists 	#已下载的分层跳过,直接下载修改的内容
d51ce1c2e575: Already exists 
c2344adc4858: Already exists 
fcf3ceff18fc: Already exists 
16da0c38dc5b: Already exists 
b905d1797e97: Already exists 
4b50d1c6b05c: Already exists 
d85174a87144: Pull complete 
a4ad33703fa8: Pull complete 
f7a5433ce20d: Pull complete 
3dcd2a278b4a: Pull complete 
Digest: sha256:32f9d9a069f7a735e28fd44ea944d53c61f990ba71460c5c183e610854ca4854
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

删除镜像命令

#删除镜像
docker rmi -f [镜像id] [镜像id]-f	强制删除图像#删除所有镜像
docker rmi `docker images -qa`

导出镜像

# 导出镜像
docker image save centos -o docker-centos7.6.tar.gz

导入镜像

# 导入镜像
docker load -i docker-centos7.6.tar.gz

容器命令

说明:有了镜像才可以创建容器,在linux里 下载一个centos的镜像来测试

[root@k8s-master ~]# docker pull centos	

新建容器并启动

docker run [参数] image#参数说明
--name='Name' 区分容器
-d						后台方式运行
-it						使用交互方式运行,进入容器查看内容
-p [小写]			 指定容器的端口 -p 8080:8080-p ip:主机端口:容器端口-p 主机端口:容器端口-p 容器端口
-P [大写]			 随机指定端口
-rm						容器退出后随之将其删除#启动并进入容器
[root@k8s-master ~]# docker run -it centos:latest  /bin/bash
[root@f17bd1e56cbf /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr#从容器中退回主机
[root@f17bd1e56cbf /]# exit
exit
[root@k8s-master ~]#

列出所有的运行的容器

#docker ps 命令
-a 		#列出当前所有的容器
-q		#显示容器的编号
-n=1	#显示最近创建的容器[root@k8s-master /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@k8s-master /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
f17bd1e56cbf        centos:latest       "/bin/bash"         6 minutes ago       Exited (0) 3 minutes ago                       exciting_benz

退出容器

exit				#直接容器停止并退出
ctrl +P +Q	#容器不停止退出[root@8df0a450ef49 /]# #输入ctrl+PQ
[root@8df0a450ef49 /]# read escape sequence
[root@k8s-master /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8df0a450ef49        centos              "/bin/bash"         48 seconds ago      Up 48 seconds                           elegant_nash

删除容器

docker rm 容器id								#删除指定的容器,不能正在删除正在运行的容器
docker rm -f $(docker ps -aq)  	#删除所有容器
docker ps -aq|xargs docker rm		#删除所有容器

启动和停止容器的操作

docker start 			#启动容器
docker restart		#重启容器
docker stop				#关闭当前运行的容器
docker kill				#强制关闭当前容器
docker stats 			#容器占用内存状态

常用其他命令

后台启动容器

#问题!
#命令 docker run -d [镜像名] 启动容器失败
[root@k8s-master /]# docker run -d centos
045d6e51f4ebf39aec13bfe19172ceb34081bd69921108f684cfc879bc58ab29#docker ps 会发现centos停止了
[root@k8s-master /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
045d6e51f4eb        centos              "/bin/bash"         7 seconds ago       Exited (0) 6 seconds ago                       optimistic_benz#常见的坑,docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止

查看日志

https://docs.docker.com/engine/reference/commandline/logs/

#运行一个容器,会发现没有日志
docker logs -f -t --tail 10 [容器id]-f 			#跟踪日志输出
-t			#显示时间戳
--tail	#从日志末尾开始显示的行数#编写一个shell脚本运行容器
"while true;do echo 666666;sleep 1;done"
[root@k8s-master /]# docker run -d centos /bin/sh -c "while true;do echo 666666;sleep 1;done"
d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e
[root@k8s-master /]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
d297ff12a815        centos              "/bin/sh -c 'while t…"   2 seconds ago       Up 1 second                             angry_ardinghelli#显示日志
[root@k8s-master /]# docker logs -f -t --tail 5 d297ff12a815
2020-06-18T09:38:26.352615139Z 666666
2020-06-18T09:38:27.357596179Z 666666
2020-06-18T09:38:28.363849798Z 666666
2020-06-18T09:38:29.369256113Z 666666
2020-06-18T09:38:30.377091746Z 666666

查看容器中进程信息

# docker top [容器id]
[root@k8s-master /]# docker top 480d8e4936dc
UID      PID      PPID    C      STIME    TTY         TIME      	CMD
root    12812     12794   0      17:42    pts/0      00:00:00   /bin/bash

查看容器元数据

# docker inspect [容器id][root@k8s-master /]# docker inspect d297ff12a815
[{"Id": "d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e","Created": "2020-06-18T09:37:38.560647732Z","Path": "/bin/sh","Args": ["-c","while true;do echo 666666;sleep 1;done"],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 12246,"ExitCode": 0,"Error": "","StartedAt": "2020-06-18T09:37:39.066548855Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:831691599b88ad6cc2a4abbd0e89661a121aff14cfa289ad840fd3946f274f1f","ResolvConfPath": "/var/lib/docker/containers/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e/resolv.conf","HostnamePath": "/var/lib/docker/containers/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e/hostname","HostsPath": "/var/lib/docker/containers/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e/hosts","LogPath": "/var/lib/docker/containers/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e/d297ff12a815e8c1dd86ad951c30caca389ec5e854b6948c8b93d0e26ed7e10e-json.log","Name": "/angry_ardinghelli","RestartCount": 0,"Driver": "overlay2","Platform": "linux","MountLabel": "","ProcessLabel": "","AppArmorProfile": "","ExecIDs": null,"HostConfig": {"Binds": null,"ContainerIDFile": "","LogConfig": {"Type": "json-file","Config": {}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0},"AutoRemove": false,"VolumeDriver": "","VolumesFrom": null,"CapAdd": null,"CapDrop": null,"Capabilities": null,"Dns": [],"DnsOptions": [],"DnsSearch": [],"ExtraHosts": null,"GroupAdd": null,"IpcMode": "private","Cgroup": "","Links": null,"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": false,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "","UsernsMode": "","ShmSize": 67108864,"Runtime": "runc","ConsoleSize": [0,0],"Isolation": "","CpuShares": 0,"Memory": 0,"NanoCpus": 0,"CgroupParent": "","BlkioWeight": 0,"BlkioWeightDevice": [],"BlkioDeviceReadBps": null,"BlkioDeviceWriteBps": null,"BlkioDeviceReadIOps": null,"BlkioDeviceWriteIOps": null,"CpuPeriod": 0,"CpuQuota": 0,"CpuRealtimePeriod": 0,"CpuRealtimeRuntime": 0,"CpusetCpus": "","CpusetMems": "","Devices": [],"DeviceCgroupRules": null,"DeviceRequests": null,"KernelMemory": 0,"KernelMemoryTCP": 0,"MemoryReservation": 0,"MemorySwap": 0,"MemorySwappiness": null,"OomKillDisable": false,"PidsLimit": null,"Ulimits": null,"CpuCount": 0,"CpuPercent": 0,"IOMaximumIOps": 0,"IOMaximumBandwidth": 0,"MaskedPaths": ["/proc/asound","/proc/acpi","/proc/kcore","/proc/keys","/proc/latency_stats","/proc/timer_list","/proc/timer_stats","/proc/sched_debug","/proc/scsi","/sys/firmware"],"ReadonlyPaths": ["/proc/bus","/proc/fs","/proc/irq","/proc/sys","/proc/sysrq-trigger"]},"GraphDriver": {"Data": {"LowerDir": "/var/lib/docker/overlay2/262154243dfb5fcc88ee7ebc33f14eb633ab80762c3c590ae6dd47963fa9c258-init/diff:/var/lib/docker/overlay2/c136121eb67e6c71677589843a6b4a68655638d12f4c79ce634d224b7239228e/diff","MergedDir": "/var/lib/docker/overlay2/262154243dfb5fcc88ee7ebc33f14eb633ab80762c3c590ae6dd47963fa9c258/merged","UpperDir": "/var/lib/docker/overlay2/262154243dfb5fcc88ee7ebc33f14eb633ab80762c3c590ae6dd47963fa9c258/diff","WorkDir": "/var/lib/docker/overlay2/262154243dfb5fcc88ee7ebc33f14eb633ab80762c3c590ae6dd47963fa9c258/work"},"Name": "overlay2"},"Mounts": [],"Config": {"Hostname": "d297ff12a815","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/sh","-c","while true;do echo 666666;sleep 1;done"],"Image": "centos","Volumes": null,"WorkingDir": "","Entrypoint": null,"OnBuild": null,"Labels": {"org.label-schema.build-date": "20200611","org.label-schema.license": "GPLv2","org.label-schema.name": "CentOS Base Image","org.label-schema.schema-version": "1.0","org.label-schema.vendor": "CentOS"}},"NetworkSettings": {"Bridge": "","SandboxID": "536bd691e3316eca9f9ad9902a9cfa7b0b37df0a384dc617a87453355a17fea0","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/536bd691e331","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "4e4b82daee88df3a954ce8b905ba24c894858668d28211d47e0617641911c6ae","Gateway": "172.17.0.1","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"IPAddress": "172.17.0.2","IPPrefixLen": 16,"IPv6Gateway": "","MacAddress": "02:42:ac:11:00:02","Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "35ca8cfcee1b97f050ae2e99c9f0c46b94009313ecb938325043f8d685cb93ba","EndpointID": "4e4b82daee88df3a954ce8b905ba24c894858668d28211d47e0617641911c6ae","Gateway": "172.17.0.1","IPAddress": "172.17.0.2","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:11:00:02","DriverOpts": null}}}}
]

进入当前正在运行的容器

# 通常容器都是使用后台方式运行的,需要进入容器,修改一些配置#方式一
#打开了新的终端,可以在里操作
docker exec -it [容器id] /bin/bash[root@k8s-master /]# docker exec -it f1b799deb1b5 /bin/bash
[root@f1b799deb1b5 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@f1b799deb1b5 /]# ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 09:56 pts/0    00:00:00 /bin/bash
root         14      0  0 09:57 pts/1    00:00:00 /bin/bash
root         28      1  0 09:57 pts/0    00:00:00 ps -ef#方式二
#进入容器当前正在执行的终端
docker attach [容器id][root@k8s-master ~]# docker  attach f1b799deb1b5
[root@f1b799deb1b5 /]# 

从容器内拷贝文件到主机

docker cp 容器id:容器内id 目的主机路径#进入容器创建一个文件
[root@k8s-master ~]# docker attach f1b799deb1b5
[root@f1b799deb1b5 /]# echo {a..z} >test.txt
[root@f1b799deb1b5 /]# cat /test.txt 
a b c d e f g h i j k l m n o p q r s t u v w x y z#将容器的文件拷贝到主机上
[root@k8s-master ~]# docker cp f1b799deb1b5:/test.txt /tmp/[root@k8s-master ~]# ls /tmp/test.txt 
/tmp/test.txt
[root@k8s-master ~]# cat /tmp/test.txt 
a b c d e f g h i j k l m n o p q r s t u v w x y z#拷贝是一个手动过程,之后使用 -v 卷的技术,可以实现自动同步;主机目录和容器目录同步

查看镜像、容器、数据卷所占用的空间

# docker system df[root@k8s-master ~]# docker system df
TYPE                TOTAL               ACTIVE           SIZE            RECLAIMABLE
Images              1                   1                215.3MB         0B (0%)
Containers          1                   0                   104B         104B (100%)
Local Volumes       2                   0                   0B           0B
Build Cache         0                   0                   0B           0B

四、测试docker镜像运行各种环境

1. 测试运行一个nginx容器,端口映射到主机的3344

[root@k8s-master ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
8559a31e96f4: Pull complete 
8d69e59170f7: Pull complete 
3f9f1ec1d262: Pull complete 
d1f5ff4f210d: Pull complete 
1e22bfa8652e: Pull complete 
Digest: sha256:21f32f6c08406306d822a0e6e8b7dc81f53f336570e852e25fbe1e3e3d0d0133
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest[root@k8s-master ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              831691599b88        2 days ago          215MB
nginx               latest              2622e6cca7eb        9 days ago          132MB[root@k8s-master ~]# docker run -d --name nginx01 -p 3344:80 nginx:latest 
145afc9f6eaa994b51d2c00bb28613bff2b1f9a48ea7f26a3c591bd40102cdd9[root@k8s-master ~]# curl -I 127.0.0.1:3344
HTTP/1.1 200 OK
Server: nginx/1.19.0
Date: Fri, 19 Jun 2020 03:13:22 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 May 2020 15:00:20 GMT
Connection: keep-alive
ETag: "5ecd2f04-264"
Accept-Ranges: bytes# 进入容器
[root@k8s-master ~]# docker exec -it nginx01 /bin/bash
root@145afc9f6eaa:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@145afc9f6eaa:/# cd /etc/nginx/
root@145afc9f6eaa:/etc/nginx# ls
conf.d		koi-utf  mime.types  nginx.conf   uwsgi_params
fastcgi_params	koi-win  modules     scgi_params  win-utf

2. 测试运行一个tomcat的容器,端口映射到主机的3355

https://hub.docker.com/_/tomcat

# 下载镜像再启动
docker pull tomcat
# 启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat# 访问此容器会报错404,是因为tomcat官网镜像没有webapps,镜像源把所有镜像不必要的都剔除了,默认是最小可运行环境# 进入容器,将默认的webapps.dist的内容拷贝一份到webapps目录下
[root@k8s-master ~]# docker exec -it tomcat01 /bin/bash
root@23e4e460879b:/usr/local/tomcat# cp -a webapps.dist/* webapps/# 再一次访问就成功了
[root@k8s-master ~]# curl -I 127.0.0.1:3355
HTTP/1.1 200 
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 19 Jun 2020 03:39:34 GMT

每次改动服务配置文件,都需要进入容器内部,十分麻烦,我们可以在容器外映射一个路径,达到在宿主机修改文件内容,容器内部就可以自动同步修改,就是数据卷的操作

3. 测试部署一套elasticsearch+kibana的日志监控的容器

https://hub.docker.com/_/elasticsearch

启动一台es容器

# es暴露的端口很多
# es十分耗内存
# es数据一般需要放置到安全目录挂载# 启动elasticsearch
[root@k8s-master ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2#访问
[root@k8s-master ~]# curl 127.0.0.1:9200
{"name" : "7426e97975a1","cluster_name" : "docker-cluster","cluster_uuid" : "aNGISnU9QZm3qQw9obQiPg","version" : {"number" : "7.6.2","build_flavor" : "default","build_type" : "docker","build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f","build_date" : "2020-03-26T06:34:37.794943Z","build_snapshot" : false,"lucene_version" : "8.4.0","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"
}

使用命令dcker stats查看es容器的内存占用情况太大

# 关闭刚刚启动的es容器,增加内存的限制,修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m"  elasticsearch:7.6.2

[root@k8s-master ~]# curl  127.0.0.1:9200
{"name" : "66fdfb9147aa","cluster_name" : "docker-cluster","cluster_uuid" : "7vONQG4HSjKXdtpMmEzbIg","version" : {"number" : "7.6.2","build_flavor" : "default","build_type" : "docker","build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f","build_date" : "2020-03-26T06:34:37.794943Z","build_snapshot" : false,"lucene_version" : "8.4.0","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search"
}

启动一台kibana容器


五、Docker可视化面板

# Portainer
基于Go,是一个轻量级的图形化界面管理工具,可轻松管理Docker主机。# Rancher
开源的企业级容器管理平台,Rancher提供了在生产环境中使用管理Docker和Kubernetes的全栈化容器部署与管理平台。(CICD)# cAdvisor
Google开发的容器监控工具, 会显示当前容器的资源使用情况,包括 CPU、内存、网络、文件系统等,显示容器列表。

启动一台portainer容器(不常用,测试学习)

[root@k8s-master ~]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

访问8088端口 http://192.168.0.10:8088

六、Docker镜像讲解

1. Docker镜像加载原理

UnionFS(联合文件系统)

下载镜像时看到的一层层的就是这个!

UnionFS(联合文件系统)

是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。UnionFS是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

2. Docker commit定制镜像

docker不建议再通过这种方式构建镜像;具体原因如下

手工创建,容易出错,效率低并且可重复性弱。

无法对镜像进行审计,存在安全隐患。

学习commit定制镜像的原因:

dockerfile构建镜像,底层也是docker commit一层一层构建新镜像的,学习的目的是更加深入地理解构建过程和镜像分层结构。

三个步骤

  • 运行容器

  • 修改容器

  • 将容器保存为新的镜像

# 第一步: 启动运行一个官方镜像的tomcat容器
[root@k8s-master ~]# docker run -it -d -p 8080:8080 --name tomcat02 tomcat
[root@k8s-master ~]# docker exec -it tomcat02 /bin/bash# 第二步: 修改内容,将默认的webapps.dist/下内容复制到webapps下
root@81fd44790b38:/usr/local/tomcat# cp -a webapps.dist/* webapps/# 第三步: commit提交
--a	#是指定修改的作者
--m	#是记录本次修改的内容
[root@k8s-master ~]# docker commit -a "lichenxing" -m "cp -a webapps.dist/* webapps/" tomcat02 tomcat02:V1.0
sha256:405a3c097a00380667ab5e3d4ed30458e5483cbb3182640c9275b2f82bc15f5d# 第四步: 查看提交的镜像
[root@k8s-master ~]# docker images
REPOSITORY        TAG              IMAGE ID            CREATED             SIZE
tomcat02          V1.0             405a3c097a00        34 seconds ago      652MB
tomcat            latest           2eb5a120304e        9 days ago          647MB

七、Dokcer数据卷

容器的持久化和同步操作!容器间也是可以数据共享的!

容器删除后,数据还在主机上保存。

1. 使用数据卷

# 方式一: 直接使用命令挂载 -v
docker run -it -v 主机目录:容器目录[root@k8s-master ~]# docker run -it -v /home/ceshi/:/home centos /bin/bash
[root@06b7f2dc16ec /]# ls /home/# 容器挂载的/home/ceshi目录自动生成
[root@k8s-master ~]# ll /home/
total 0
drwxr-xr-x. 2 root root  6 Jun 19 16:36 ceshi# 查看容器的详细信息(Mounts部分)
[root@k8s-master ~]# docker inspect 06b7f2dc16ec"Mounts": [{"Type": "bind","Source": "/home/ceshi",	# 主机内的地址"Destination": "/home",		# docker容器内的地址"Mode": "","RW": true,"Propagation": "rprivate"}],# 主机目录和容器目录都为空,在容器内添加文件
[root@06b7f2dc16ec /]# cd /home/
[root@06b7f2dc16ec home]# touch test.java# 在主机上查看,已经同步过来了
[root@k8s-master ~]# ll /home/ceshi/
total 0
-rw-r--r--. 1 root root 0 Jun 19 16:43 test.java# 在主机上追加文件内容
[root@k8s-master ~]# echo {a..z} > /home/ceshi/test.java# 在容器内查看文件
[root@06b7f2dc16ec home]# cat test.java
a b c d e f g h i j k l m n o p q r s t u v w x y z

修改只需要在主机本地修改即可,容器可以自动同步。

补充:

使用 --mount 标记可以指定挂载一个本地主机的目录到容器中去,如果使用mount时,宿主机中没有这个文件会报错,而不是像-v,没有这个文件也会自动创建。

# 挂载一个主机目录作为数据卷:(-v 和 --mount的对比)
docker run -d -P --name web \# -v /src/webapp:/opt/webapp \--mount type=bind,source=/src/webapp,target=/opt/webapp \training/webapp \python app.py上面的命令加载主机的 /src/webapp 目录到容器的 /opt/webapp目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错。# Docker 挂载主机目录的默认权限是 读写,用户也可以通过增加readonly指定为只读。
docker run -d -P --name web \# -v /src/webapp:/opt/webapp:ro \--mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \training/webapp \python app.py# 挂载一个本地主机文件作为数据卷:--mount标记也可以从主机挂载单个文件到容器中
docker run -it \# -v /root/.bash_history:/root/.bash_history \--mount type=bind,source=/root/.bash_history,target=/root/.bash_history \ubuntu:17.10 \bash# 这样就可以记录在容器输入过的命令了。
root@2affd44b4667:/# history
1  ls
2  history

2. 安装MySQL

https://hub.docker.com/_/mysql

# 下载mysql5.7的官方镜像
docker pull mysql:5.7# 运行一台mysql容器 (需要设置mysql密码; 映射配置文件和数据文件;通过官方镜像仓库查看启动容器的命令)
[root@k8s-master ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
0d709657652353d906f710118144ea401c6ce539c825abd2aa019e889278944c#查看主机映射目录
[root@k8s-master home]# ls 
ceshi  lcx  mysql
[root@k8s-master home]# cd mysql/
[root@k8s-master mysql]# ls
conf  data
[root@k8s-master mysql]# ls data/
auto.cnf    client-cert.pem  ibdata1      ibtmp1              private_key.pem  server-key.pem
ca-key.pem  client-key.pem   ib_logfile0  mysql               public_key.pem   sys
ca.pem      ib_buffer_pool   ib_logfile1  performance_schema  server-cert.pem

通过本地第三方工具 SQLyog登陆mysql容器


新建一个数据库 test

# 查看主机映射目录也已经同步了test库目录
[root@k8s-master mysql]# ls data/
auto.cnf         client-key.pem  ib_logfile1         private_key.pem  sys
ca-key.pem       ib_buffer_pool  ibtmp1              public_key.pem   test
ca.pem           ibdata1         mysql               server-cert.pem
client-cert.pem  ib_logfile0     performance_schema  server-key.pem

3. 容器数据持久化

# 将容器删除后,数据已经保留下来了
[root@k8s-master ~]# docker rm -f mysql01
mysql01[root@k8s-master mysql]# ls data/
auto.cnf         client-key.pem  ib_logfile1         private_key.pem  sys
ca-key.pem       ib_buffer_pool  ibtmp1              public_key.pem   test
ca.pem           ibdata1         mysql               server-cert.pem
client-cert.pem  ib_logfile0     performance_schema  server-key.pem

4. 具名和匿名挂载

匿名挂载:没有名字

# 启动一个nginx容器, 选择随机端口和随机挂载路径(只写了容器内的路径,没有写容器外的路径)
[root@k8s-master ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx:latest# 查看所有卷的情况(都是匿名卷,没有名字)
[root@k8s-master ~]# docker volume ls
DRIVER              VOLUME NAME
local               6350e9d05a6611859fd3de283d1ea41eb234fc8720ec2d7a415d343ebc4e8de4
local               a1b15cc90674c1d69f2f77e3b35543886d4f7ac40975f3dffe200df64e8e9b64
local               bd43717a0bbfebd513b69fafa7ec3824805136b9ed7afd57605bfd3fedfd5662
local               e8c6ff6336476cd8bbd65bee93e18ce1c073ab7901631d55312421f40fbde38d
local               f2ecc7f10858285cda52f3a87bcc5e845f0de90785c56235744c9380cb7872cf

具名挂载:拥有名字

# 再启动一个nginx容器 
[root@k8s-master ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx:latest 
c446916349eefb151bf29f8ab657458e16deee7a46d65a3afa72b75a0ea30612# 查看所有卷的情况(有名字为juming-nginx的卷)
[root@k8s-master ~]# docker volume ls
DRIVER              VOLUME NAME
local               6350e9d05a6611859fd3de283d1ea41eb234fc8720ec2d7a415d343ebc4e8de4
local               a1b15cc90674c1d69f2f77e3b35543886d4f7ac40975f3dffe200df64e8e9b64
local               bd43717a0bbfebd513b69fafa7ec3824805136b9ed7afd57605bfd3fedfd5662
local               e8c6ff6336476cd8bbd65bee93e18ce1c073ab7901631d55312421f40fbde38d
local               f2ecc7f10858285cda52f3a87bcc5e845f0de90785c56235744c9380cb7872cf
local               juming-nginx# 查看具名挂载卷的路径
[root@k8s-master ~]# docker volume inspect juming-nginx 
[{"CreatedAt": "2020-06-19T17:52:09+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data","Name": "juming-nginx","Options": null,"Scope": "local"}
]

所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx/_data

通过具名挂载可以方便的找到我们的卷,大多数情况在使用的是具名挂载

# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载?
-v 容器内路径						 #匿名挂载
-v 卷名:容器内路径					#具名挂载
-v /宿主机路径:容器内路径		#指定路径挂载

扩展:

# 通过 -v 容器内路径:ro/rw 改变读写权限
ro	readonly	#只读	
rw	readwrite	#可读可写# 一旦设置了容器的读写权限,容器对我们挂载出来的内容就会有了权限了。
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx:latest
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx:latest# ro 只要看到ro就说明此路径是只能通过宿主机来操作,容器内部是无法操作修改的!

5. Dockerfile的基础操作

dockerfile 就是用来构建docker镜像的构建文件! 命令脚本。

# 创建一个存放dockerfile文件的目录
mkdir -p /home/docker-test-volume# 编写一个dockerfile,生成镜像(指令都为大写)
# 每行命令,就是镜像的一层!
[root@k8s-master docker-test-volume]# cat dockerfile1
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash# 生成dockerfile文件
[root@k8s-master docker-test-volume]# docker build -f dockerfile1 -t lichenxing/centos:1.0 ./
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos---> 831691599b88
Step 2/4 : VOLUME ["volume01","volume02"]---> Running in 9a58f0ee53e5
Removing intermediate container 9a58f0ee53e5---> 494b993538b5
Step 3/4 : CMD echo "----end----"---> Running in 380c5748e66a
Removing intermediate container 380c5748e66a---> 6f77f010dee6
Step 4/4 : CMD /bin/bash---> Running in 002cd526e782
Removing intermediate container 002cd526e782---> 62fd78da2572
Successfully built 62fd78da2572
Successfully tagged lichenxing/centos:1.0# 查看生成的镜像
[root@k8s-master docker-test-volume]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
lichenxing/centos     1.0                 62fd78da2572        43 seconds ago      215MB# 使用生成的镜像创建一台容器
[root@k8s-master docker-test-volume]# docker run -it lichenxing/centos:1.0 /bin/bash
[root@1af48762856e /]# # 查看目录,可以看到在dockerfile中自动挂载的数据卷
[root@1af48762856e /]# ls -l
total 0
lrwxrwxrwx.   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x.   5 root root 360 Jun 23 03:31 dev
drwxr-xr-x.   1 root root  66 Jun 23 03:31 etc
drwxr-xr-x.   2 root root   6 May 11  2019 home
lrwxrwxrwx.   1 root root   7 May 11  2019 lib -> usr/lib
lrwxrwxrwx.   1 root root   9 May 11  2019 lib64 -> usr/lib64
drwx------.   2 root root   6 Jun 11 02:35 lost+found
drwxr-xr-x.   2 root root   6 May 11  2019 media
drwxr-xr-x.   2 root root   6 May 11  2019 mnt
drwxr-xr-x.   2 root root   6 May 11  2019 opt
dr-xr-xr-x. 130 root root   0 Jun 23 03:31 proc
dr-xr-x---.   2 root root 162 Jun 11 02:35 root
drwxr-xr-x.  11 root root 163 Jun 11 02:35 run
lrwxrwxrwx.   1 root root   8 May 11  2019 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 May 11  2019 srv
dr-xr-xr-x.  13 root root   0 Jun 23 01:36 sys
drwxrwxrwt.   7 root root 145 Jun 11 02:35 tmp
drwxr-xr-x.  12 root root 144 Jun 11 02:35 usr
drwxr-xr-x.  20 root root 262 Jun 11 02:35 var
drwxr-xr-x.   2 root root   6 Jun 23 03:31 volume01		#生成镜像时自动挂载的数据卷目录
drwxr-xr-x.   2 root root   6 Jun 23 03:31 volume02		#生成镜像时自动挂载的数据卷目录## 这两个卷一定有一个与外部同步的目录
# 在卷目录下创建一个文件
[root@1af48762856e /]# cd volume01/
[root@1af48762856e volume01]# touch container.txt# 在宿主机上查看此容器的元数据可以看到卷挂载到了外部的某个目录下
[root@k8s-master docker-test-volume]# docker inspect 1af48762856e
...
"Mounts": [{"Type": "volume","Name": "588dd712d0817140680bd2d7fad6d85bf837cbf9f1ad8c435d06ff98d076f259","Source": "/var/lib/docker/volumes/588dd712d0817140680bd2d7fad6d85bf837cbf9f1ad8c435d06ff98d076f259/_data","Destination": "volume02","Driver": "local","Mode": "","RW": true,"Propagation": ""},{"Type": "volume","Name": "fbd1a9f5c760ef7b592c4b31aaaa3ab4887d650b40397476012d4d942b151bc6","Source": "/var/lib/docker/volumes/fbd1a9f5c760ef7b592c4b31aaaa3ab4887d650b40397476012d4d942b151bc6/_data","Destination": "volume01","Driver": "local","Mode": "","RW": true,"Propagation": ""}
],# 可以看到volume01的挂载目录是路径,cd切换到目录下查看已经同步了创建的文件
/var/lib/docker/volumes/fbd1a9f5c760ef7b592c4b31aaaa3ab4887d650b40397476012d4d942b151bc6/_data/
[root@k8s-master _data]# ll
total 0
-rw-r--r--. 1 root root 0 Jun 23 11:35 container.txt

通常构建自己的镜像时,没有挂在卷,要手动镜像挂载 -v 卷名:容器内路径

6. 数据卷容器

创建三台容器来进行测验数据卷共享 (使用刚刚通过dockerfile生成的镜像)

--volumes-from	# 只要通过此参数,则可以实现容器间的数据共享# 创建第一台容器docker01,挂载的数据卷下没有内容
[root@k8s-master ~]#  docker run -it --name docker01 lichenxing/centos:1.0 
[root@eac7afb4cb11 /]# ls -l
total 0
....
drwxr-xr-x.   2 root root   6 Jun 23 05:54 volume01
drwxr-xr-x.   2 root root   6 Jun 23 05:54 volume02
[root@eac7afb4cb11 /]# ls volume01
[root@eac7afb4cb11 /]# ls volume02# 创建的第二台容器docker02,挂载的为docker上的数据卷,也没有内容
[root@k8s-master ~]#  docker run -it --name docker02 --volumes-from docker01 lichenxing/centos:1.0 
[root@a493d7a3d2ca /]# ls -l
total 0
....
drwxr-xr-x.   2 root root   6 Jun 23 05:54 volume01
drwxr-xr-x.   2 root root   6 Jun 23 05:54 volume02
[root@a493d7a3d2ca /]# ls  volume01 
[root@a493d7a3d2ca /]# ls  volume02# 在docker01容器上的数据卷目录创建文件
[root@k8s-master ~]# docker attach docker01
[root@eac7afb4cb11 /]# touch /volume01/docker01# 在docker02容器上查看,docker01的数据卷目录下文件也已经同步过来了
[root@k8s-master ~]# docker attach docker02 
[root@a493d7a3d2ca /]# ls /volume01/
docker01# 创建第三台容器docker03,将docker01的数据卷挂载; 并且再创建一个docker03文件
# 可以发现容器docker01上的数据卷内容都同步了
[root@k8s-master ~]#  docker run -it --name docker03 --volumes-from docker01 lichenxing/centos:1.0 
[root@336c364cb4fa /]# ls -l /volume01/
total 0
-rw-r--r--. 1 root root 0 Jun 23 06:01 docker01
[root@336c364cb4fa /]# touch /volume01/docker03# 在容器docker01上查看也同步了
[root@k8s-master ~]# docker attach docker01
[root@eac7afb4cb11 /]# ls -l volume01/
total 0
-rw-r--r--. 1 root root 0 Jun 23 06:01 docker01
-rw-r--r--. 1 root root 0 Jun 23 06:07 docker03

删除容器docker01后,其他容器的数据卷内容没有丢失-拷贝机制

[root@k8s-master ~]# docker rm -f docker01 
docker01[root@k8s-master ~]# docker attach docker02 
[root@a493d7a3d2ca /]# ls -l /volume01/
total 0
-rw-r--r--. 1 root root 0 Jun 23 06:01 docker01
-rw-r--r--. 1 root root 0 Jun 23 06:07 docker03
[root@a493d7a3d2ca /]# read escape sequence[root@k8s-master ~]# docker attach docker03
[root@336c364cb4fa /]# ls -l /volume01/
total 0
-rw-r--r--. 1 root root 0 Jun 23 06:01 docker01
-rw-r--r--. 1 root root 0 Jun 23 06:07 docker03
[root@336c364cb4fa /]# read escape sequence

可以运用在多个mysql实现数据共享

# 例子 mysql01
[root@k8s-master ~]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7# 例子 mysql02; 挂载mysql01的数据卷
[root@k8s-master ~]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7

结论

  • 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
  • 一旦持久化到本地目录,本地的数据是不会删除的。

九、Dockerfile

1. Dockerfile介绍

dockerfile 就是用来构建docker镜像的构建文件! 命令脚本!

构建步骤

  • 编写一个dockerfile文件
  • docker build构建成为一个镜像
  • docker run 运行镜像
  • docker push 发布镜像(dockerHub、私有仓库)

查看一下官方是怎么编写的

很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!

2. Dockerfile构建

基础知识

  • 每个指令都必须是大写字母
  • 执行从上到下顺序执行
  • "#"表示注释
  • 每一个指令都会创建提交一个新的镜像层,并提交!

  • Dockerfile是面向开发,我们以后要发布项目,做镜像,就需要编写dockerfile文件。

  • Docker镜像逐渐成为企业交付的标准。

  • Dockerfile :构建文件,定义了一切的步骤,源代码。

  • DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品,原来是jar包 war包

  • Docker容器:容器就是镜像运行起来提供的服务器

3. Dockerfile的指令

FROM				  #指定基础镜像
MAINTAINER		 #指定镜像创建者信息(姓名+邮箱)
RUN						#执行构建命令
CMD						#设置容器启动时执行的操作(只有最后一个会生效,可被替代)
ENTRYPOINT		 #设置容器启动时执行的操作(可以追加命令)
USER					#设置容器的用户
EXPOSE				#指定容器需要映射到宿主机的端口
ENV						#用于设置环境变量
ADD						#从src复制文件到容器的dest路径(会自动解压tar包)
VOLUME				#指定挂载点
WORKDIR				#工作目录
ONBUILD				#在子镜像中执行,构建一个被继承,就会运行此指令,触发指令
COPY					#类似ADD,将文件拷贝到镜像中(不会解压tar包)

4. 自己写一个Dockerfile文件构建镜像

Docker Hub中,99%镜像都是从这个基础镜像FROM scratch过来的,然后配置需要的软件和配置进行构建。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。如果你以scratch为基础镜像的话,意味着不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。有的人可能感觉很奇怪,没有任何基础镜像,我怎么去执行我的程序呢,其实对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接FROM scratch会让镜像体积更加小巧。

# 创建一个存放dockerfile文件的目录
mkdir -p /home/dockerfile
cd /home/dockerfile/
# 编写dockerfile文件
[root@k8s-master dockerfile]# cat mydockerfile-centos 
FROM centos
MAINTAINER lichenxing<245684979@qq.com>ENV MYPATH /usr/local
WORKDIR $MYPATHRUN yum -y install vim
RUN yum -y install net-toolsEXPOSE 80CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
# 进行构建
#docker build "."最后的"."号,其实是在指定镜像构建过程中的上下文环境的目录
docker build -f [dockerfile文件路径] -t 镜像名:[tag] .[root@k8s-master dockerfile]#docker build -f mydockerfile-centos -t mycentos:0.1 .
....
Successfully built 754ab894cdb8
Successfully tagged mycentos:0.1
# 查看构建成功的镜像
[root@k8s-master dockerfile]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
mycentos              0.1                 754ab894cdb8        3 minutes ago       295MB

测试运行

## 这是构建之前的官方centos镜像
[root@k8s-master dockerfile]# docker run -it centos
[root@5a792ccff9b2 /]# pwd		#工作目录默认根目录
/
[root@5a792ccff9b2 /]# vim		#没有vim命令
bash: vim: command not found
[root@5a792ccff9b2 /]# ifconfig	#没有ifconfig命令
bash: ifconfig: command not found## 这是通过dockerfile构建完成的镜像mycentos:0.1
[root@k8s-master dockerfile]# docker run -it mycentos:0.1 
[root@8ebed8ffcb20 local]# pwd		##工作目录修改为/usr/local
/usr/local
[root@8ebed8ffcb20 local]# which vim	#有vim命令
/usr/bin/vim
[root@8ebed8ffcb20 local]# which ifconfig #有ifconfig命令
/usr/sbin/ifconfig

查看镜像的构建历史记录

通过此方法,可以在拿到一个镜像时,研究一下是怎么做到的

5. RUN 执行命令

是否可以像 Shell 脚本一样把每个命令对应一个 RUN 呢?

  • Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。
  • 每个指令新建一层这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。 这是很多初学 Docker 的人常犯的一个错误。
  • Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。
  • 一些下载 创建 删除的命令没有必要建立很多层,这只是一层的事情。因此,这里没有使用很多个 RUN 对一一对应不同的命令,而是仅仅使用一个 RUN 指令,并使用&&将各个所需命令串联起来,简化为1层。
  • 在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。
  • 最后建议添加清理的命令,删除为了编译构建所需要的各种软件,清理所有下载、展开的文件,缓存文件。这是很重要的一步,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。制作出了很臃肿的镜像的原因之一,就是忘记了每一层构建的最后一定要清理掉无关文件。

6. CMD 和 ENTRYPOINT 区别

CMD						#设置容器启动时执行的操作(只有最后一个会生效,可被替代)
ENTRYPOINT		 #设置容器启动时执行的操作(可以追加命令)

测试 CMD

# 编写一个简单的CMD的dockerfile文件
[root@k8s-master dockerfile]# cat dockerfile-cmd-test 
FROM centos
CMD ["ls","-a"]# 进行构建镜像
[root@k8s-master dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
....
Successfully built 0a29d7f31b12
Successfully tagged cmdtest:latest# 运行一个CMD镜像的容器,可以看到,直接输出dockerfile中写的CMD指令
[root@k8s-master dockerfile]# docker run cmdtest 
.
..
.dockerenv
bin
dev
etc
home
...# 再次运行容器,最近一个命令"-l"  [ls -al]
[root@k8s-master dockerfile]# docker run cmdtest -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.## CMD的清理向下"-l"替换了CMD ["ls","-a"]命令, "-l"不是命令所以会报错
[root@k8s-master dockerfile]# docker run cmdtest ls -al
total 0
drwxr-xr-x.   1 root root   6 Jun 23 09:41 .
drwxr-xr-x.   1 root root   6 Jun 23 09:41 ..
-rwxr-xr-x.   1 root root   0 Jun 23 09:41 .dockerenv
lrwxrwxrwx.   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x.   5 root root 340 Jun 23 09:41 dev
drwxr-xr-x.   1 root root  66 Jun 23 09:41 etc
drwxr-xr-x.   2 root root   6 May 11  2019 home
....

测试 ENTRYPOINT

# 编写一个ENTRYPOINT的dockerfile文件
[root@k8s-master dockerfile]# cat dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]# 进行构建镜像
[root@k8s-master dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint .
....
Successfully built 120ba8d637f5
Successfully tagged entrypoint:latest# 运行一个ENTRYPOINT镜像的容器,发现和CMD没有区别
[root@k8s-master dockerfile]# docker run entrypoint
.
..
.dockerenv
bin
dev
etc
home
....# 再次运行容器,追加一个参数 "-l";会发现直接就输出了详细信息
# 追加的命令,是直接拼接在 ENTRYPOINT 命令的后面,而不会去替换命令
[root@k8s-master dockerfile]# docker run entrypoint -l
total 0
drwxr-xr-x.   1 root root   6 Jun 23 09:48 .
drwxr-xr-x.   1 root root   6 Jun 23 09:48 ..
-rwxr-xr-x.   1 root root   0 Jun 23 09:48 .dockerenv
lrwxrwxrwx.   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x.   5 root root 340 Jun 23 09:48 dev
drwxr-xr-x.   1 root root  66 Jun 23 09:48 etc
drwxr-xr-x.   2 root root   6 May 11  2019 home
....

Dockerfile中很多命令都十分的相似,我们需要了解他们的区别,最好的学习方法就是对比它们。

7. 测试 Tomcat镜像(ADD COPY)

1. 准备镜像文件,tomcat压缩包,jdk的压缩包

2. 编写dockerfile文件

建议官方命名 Dockerfilebuild时就不需要-f指定了

[root@k8s-master tomcat]# cat Dockerfile
FROM centos
MAINTAINER lichenxing<245684979@qq.com>COPY readme.txt /usr/local/readme.txtADD jdk-8u60-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.0.27.tar.gz /usr/local/RUN yum -y install vim ENV MYPATH /usr/local
WORKDIR $MYPATHENV JAVA_HOME /usr/local/jdk1.8.0_60
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.0.27
ENV CATALINA_BASH /usr/local/apache-tomcat-8.0.27
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/binEXPOSE 8080CMD /usr/local/apache-tomcat-8.0.27/bin/startup.sh && tail -F /url/local/apache-tomcat-8.0.27/bin/logs/catalina.out

3. 构建镜像

[root@k8s-master tomcat]# pwd
/home/dockerfile/build/tomcat
[root@k8s-master tomcat]# docker build -t diytomcat ./
....
Successfully built e256e862f380
Successfully tagged diytomcat:latest

4. 运行此镜像的容器

# 将webapps目录下的一些日志或者代码可以挂载到宿主机的目录下[root@k8s-master tomcat]# docker run -d -p 9090:8080 --name lcxtomcat -v /home/dockerfile/build/tomcat/test:/usr/local/apache-tomcat-8.0.27/webapps/test -v /home/dockerfile/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-8.0.27/logs/ diytomcat
f1c38b290af2d88ca5ccfc99b5baaea77cc43d9de6a8ce75d6443125f74d2c3a# 可以看到挂载到宿主机的目录已经同步
[root@k8s-master tomcat]# pwd
/home/dockerfile/build/tomcat
[root@k8s-master tomcat]# ls
apache-tomcat-8.0.27.tar.gz  Dockerfile  jdk-8u60-linux-x64.tar.gz  readme.txt  test  tomcatlogs
[root@k8s-master tomcat]# ll tomcatlogs/
total 20
-rw-r--r--. 1 root root 6539 Jun 24 17:41 catalina.2020-06-24.log
-rw-r--r--. 1 root root 6539 Jun 24 17:41 catalina.out
-rw-r--r--. 1 root root    0 Jun 24 17:41 host-manager.2020-06-24.log
-rw-r--r--. 1 root root  280 Jun 24 17:41 localhost.2020-06-24.log
-rw-r--r--. 1 root root    0 Jun 24 17:41 localhost_access_log.2020-06-24.txt
-rw-r--r--. 1 root root    0 Jun 24 17:41 manager.2020-06-24.log

5. 进入tomcat容器中查看

[root@k8s-master tomcat]# docker exec -it lichenxingtomcat /bin/bash
[root@f1c38b290af2 local]# pwd
/usr/local
[root@f1c38b290af2 local]# ls
apache-tomcat-8.0.27  etc    include	  lib	 libexec     sbin   src
bin		      games  jdk1.8.0_60  lib64  readme.txt  share
[root@f1c38b290af2 local]# ls -l apache-tomcat-8.0.27/
total 92
-rw-r--r--. 1 root root 57011 Sep 28  2015 LICENSE
-rw-r--r--. 1 root root  1444 Sep 28  2015 NOTICE
-rw-r--r--. 1 root root  6741 Sep 28  2015 RELEASE-NOTES
-rw-r--r--. 1 root root 16204 Sep 28  2015 RUNNING.txt
drwxr-xr-x. 2 root root  4096 Sep 28  2015 bin
drwxr-xr-x. 1 root root    22 Jun 24 09:41 conf
drwxr-xr-x. 2 root root  4096 Sep 28  2015 lib
drwxr-xr-x. 2 root root   197 Jun 24 09:41 logs
drwxr-xr-x. 2 root root    30 Sep 28  2015 temp
drwxr-xr-x. 1 root root    18 Jun 24 09:41 webapps
drwxr-xr-x. 1 root root    22 Jun 24 09:41 work
[root@f1c38b290af2 local]# ls -l apache-tomcat-8.0.27/webapps/
total 8
drwxr-xr-x.  3 root root 4096 Sep 28  2015 ROOT
drwxr-xr-x. 14 root root 4096 Sep 28  2015 docs
drwxr-xr-x.  6 root root   83 Sep 28  2015 examples
drwxr-xr-x.  5 root root   87 Sep 28  2015 host-manager
drwxr-xr-x.  5 root root  103 Sep 28  2015 manager
drwxr-xr-x.  2 root root    6 Jun 24 09:41 test
[root@f1c38b290af2 local]# ls -l apache-tomcat-8.0.27/logs/
total 20
-rw-r--r--. 1 root root 6539 Jun 24 09:41 catalina.2020-06-24.log
-rw-r--r--. 1 root root 6539 Jun 24 09:41 catalina.out
-rw-r--r--. 1 root root    0 Jun 24 09:41 host-manager.2020-06-24.log
-rw-r--r--. 1 root root  280 Jun 24 09:41 localhost.2020-06-24.log
-rw-r--r--. 1 root root    0 Jun 24 09:41 localhost_access_log.2020-06-24.txt
-rw-r--r--. 1 root root    0 Jun 24 09:41 manager.2020-06-24.log
# 测试连接性
[root@f1c38b290af2 local]# curl -I 127.0.0.1:8080
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 24 Jun 2020 09:48:16 GMT

宿主机的9090端口

6. 上传一个web站点的压缩包到test目录下进行测试

[root@k8s-master tomcat]# pwd
/home/dockerfile/build/tomcat
[root@k8s-master tomcat]# cd ./test/
[root@k8s-master test]# ll
total 20316
-rw-r--r--.  1 root root 20797013 Jun 24 18:02 jpress-web-newest.war
drwxr-xr-x.  3 root root       38 Sep 19  2016 META-INF
-rw-r--r--.  1 root root       96 Jul 27  2016 robots.txt
drwxr-xr-x. 11 root root      139 Sep 19  2016 static
drwxr-xr-x.  4 root root       31 Sep 19  2016 templates
drwxr-xr-x.  6 root root       75 Jun 24 18:02 WEB-INF

先不用做安装,只测试。没有数据库环境

  • 在主机的test目录下就可以修改代码文件。
# 可以在宿主机上直接查看访问的日志文件
[root@k8s-master tomcat]# tail -f tomcatlogs/catalina.out JFinal action report -------- 2020-06-24 10:05:59 ------------------------------
Controller  : io.jpress.install.InstallController.(InstallController.java:1)
Method      : step2
Interceptor : io.jpress.core.interceptor.JI18nInterceptor.(JI18nInterceptor.java:1)io.jpress.interceptor.GlobelInterceptor.(GlobelInterceptor.java:1)io.jpress.interceptor.AdminInterceptor.(AdminInterceptor.java:1)io.jpress.core.interceptor.HookInterceptor.(HookInterceptor.java:1)io.jpress.install.InstallInterceptor.(InstallInterceptor.java:1)
--------------------------------------------------------------------------------

8. 发布镜像到DockerHub

官方DockerHub仓库

https://hub.docker.com/

需要注册自己的账户,确认可以登录

在服务器上提交镜像到官方仓库

[root@k8s-master tomcat]# docker login -u 245684979
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded# 为封装好的镜像打一个标签
# 这里要注意 给自己镜像命名的时候格式应该是: docker注册用户名/镜像名,不然是push不上去的
[root@k8s-master tomcat]# docker tag diytomcat:latest 245684979/diytomcat:1.0

[root@k8s-master tomcat]# docker push 245684979/diytomcat:1.0 
The push refers to repository [docker.io/245684979/diytomcat]
0877995fc452: Pushing  9.192MB/57.19MB
5dedcbd44b60: Pushing  2.864MB/12.94MB
f675325f4324: Pushing  1.607MB/364.8MB
c966da79fa06: Pushing   2.56kB
eb29745b8228: Pushing  6.019MB/215.3MB
...

提交的时候也是按照镜像的成绩来进行提交的,提交成功后在DockerHub就可以看到了

9. 发布镜像到阿里云镜像仓库

登陆阿里云

找到容器镜像服务

创建命名空间

创建容器镜像

浏览操作指南

[root@k8s-master ~]# docker push registry.cn-beijing.aliyuncs.com/lichenxing/lcxtomcat:1.0 
The push refers to repository [registry.cn-beijing.aliyuncs.com/lichenxing/lcxtomcat]
0877995fc452: Pushed 
5dedcbd44b60: Pushed 
f675325f4324: Pushed 
c966da79fa06: Pushed 
eb29745b8228: Pushed 
1.0: digest: sha256:2e3c25e752897e3c166cc3b372bddefb3de5db0fb04d1f8a883580e04bdd6c90 size: 1372

10. 发布镜像到私有仓库

有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个本地仓库供私人使用。docker-registry是官方提供的工具,可以用于构建私有的镜像仓库。

普通的registry

默认情况下,仓库会被创建在容器的/var/lib/registry目录下。可以通过 -v 参数来将镜像文件存放在本地的指定路径。

# 运行官方registry镜像
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry  registry# 将镜像加速器地址改为本地
[root@k8s-master ~]# cat  /etc/docker/daemon.json 
{"registry-mirrors": ["https://registry.docker-cn.com"],"insecure-registries": ["192.168.0.10:5000"]
}
systemctl restart docker#  给镜像打标签
docker tag diytomcat 192.168.0.10:5000/lcxtomcat:1.0# 上传镜像到私有仓库
[root@k8s-master ~]# docker push 192.168.0.10:5000/lcxtomcat
The push refers to repository [192.168.0.10:5000/lcxtomcat]
0877995fc452: Pushed 
5dedcbd44b60: Pushed 
f675325f4324: Pushed 
c966da79fa06: Pushed 
eb29745b8228: Pushed 
1.0: digest: sha256:2e3c25e752897e3c166cc3b372bddefb3de5db0fb04d1f8a883580e04bdd6c90 size: 1372# 查看私有仓库上传的镜像
[root@k8s-master ~]# curl 127.0.0.1:5000/v2/_catalog
{"repositories":["lcxtomcat"]}

十、Docker网络

  • None:不为容器配置任何网络功能,–net=none
  • Container:与另一个运行中的容器共享Network Namespace,–net=container:containerID(K8S)
  • Host:与宿主机共享Network Namespace,–network=host 性能最高
  • Bridge:Docker设计的NAT网络模型(默认)

# 清除所有容器和镜像环境
docker rm -f $(docker ps -aq)
docker rmi `docker images -qa`
# 启动一台容器
[root@k8s-master ~]# docker run -d -P --name tomcat01 tomcat# 查看容器的网卡信息
[root@k8s-master ~]# docker exec -it tomcat01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
21: eth0@if22: <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 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever# linux宿主机可以ping通容器内部
[root@k8s-master ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.053 ms

原理:

  • 每启动一个docker容器,docker都会给容器分配一个ip,我们只要按照了docker,就会有一个网卡docker0,Bridge桥接模式使用的技术是evth-pair技术。
  • evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连,正因为有这个特性,evth-pair充当一个桥梁,专门连接各种虚拟网络设备。每开启运行一个容器,就会增加一对儿对应的网卡。
  • Openstack、Docker、OVS都是使用的 evth-pair技术。
  • 容器删除,对应的网桥也被删除

1. Bridge模式

Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。从docker0子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中。可以通过brctl show命令查看。

bridge模式是 docker 的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker 实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。

–link 容器互联

随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 --link 参数。

思考:编写一个微服务,database url=ip:,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以用名字来进行访问容器吗?

# 创建俩台容器 tomcat01和tomcat02docker run -it -d -P --name tomcat01 245684979/diytomcat:1.0docker run -it -d -P --name tomcat02 245684979/diytomcat:1.0# 尝试相互ping不能ping通[root@k8s-master ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known# 创建tomcat03容器,使用--link,即可解决了网络连通问题
docker run -it -d -P  --name tomcat03 --link tomcat02 245684979/diytomcat:1.0# 通过容器tomcat03来ping容器tomcat02可以ping通了
[root@k8s-master ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.055 ms# 反向是不可以ping通 02 ping 03
[root@k8s-master ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

查看网络的信息

# 查看网络详细信息
[root@k8s-master ~]# docker network inspect cd3809ba6584
[{"Name": "bridge","Id": "cd3809ba6584494c86e9802d3dfc6424bb33226c93b80bd31d9f43dd25c200c2","Created": "2020-06-29T11:20:18.826585474+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "172.17.0.0/16","Gateway": "172.17.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"07926c954f2ad324dc977bed26af4953713355dcc5b67aea97f18830984bfce5": {"Name": "tomcat02","EndpointID": "ff5fc39a60e1c6291afed28de6c2d14a5c43554e9a6dbff04495ee4d4ae0ec64","MacAddress": "02:42:ac:11:00:03","IPv4Address": "172.17.0.3/16",	# 为tomcat02分配的IP"IPv6Address": ""},"b423584cb2f658703f42bfc8fe9fe40e61b3b9b7d29d4bee5af213340e9058ae": {"Name": "tomcat01","EndpointID": "2e6d7bf8db206b2392eec7b959c5c695e61e1826e1eb03f3e8d0d012b3a3cc63","MacAddress": "02:42:ac:11:00:02","IPv4Address": "172.17.0.2/16",	# 为tomcat01分配的IP"IPv6Address": ""},"b820e4afdccdb8a50045c77de6e575bff0df692ed144673e2cb2bb2259a76c08": {"Name": "tomcat03","EndpointID": "d7bf4b2f4b213f6497cfcfdac40c827d104f56dee5a6cd14fade2b48d8ae9f54","MacAddress": "02:42:ac:11:00:04","IPv4Address": "172.17.0.4/16",	# 为tomcat03分配的IP"IPv6Address": ""}},"Options": {"com.docker.network.bridge.default_bridge": "true","com.docker.network.bridge.enable_icc": "true","com.docker.network.bridge.enable_ip_masquerade": "true","com.docker.network.bridge.host_binding_ipv4": "0.0.0.0","com.docker.network.bridge.name": "docker0","com.docker.network.driver.mtu": "1500"},"Labels": {}}
]
# 查看tomcat03的信息,可以看到links指定的是tomcat02
[root@k8s-master ~]# docker inspect tomcat03
...."Links": ["/tomcat02:/tomcat03/tomcat02"],
....# 通过查看tomcat03的hosts文件也可以看到
[root@k8s-master ~]# 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 07926c954f2a		# 指定了tomcat02
172.17.0.4	b820e4afdccd
  • --link 就是在hosts配置中增加了一个主机名的解析
  • 随着 Docker 网络的完善,建议将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 --link 参数
  • docker0问题 不支持容器名连接访问。

自定义网络

查看网络

# 查看网络
[root@k8s-master ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
cd3809ba6584        bridge              bridge              local
018532904f4e        host                host                local
edfe5b0c21a1        none                null                local
# 清除测试的所有容器
docker rm -f $(docker ps -aq)# 创建一台容器; --network brigde 就是docker0
docker run  -d -P --name tomcat01 --network bridge tomcat# 创建一个网络mynet
# --driver  : 网络模式
# --subnet  : 子网地址
# --gateway : 子网的网关地址
docker network create --driver  bridge --subnet 172.20.0.0/16 --gateway 172.20.0.1 mynet# 查看自己创建的网络详细信息
[root@k8s-master ~]# docker network inspect mynet 
[{"Name": "mynet","Id": "ea720ae53f20b83193bca0c1dbb6296165539aa4c547f1ef37028e705b87da6c","Created": "2020-06-29T14:33:22.194817791+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "172.20.0.0/16",	#子网"Gateway": "172.20.0.1"		#网关}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {},"Labels": {}}
]

启动两台容器;指定创建的自定义网络

docker run -d -P --name tomcat-net01 --net mynet tomcat
docker run -d -P --name tomcat-net02 --net mynet tomcat
# 再次查看网络详情,可以看到启动的容器的IP
[root@k8s-master ~]# docker network inspect mynet
...."Containers": {"2767e468d20157e43b67174eeef94267ce2b3a5b9f66446b24fd17c06549fdb3": {"Name": "tomcat-net01","EndpointID": "abadd831f2591a0d2aed089abac60292cfc0925193d6f3394131955140118750","MacAddress": "02:42:ac:14:00:02","IPv4Address": "172.20.0.2/16","IPv6Address": ""},"4a70bba89baf3e98b4f3e35de9ee19d5363f06c592dff2bf81134fbc187ac0a0": {"Name": "tomcat-net02","EndpointID": "8cdf9df77303ec7c3562e4b216d09ac5c5a39a7d7a5a1563b93ea7f5fd4d5060","MacAddress": "02:42:ac:14:00:03","IPv4Address": "172.20.0.3/16","IPv6Address": ""}},# 再次测试ping连接; ping主机名也可以ping通了
[root@k8s-master ~]# docker exec -it tomcat-net01 ping 172.20.0.3
PING 172.20.0.3 (172.20.0.3) 56(84) bytes of data.
64 bytes from 172.20.0.3: icmp_seq=1 ttl=64 time=0.111 ms[root@k8s-master ~]# docker exec -it tomcat-net01 ping tomcat-net02
PING tomcat-net02 (172.20.0.3) 56(84) bytes of data.
64 bytes from tomcat-net02.mynet (172.20.0.3): icmp_seq=1 ttl=64 time=0.042 ms--------------------------------------
##现在不使用--link也可以ping通主机名了

自定义的网络docker都已经帮我们维护好了对应的关系,平时也推荐这样使用网络。

优势:

  • Redis:不同的集群使用不同的网络,保证集群是安全和健康的
  • MySQL:不同的集群使用不同的网络,保证集群是安全和健康的

2. Host 模式

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

# 运行一个host网络的容器
docker run -it -d -P --name tomcat-host01 --net host tomcat# 查看此容器的ip地址和宿主机一致
[root@k8s-master ~]# docker exec -it tomcat-host01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:8a:1a:eb brd ff:ff:ff:ff:ff:ffinet 192.168.0.10/24 brd 192.168.0.255 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fe8a:1aeb/64 scope link valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:8a:1a:f5 brd ff:ff:ff:ff:ff:ffinet 172.16.0.10/24 brd 172.16.0.255 scope global eth1valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fe8a:1af5/64 scope link valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:8d:a8:1d:4b brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:8dff:fea8:1d4b/64 scope link valid_lft forever preferred_lft forever
21: br-45945e527658: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:16:06:bd:c9 brd ff:ff:ff:ff:ff:ffinet 172.20.0.1/16 brd 172.20.255.255 scope global br-45945e527658valid_lft forever preferred_lft foreverinet6 fe80::42:16ff:fe06:bdc9/64 scope link valid_lft forever preferred_lft forever

3. Container 模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

# 运行一个centos镜像容器
[root@k8s-master ~]# docker run -it -d --name centos01  centos
[root@k8s-master ~]# docker exec -it centos01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
28: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever# 运行一个Container模式的容器; 指定centos01容器;查看网络
[root@k8s-master ~]# docker run -it -d --name centos-container --network container:centos01 centos
[root@k8s-master ~]# docker exec -it centos-container ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
28: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever

4. None模式

使用none模式,Docker 容器拥有自己的 Network Namespace,但是,并不为Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。

# 运行一个none模式的容器
docker run -it -d --name centos-none --network none centos# 进入容器查看网卡发现没有ip地址
[root@k8s-master ~]# docker exec -it centos-none ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever

5. 网络连通


# 用bridge模式的容器去ping自定义网络的容器;发现ping不通,因为网络不同
[root@k8s-master ~]# docker exec -it tomcat01 ping tomcat-net01
ping: tomcat-net01: Name or service not known

测试 将默认 bridge 模式的容器 tomcat01 和 自定义 mynet 网络打通

docker network connect mynet tomcat01
# 查看mynet网络详情
docker network inspect mynet

# 一个容器 两个ip地址!
[root@k8s-master ~]# docker exec -it tomcat01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
32: eth0@if33: <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 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
40: eth1@if41: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:14:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.20.0.4/16 brd 172.20.255.255 scope global eth1valid_lft forever preferred_lft forever# 可以ping通了
[root@k8s-master ~]# docker exec -it tomcat01 ping tomcat-net01
PING tomcat-net01 (172.20.0.2) 56(84) bytes of data.
64 bytes from tomcat-net01.mynet (172.20.0.2): icmp_seq=1 ttl=64 time=0.045 ms# 而其他的是依旧ping不通的
[root@k8s-master ~]# docker exec -it tomcat02 ping tomcat-net01
ping: tomcat-net01: Name or service not known

总结:如果要跨网络操作其他容器,就需要使用 docker network connect连通。

6. 部署一个Redis集群

# 创建一个redis网络
docker network create redis --subnet 172.30.0.0/16# 执行一下命令创建6套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.30.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done[root@k8s-master ~]# tree /mydata/redis/
/mydata/redis/
├── node-1
│   └── conf
│       └── redis.conf
├── node-2
│   └── conf
│       └── redis.conf
├── node-3
│   └── conf
│       └── redis.conf
├── node-4
│   └── conf
│       └── redis.conf
├── node-5
│   └── conf
│       └── redis.conf
└── node-6└── conf└── redis.conf# 依次启动6台redis容器
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.30.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.confdocker 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.30.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.confdocker 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.30.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.confdocker 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.30.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.confdocker 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.30.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.confdocker 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.30.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 查看启动的redis容器
[root@k8s-master ~]# docker ps -a
CONTAINER ID        IMAGE                    COMMAND                  CREATED              STATUS              PORTS                                              NAMES
85de61b9c858        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   4 seconds ago        Up 2 seconds        0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp   redis-6
0a1c84984623        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   5 seconds ago        Up 3 seconds        0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp   redis-5
747dc6d77115        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   46 seconds ago       Up 45 seconds       0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp   redis-4
0f88ca73c73a        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:6373->6379/tcp, 0.0.0.0:16373->16379/tcp   redis-3
3ca265147808        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp   redis-2
c9b5fea846b9        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   3 minutes ago        Up 3 minutes        0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp   redis-1
# 创建redis集群
[root@k8s-master ~]# docker exec -it redis-1 /bin/sh
/data # redis-cli --cluster create 172.30.0.11:6379 172.30.0.12:6379 172.30.0.13:6379 172.30.0.14:637
79 172.30.0.15:6379 172.30.0.16:6379 --cluster-replicas 1
-------------------------
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.30.0.15:6379 to 172.30.0.11:6379
Adding replica 172.30.0.16:6379 to 172.30.0.12:6379
Adding replica 172.30.0.14:6379 to 172.30.0.13:6379
M: ef62648c7f22c87109e3a4004e0b7b2a9717c5ca 172.30.0.11:6379slots:[0-5460] (5461 slots) master
M: 18eeb76c35d2185d39ecf0700cb486446f78065d 172.30.0.12:6379slots:[5461-10922] (5462 slots) master
M: 89a2b7bc56f838794f3b4492745f33a55f2af842 172.30.0.13:6379slots:[10923-16383] (5461 slots) master
S: 22acd8c91964e59f767fe95468210e876b65aa63 172.30.0.14:6379replicates 89a2b7bc56f838794f3b4492745f33a55f2af842
S: 7d37c75d6f6868e0eb50505763c6dcca533a7252 172.30.0.15:6379replicates ef62648c7f22c87109e3a4004e0b7b2a9717c5ca
S: c9726603df7d4a132ce012dd68ad829a69553ec9 172.30.0.16:6379replicates 18eeb76c35d2185d39ecf0700cb486446f78065d
Can I set the above configuration? (type 'yes' to accept): yes		#输入yes
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.		#集群配置完毕
# 查看redis集群
/data # redis-cli -c 
127.0.0.1:6379> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:85
cluster_stats_messages_pong_sent:88
cluster_stats_messages_sent:173
cluster_stats_messages_ping_received:83
cluster_stats_messages_pong_received:85
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:173# 三主三从
127.0.0.1:6379> CLUSTER NODES
7d37c75d6f6868e0eb50505763c6dcca533a7252 172.30.0.15:6379@16379 slave ef62648c7f22c87109e3a4004e0b7b2a9717c5ca 0 1593426397000 5 connected
c9726603df7d4a132ce012dd68ad829a69553ec9 172.30.0.16:6379@16379 slave 18eeb76c35d2185d39ecf0700cb486446f78065d 0 1593426397015 6 connected
22acd8c91964e59f767fe95468210e876b65aa63 172.30.0.14:6379@16379 slave 89a2b7bc56f838794f3b4492745f33a55f2af842 0 1593426398022 4 connected
18eeb76c35d2185d39ecf0700cb486446f78065d 172.30.0.12:6379@16379 master - 0 1593426397518 2 connected 5461-10922
89a2b7bc56f838794f3b4492745f33a55f2af842 172.30.0.13:6379@16379 master - 0 1593426397518 3 connected 10923-16383
ef62648c7f22c87109e3a4004e0b7b2a9717c5ca 172.30.0.11:6379@16379 myself,master - 0 1593426396000 1 connected 0-5460
# 存一个值;可以看到存到了172.30.0.13,是master节点
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.30.0.13:6379
OK# 在其他窗口将redis-3 关闭
[root@k8s-master ~]# docker stop redis-3 
redis-3# 再次进入到redis集群查看之前的值;已经存到172.30.0.14节点上了
/data # redis-cli -c
127.0.0.1:6379> get a 
-> Redirected to slot [15495] located at 172.30.0.14:6379
"b"


部署redis集群完成!

十一、 Docker Compose

十二、 Docker Swarm

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 表单验证-正则表达式

    本周的学习任务是制作一个正则表达式。学长给了一个正则表达式教程,看完了以后发现并没有记住什么。正则表达式真的要记的东西很多,所以我都是直接在网上找相应的表达式,因为要调试验证,慢慢也记住了一些最基本的东西。现在拿到一个正则表达式还是能够做一些最基本分析,也…...

    2024/5/9 6:38:17
  2. 【c#】关于设置RichTextBox背景透明+无光标只读状态

    今天在设置一个软件的RichTextBox的时候,需要一个背景透明,不可编辑的文本展示框,而且还要向文本框中不停地追加数据,所以我选择修改winform自带的richtextbox组件。 首先,我们先新建一个自定义组件,继承与RichTextBox,在构造函数中添加双缓冲避免组件闪烁:public DsAl…...

    2024/5/8 23:27:02
  3. 在父节点transform: translate(0, 0)子节点部分position:fixed部分浏览器无效

    在bootstrap模态框中使用一个全屏模态框在使用fixed属性后,测试在IE11、Firefox、safari中均没有问题,在Opera和Chrome中无效。 解决办法:将带有fixed属性弹框放到外面来,html或js转移都行。 原理...

    2024/4/17 10:15:51
  4. C语言中函数参数为什么是由右往左入栈的?

    先通过一个小程序来看一看:#include void foo(int x, int y, int z) { printf("x = %d at [%X]n", x, &x); printf("y = %d at [%X]n", y, &y); printf("z = %d at [%X]n", z, &z); }int main(int argc, char *argv[]) { foo(100, …...

    2024/4/19 23:48:51
  5. linux下安装docker、配置开机启动及配置阿里云镜像

    什么是docker docker是虚拟化容器技术。Docker基于镜像,可以秒级启动各种容器。每一种容器都是一个完整的运行 环境,容器之间互相隔离。 好比之前在linux上安装各种软件,如果某个软件出现问题影响到了linux系统,会导致整个系统的软件都崩溃。 docker就好比是相互隔离的容器…...

    2024/4/17 10:14:51
  6. 探索 CSS3 中的 box-shadow 属性

    原文链接:http://web.jobbole.com/87938/挖掘你之前未曾见过的一些应用。 PS:文章末尾的 codepen 有8个不错的案例。“box-shadow”属性box-shadow属性是一个CSS3属性,允许我们在几乎任何元素上来创建阴影效果,类似于在设计软件中的”drop shadow”。这些阴影效果允许我们在…...

    2024/4/17 10:15:33
  7. 用C语言制作的猜数游戏

    游戏内容:根据系统的提示在1—100之间猜一个数,如果在10s内猜对了,就结束关机,如果猜错了,就关机。 void menu() {printf("***********************\n");printf("*** 1.play 0.exit ***\n");printf("***********************\n"); } void…...

    2024/4/19 1:17:36
  8. C#设置richtextbox滚动到最后一行

    关键字:richtextbox 滚动到最后 C#设置richtextbox滚动到最后一行 C# private delegate void delInfoList(string text);//申明委托,防止不同线程设置richtextbox时出现错误void SetrichTextBox(string value) {if (RecRichTextBox.InvokeRequired) {delInfoList d = new …...

    2024/5/3 6:31:42
  9. C与汇编:调用子函数

    研究目的:了解汇编如何实现C语言中的函数调用编译器:TDM-GCC 4.9.2 64-bit Release反汇编:Dev-C++ 5.11C语言代码:该函数调用了一个简单的add函数,add函数将输入的两个参数值相加,并返回两参数之和。main函数:1、2行:rbp的作用是标记基址,在一个函数的执行过程中是固定…...

    2024/4/17 15:59:01
  10. 闭关修炼80天,啃下这些分布式技术笔记,有幸通过阿里Java岗P7面试

    从去年互联网寒冬的裁员潮,到今年受疫情影响的春招消失。我有两个很多年的朋友,最初大家水平差不多,但几年的时间他们两个人走上了不同的道路。一位朋友每天写业务代码,做些增删改查的工作,疫情期间,公司停发了补贴,现在时刻担心被裁员。另外一个朋友,之前工作不太顺利…...

    2024/4/17 10:15:45
  11. [C#][转载]实现richtextbox的多步撤消(Undo、Redo)?

    下面是针对textbox的。高手参照此资料做一个richtextbox, [C#]可以进行多步撤消(Undo、Redo)的TextBox 默认的TextBox只能进行一步撤消,且不存在Redo操作(二次撤消相当于一次Redo)。以下这个组件实现了TextBox的多步撤消(Undo、Redo)操作,代码改编于Kevin.SyntaxTextB…...

    2024/4/25 11:58:14
  12. 正则表达式基础入门看这一篇就够了

    https://mp.weixin.qq.com/s/ejtbumkNZpaPSc4AP2XsoA 摘自java 团长正则表达式在几乎所有语言中都可以使用,无论是前端的JavaScript、还是后端的Java、c#。他们都提供相应的接口/函数支持正则表达式。但很神奇的是:无论你大学选择哪一门计算机语言,都没有关于正则表达式的课…...

    2024/4/17 10:15:33
  13. c#richtextbox的内容保存为TXT文本

    c#richtextbox的内容保存为TXT文本private void toolStripButton1_Click(object sender, EventArgs e){string path = @"D:\text.txt";string text = richTextBox1.Text;FileStream fs = null;byte[] array = new UTF8Encoding(true).GetBytes(text);fs = new FileSt…...

    2024/4/17 10:14:57
  14. C语言中如何调用另一个源文件里的函数

    在开发大型项目时,我们常常需要将一份源码分成多个源文件来进行编写,这样可以方便后期的维护。下面就介绍如何从一个源文件里调用另一个源文件的函数。 在源文件A1.c中调用A2.c 中的函数有两种方法: 1.在A2.c中有完整的函数定义,在A1.c中添加一下要用到的函数原型(声明)就…...

    2024/4/20 16:35:43
  15. 14. 设计模式-代理模式

    文章目录设计模式-代理模式1. 静态代理1.1 引出静态代理模式1.2 代码实现之接口ITeacherDao被代理对象TeacherDao静态代理对象TeacherDaoProxyClient1.3 静态代理优缺点2.动态代理-JDk代理2.1 JDK代理2.2 代码实现之接口ITeacherDao被代理对象TeacherDao代理对象工厂类ProxyFac…...

    2024/4/17 10:16:27
  16. 自己写的几个常用css动画(自己收藏用)

    /*向左移动并弹性显示*/ @-webkit-keyframes fadeToLeftTan{0%{ -webkit-transform:translateX(100%); opacity:0;}70%{ -webkit-transform:translateX(-5%); opacity:1;}80%{ -webkit-transform:translateX(2%); opacity:1;}90%{ -webkit-transform:translateX(-2%); opacity:…...

    2024/5/2 23:02:38
  17. 如何用C语言封装 C++的类(C调用C++函数)、(C++调用C函数)

    1、C调用C++本文给出了一种方法。基本思想是,写一个 wrapper文件,把 C++类封装起来,对外只提供C语言的接口,和 C++i相关的都在 wrapper的实现文件里实现。//------apple.h #ifndef __APPLE_H__ #define __APPLE_H__ class Apple { public:enum{APPLE_COLOR_RED,APPLE_COLO…...

    2024/5/3 4:47:29
  18. c语言编写猜数字游戏

    #include<stdio.h> #include<stdlib.h> #include<time.h>int main() {int num = 0;int ret = 0;srand((unsigned)time(NULL));ret = rand()%100+1; //产生一个小于100的随机数while(1){printf("请输入一个数字>>\n");scanf("…...

    2024/5/3 5:35:57
  19. 判断richtextbox选中的是否为图片

    if (richTextBox1.SelectedRtf.IndexOf(@"{\pict") > -1){Text = "Img";}else{Text = "Form1";}转载于:https://www.cnblogs.com/xe2011/p/3478936.html...

    2024/4/20 5:30:14
  20. transform对span无效果

    想要通过transform实现类似图中效果 <div><span>个人报表</span> </div>div{width:80px;text-align:center;border:1px solid #b5b5b5;transform:skew(-30deg); } span{transform:skew(30deg); }结果文字依然是倾斜的 查看CSS参考手册,transform适用于…...

    2024/4/17 10:17:03

最新文章

  1. 什么是Facebook付费广告营销?

    Facebook作为全球最大的社交平台之一&#xff0c;成为了跨境卖家不可或缺的营销阵地。它不仅拥有庞大的用户基数&#xff0c;还提供了丰富的广告工具和社群互动功能&#xff0c;让商家能够精准触达目标市场&#xff0c;提升品牌影响力。云衔科技通过Facebook付费广告营销的专业…...

    2024/5/9 7:40:42
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. 产品推荐 | 中科亿海微推出亿迅®A8000金融FPGA加速卡

    01、产品概述 亿迅A8000金融加速卡&#xff0c;是中科亿海微联合金融证券领域的战略合作伙伴北京睿智融科&#xff0c;将可编程逻辑芯片与金融行业深度结合&#xff0c;通过可编程逻辑芯片对交易行情加速解码&#xff0c;实现低至纳秒级的解码引擎&#xff0c;端到端的处理时延…...

    2024/5/9 3:34:56
  4. node.js常用指令

    1、node&#xff1a;启动 Node.js REPL&#xff08;交互式解释器&#xff09;。 node 2、node [文件名]&#xff1a;执行指定的 JavaScript 文件。 node app.js 3、npm init&#xff1a;初始化一个新的 Node.js 项目&#xff0c;生成 package.json 文件。 此命令会创建一个…...

    2024/5/8 5:27:10
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/7 9:45:25
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/9 4:20:59
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/8 20:48:49
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/8 19:33:07
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/8 20:38:49
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/9 7:32:17
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57