Docker完结版

1 . Docker 概述:

1.1 Docker为什么会出现:

问题: 在互联网开发环境当中很多情况会遇到在我的电脑上可以运行但是到你的电脑上就无法运行可,而且在软件版本更新以后会导致服务不可用的情况出现。

解决方式:
发布一个项目:

将一个项目打成jar包时带上Redis,Mysql, jdk, ES等一套环境一起发布部署

特点:(使用Docker后的开发步骤)

java --- jar(环境) ---- 打包项目带上环境(镜像)---- (Docker仓库:商店)----- 运维人员下载我们发布的镜像运行即可!

image-20230416145604275

原始的项目结构存在着端口冲突的问题:

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

重点:

Docker 隔离其实就是保存最原生的东西,最核心的环境,例如一个Linux虚拟几最核心的东西也不是很大

Docker是基于Go语言开发的,是一个开源项目:

官方网站:Docker: Accelerated, Containerized Application Development

官方文档:Docker Docs: How to build, share, and run applications | Docker Documentationimage-20230416151943462

可发布自己的镜像网站:

image-20230416152255457

1.2 Docker能干嘛:

之前虚拟机的缺点:

1.资源占用较多
2.冗余的步骤很多
3.启动很慢

容器化技术:

容器化技术并不是模拟一个完整的操作系统,虚拟机和Docker不同之处:

  • 传统的虚拟机,虚拟机虚拟出一套硬件,运行一个完整的操作系统
  • 容器内的应用直接运行在宿主机的内容,容器没有自己的内核,也没有虚拟机的硬件,所以轻便
  • 每个容器是相互隔离的,每一个容器内部都有一个属于自己的文件系统,互不影响

DevOps(开发 运维)

1.应用更快速的交付以及部署:
    (1)传统的:一堆文档,安装程序
    (2)Docker:打包镜像发布测试,一键运行
2.更便捷的升级和扩缩容:
     使用Docker之后,我们部署应用就和搭积木一样
3.更加简单的系统运维:
      在容器化之后,我们开发,测试环境都是高度的一致
4.更加高效的计算资源的利用:
       Docker是内核级别的虚拟化,可以在一个虚拟机上运行很多的容器实例!服务器的性能可以被压榨
       到极致

2. Docker 安装:

2.1 Docker的基本组成:

image-20230417162129700

Docker 镜像(Images):

Docker 镜像是用于创建 Docker 容器的模板,tomcat镜像—>run—>tomcat001容器(提供服务器)

Docker容器(Container):

容器是独立运行的一个或一组应用,是镜像运行时的实体。

Docker客户端(Client):

Docker 客户端通过命令行或者其他工具使用 Docker SDK与 Docker 的守护进程通信。

仓库(repository):

仓库就是存放镜像的地方!仓库分为共有镜像和私有镜像(Docker Hub)

2.2 Docker的安装:

环境准备:

1.需要会一点Linux基础
2.centos7
3.会使用Xshell连接远程服务器的操作

环境查看:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# uname -r
3.10.0-1160.83.1.el7.x86_64
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# ^C
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

进行安装:

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

image-20230417164932642

3.配置Docker仓库:
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

image-20230417165150492

4.更新软件包索引:
yum makecache faster

image-20230417165414588

5.安装最新版本的docker引擎:
yum -y install docker-ce docker-ce-cli containerd.io

image-20230417165843433

6.启动docker:
systemctl start docker
7.设置开机自动启动:
systemctl enable docker
8.测试:
docker run hello-world

image-20230417170128776

2.3 配置阿里云镜像加速:

1.登录阿里云找到容器镜像服务:

image-20230417183506922

2.找到镜像加速地址:

image-20230417183728034

3.配置使用:(Xshell中一步步执行)

在镜像加速器中选择centOS就会看到以下配置:

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

执行步骤如下:

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

image-20230417184305271

2.4 回顾HelloWorld镜像执行流程:

image-20230417184638656

2.5 Docker的底层原理:

(1)基础性原理:

docker是Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问,DockerServer接收到Docker-Client的指令,就会执行这个命令。

(2)Docker为什么比VM快:
image-20230417185933126

(1)Docker有着比虚拟机更少的抽象层
(2)Docker利用的是宿主机的内核,所以创建一个新的容器时候,docker不需要像虚拟机一样重新加载一个操作系统内核,虚拟机的加载Guest OS,分钟级别的,而docker利用宿主机的操作系统,省略了该步骤。

3. Docker 命令:

3.1 帮助命令:

(1) docker version  #docker的版本信息
(2) docker --info   #docker的详细信息
(3) docker  --help  #docker的万能命令

3.2 镜像命令:

3.2.1 docker images:

(1) 查看本地的主机上的镜像:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   19 months ago   13.3kB

image-20230419092044276

(2) 参数解释:

1.REPOSITORY:镜像的仓库源
2.TAG:镜像的标签
3.IMAGE ID:镜像的ID
4.CREATED:镜像的创建时间
5.SIZE:镜像的大小

(3) 可选项:

-a, --all             #列出所有的镜像             
-q, --quiet           #只显示镜像id

image-20230419092505337

(1) 搜索镜像:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker search mysql

image-20230419092750850

(2)可选项:

-f, --filter=STARS=3000 搜索出来的镜像就是STARS大于3000的

3.2.3 docker pull:

#下载镜像docker pull 镜像名 [:tag]
[root@localhost /]# docker pull mysql
Using default tag: latest #如果不写版本 默认latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete  #分层下载,docker images核心,联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #docker.io真实地址

#等价
docker pull mysql == docker pull docker.io/library/mysql:latest

#指定版本下载
[root@localhost /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

3.2.4 docker rmi:

删除镜像:

[root@ecs-300055 /]# docker rmi -f 镜像id #删除指定的镜像
[root@ecs-300055 /]# docker rmi -f 镜像id 镜像id 镜像id 镜像id #删除多个镜像
[root@ecs-300055 /]# docker rmi -f $(docker images -aq) #删除全部镜像

3.3 容器命令:

说明:我们有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习

docker pull centos

3.3.1 新建容器并启动:

docker run [可选参数] images

#参数说明
--name="Name" 容器名字 tomcat01 tomcat02用来区分容器
-d            后台运行方式
-it           使用交互方式,进入容器
-p            指定容器的端口 -p 8080:8080
     -p ip:主机端口:容器端口
     -p  主机端口映射到容器端口(常用)
     -p  容器端口
     容器端口
-P            随机指定端口


#测试
[root@ecs-300055 /]# docker run -it centos /bin/bash #启动并进入容器
[root@4029218a7e38 /]# ls #查看容器内的centos,基础版本,很多命令都是不完善的
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@4029218a7e38 /]# exit #退出容器
exit
[root@ecs-300055 /]# ls #查看服务器
bin  CloudResetPwdUpdateAgent  etc         lib         media  patch  run   sys  var
boot CloudrResetPwdAgent       home        lib64       mnt    proc   sbin  tmp  www
CloudResetPwdAgent  dev

3.3.2 列出所有运行的容器:

[root@ecs-300055 /]# docker ps 
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
-a   #列出当前正在运行的容器,顺带历史运行过的容器
-n=? #显示最近创建的容器
-q   #只显示容器的编号

3.3.3 退出容器:

exit     #直接退出容器并停止
ctrl+p+q #退出容器不停止

3.3.4 删除容器:

docker rm #容器id不能删除运行的容器,如果强制删除是rm -rf
rocker rm -f $(docker ps -aq) #删除全部容器
docker ps -a -q|xargs docker rm #删除所有的容器

3.3.5 启动以及停止容器的操作:

docker start 容器id          #启动容器
docker restart 容器id        #重启容器
docker stop 容器id           #停止当前正在运行的容器
docker kill 容器id           #强制停止当前容器

3.3.6 后台启动:

#docker run -d 镜像名!
[root@ecs-300055 /]# docker run -d centos

#问题docker ps 发现centos停止了

#常见的坑,docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止

#nginx 容器启动,发现自己提供服务,就会立刻停止,就是没有程序了

3.3.7 查看日志命令:

#docker logs  -f -t --tail #查看日志

#编写一个shell脚本(在容器中每隔1s钟输出一个liuyucheng)
[root@ecs-300055 /]# docker run -d centos /bin/sh -c "while true;do echo liuyucheng;sleep 1;done"

[root@ecs-300055 /]# docker ps
CONTAINER ID   IMAGE        
c4180c000d34   centos 

#显示日志(我们通过刚刚的容器id来查看对应的日志信息,就会发现一开始就显示了10条日志信息打印的liuyucheng)
[root@ecs-300055 /]# docker logs -tf --tail 10 c4180c000d34 #显示10条日志条数

3.3.8 查看容器的进程信息:

#命令
#docker top 容器id

[root@ecs-300055 /]# docker top c4180c000d34
UID      PID       PPID        C         STIME        TTY
root    104390    104371       0         13:54         ?
root    106863    104390       0         14:24         ?

3.3.9 查看镜像的元数据:

#命令
docker inspect 容器id

#测试
[root@ecs-300055 /]# docker inspect c4180c000d34
[
    {
        "Id": "c4180c000d348b0f3a0fe6cf6fddb0be07626e41876f7ae99e5c0e2eaad72532",
        "Created": "2022-10-14T05:54:53.272957973Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo kuangshen;sleep 1;done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 104390,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-10-14T05:54:53.534402239Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/c4180c000d348b0f3a0fe6cf6fddb0be07626e41876f7ae99e5c0e2eaad72532/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/c4180c000d348b0f3a0fe6cf6fddb0be07626e41876f7ae99e5c0e2eaad72532/hostname",
        "HostsPath": "/var/lib/docker/containers/c4180c000d348b0f3a0fe6cf6fddb0be07626e41876f7ae99e5c0e2eaad72532/hosts",
        "LogPath": "/var/lib/docker/containers/c4180c000d348b0f3a0fe6cf6fddb0be07626e41876f7ae99e5c0e2eaad72532/c4180c000d348b0f3a0fe6cf6fddb0be07626e41876f7ae99e5c0e2eaad72532-json.log",
        "Name": "/upbeat_fermat",
        "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,
            "CgroupnsMode": "host",
            "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/7c3c38a23afcd620aabc48ad3617e4ff98092ca1dba9066464c0d1b76ee7f82d-init/diff:/var/lib/docker/overlay2/0eff6e6a1fc9a79822588fb0a938399238a8d9f2523c2dd4aad8d0a7635b4cf1/diff",
                "MergedDir": "/var/lib/docker/overlay2/7c3c38a23afcd620aabc48ad3617e4ff98092ca1dba9066464c0d1b76ee7f82d/merged",
                "UpperDir": "/var/lib/docker/overlay2/7c3c38a23afcd620aabc48ad3617e4ff98092ca1dba9066464c0d1b76ee7f82d/diff",
                "WorkDir": "/var/lib/docker/overlay2/7c3c38a23afcd620aabc48ad3617e4ff98092ca1dba9066464c0d1b76ee7f82d/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "c4180c000d34",
            "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 kuangshen;sleep 1;done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "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": "532a4f77fbda276a3e5c8617b12654163c5309f282fc69830efffa0ebecdfe47",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/532a4f77fbda",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "3738eebbeaf302662c650ff15c5d77b6faa29ab35b25da1f45aa7a635130a301",
            "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": "8117f3824ee897e4394d97a15ca1caa6dae0808f2bf00edda0e8c3b84856bea5",
                    "EndpointID": "3738eebbeaf302662c650ff15c5d77b6faa29ab35b25da1f45aa7a635130a301",
                    "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
                }
            }
        }
    }
]

3.3 10.进入当前正在运行的容器:

#我们通常容器都是使用后台运行的,需要进入容器,修改一些配置

#命令
docker exec -it 容器id bashshell

#测试
[root@ecs-300055 /]# docker exec -it c4180c000d34 /bin/bash
[root@c4180c000d34 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@c4180c000d34 /]# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 05:54 ?        00:00:00 /bin/sh -c while true;do echo kuangshen;sleep 1;done
root        2440       0  0 06:35 pts/0    00:00:00 /bin/bash
root        2461       1  0 06:35 ?        00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root        2462    2440  0 06:35 pts/0    00:00:00 ps -ef

#方法二
docker attach 容器id

#测试
[root@ecs-300055]~# docker attach c4180c000d34 #正在执行当前代码


#docker exec   #进入容器后开启一个新的终端,可以在里面操作(常用)
#docker attach #进入容器正在执行的终端,不会启动新的进程

3.3.11 从容器内拷贝文件到主机:

docker cp 容器id:容器内路径  目的的主机路径

#查看当前文件夹下
[root@ecs-300055]/home# ls
www

#创建并运行容器
[root@ecs-300055]/home# docker run -it centos
[root@5dd3b22b9824 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@5dd3b22b9824 /]# cd home/
[root@5dd3b22b9824 home]# ls

#新建一个文件
[root@5dd3b22b9824 home]# touch jkdb.py
[root@5dd3b22b9824 home]# ls
jkdb.py
[root@5dd3b22b9824 home]# exit
exit
[root@ecs-300055]/home# ls
www
[root@ecs-300055]/home# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                     PORTS     NAMES
5dd3b22b9824   centos    "/bin/bash"              33 seconds ago   Exited (0) 4 seconds ago             naughty_shockley

#将文件拷贝到主机上
[root@ecs-300055]/home# docker cp 5dd3b22b9824:/home/jkdb.py /home
[root@ecs-300055]/home# ls
jkdb.py  www

#拷贝是个手动过程,未来我们使用-v卷的技术,可以实现

3.4 小结:

img

4. Docker 镜像:

4.1 实践部署镜像:

Docker 安装 Nginx:
#搜索镜像 search 建议去网站搜索
#拉取镜像 pull
#运行测试

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
nginx         latest    605c77e624dd   15 months ago   141MB
hello-world   latest    feb5d9fea6a5   19 months ago   13.3kB
centos        latest    5d0da3dc9764   19 months ago   231MB

#-d后台运行 
#--name给容器命名
#-p宿主机端口:容器内部端口(可以通过公网的3344访问到docker的nginx镜像,nginx运行的内部端口80)
[root@ecs-300055]/home# docker run -d --name nginx01 -p 3344:80 nginx

image-20230419105402051

这里注意如果是使用的阿里云服务器记得一定要开放3344安全组规则,另外如果开启了服务器的防火墙,就要为防火墙配置放行3344端口规则。

测试:是否可以访问:
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# curl localhost:3344

image-20230419105637778

出现以上的显示说明下载与运行成功。

解释3344:80端口开放的原理:(端口暴露的概念)

image-20230419134149703

image-20230419134423990

思考一个问题:
我们每一次改动nginx配置文件,都需进入容器内部十分的麻烦,我要是可以在容器的外部提供一个映射路径,达到在容器外修改文件,容器内就可以自动修改。(-v Docker的容器卷技术)。

Docker 装Tomcat:
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker run -it tomcat:9.0
# 我们之前启动都是后台启动,停止了容器之后,容器还是可以查到了,但上述命令时一般是用来测试
# 用完就删除
docker pull tomcat:9.0

# 进入容器
docker exec -it tomcat01 /bin/bash

# 发现问题:
1.linux命令少了, 
2. webapps下内容为空,阿里云净吸纳过默认是最小的镜像,所有不必要的都剔除了,保证最小可运行环境即可

解决方案:

我们在webapps.dist目录下找到了对应的项目文件,我们将该文件下的东西全部放置到webapps目录下

root@ba33e8d8a607:/usr/local/tomcat# cd webapps.dist
root@ba33e8d8a607:/usr/local/tomcat/webapps.dist# ls
ROOT  docs  examples  host-manager  manager
root@ba33e8d8a607:/usr/local/tomcat/webapps.dist# cd ../
root@ba33e8d8a607:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@ba33e8d8a607:/usr/local/tomcat# cd webapps
root@ba33e8d8a607:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager

再次访问公网阿里云IP加335端口:成功

image-20230419141327003

思考问题:我们以后要部署项目,如果每一个都要进入容器会很麻烦,要是可以在容器外部提供一个映射路径,达到在容器外部部署项目文件,在容器内部就可以自动更新。

Docker部署ES+Kibana
# es 暴露的端口很多
# es 十分的耗内存
# es 的数据一般需要放置到安全目录! 挂载
# --net somenetwork Docker的网络配置
 
# 启动elasticsearch
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2

# 启动了linux就卡主了,docker stats 查看cpu状态

# 增加内存限制,修改配置文件 -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

使用:Kibana连接ElasticSearch.

4.2 Portainer可视化面板安装:

基本管理镜像的工具:(docker的图像化管理工具)

  • portainer(先使用这个)
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
 
# 测试
[root@iZ2zeg4ytp0whqtmxbsqiiZ home]# curl localhost:8088
<!DOCTYPE html
><html lang="en" ng-app="portainer">
 
# 外网访问 http://ip:8088

image-20230419145230967

image-20230419145251458

image-20230419145350488

  • Rancher(CI/CD再用):持续集成持续部署

4.3 Docker 镜像原理之联合文件系统:

1.镜像是什么?

镜像就是轻量级别,可执行的独立软件包,用来打包软件运行环境和基于运行环境所开发的软件,它包含运行某个软件所需要的所有内容,包括代码,运行时,库,环境变量和配置文件

所有的应用直接打包docker镜像,就可以直接跑起来!

如何得到镜像:

  • 从远程仓库下载
  • 同一公司拷贝
  • 自己制作镜像DockerFile
UnionFS(联合文件系统)
UnionFS:Union文件系统是一种分层,轻量级别并且高性能的文件系统,他支持对文件系统的修改作为一次提交来进行层层叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像,可以制作各种具体应用的镜像。

因此:我们在pull下拉文件时候就会一层层下载。

Docker镜像加载原理
docker的镜像实际是由一层层文件系统组成,这种层级文件系统称之为UnionFS
bootfs主要包含bootloader和kernel,bootloader主要是引导加载Kernel,Linux刚启动时候会加载bootfs文件系统,在Docker镜像的最底层是bootfs.这一层与我们典型的Linux/Unix是一样的。包含boot加载器和内核。当boot加载完成后整个内核就在内存当中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs

image-20230419151211050

4.4 Docker分层的理解:

image-20230421135515773

image-20230421135650878

image-20230421135853326

4.5 commit镜像:

Docker镜像都是只读的,当容器启动时候,一个新的可写层将被加载到镜像层的顶部,这一层就是我们通常所说的容器层,容器层之下都叫作镜像层:

image-20230421141201318

commit镜像:

docker commit 提交容器成为一个新的版本
 
# 命令和git 原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
 
docker commit -a="liuyuhceng" -m="add webapps app" d7as56hfhgh tomcat007:1.0

实战测试:

# 1. 启动一个默认的tomcat
# 2. 发现这个默认的tomcat是没有webapps应用, 镜像的原因,官方镜像默认webapps下面是没有内容的
# 3. 我自己拷贝进去了基本的文件
# 4. 将我们操作过的容器通过commit提价为一个镜镜像!我们以后就使用我们自己制作的镜像了

5. Docker 容器数据卷:

5.1什么是Docker的容器数据卷:

将应用和环境打包成一个镜像

数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化

例如:Mysql,容器删了,如果数据存放在容器当中,那么就是删库跑路了,因此我们希望Mysql的数据可以存储在本地当中!

要求:容器之间需要有数据共享的技术!Docker容器中产生的数据可以同步到本地当中!

解决上述的要求我们可以采用Docker当中的卷技术,也就是目录挂载,将我们容器内的目录挂载到linux目录上面。

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

5.2 使用数据卷:

方式一:直接使用命令来挂载 -v
docker run -it -v 主机目录:容器目录
 
[root@iZ2zeg4ytp0whqtmxbsqiiZ home]# docker run -it -v /home/ceshi:/home centos /bin/bash

查看容器运行的详细的信息:

docker inspect  [contained ID]

image-20230421145313179

测试同步:

image-20230421150005341

再来测试:

1.停止容器
2.主机上修改文件
3.启动容器
4.容器内的数据依旧是同步的!

5.3 实战部署Mysql:

解决Mysql的数据持久化问题!

将Mysql的容器与数据分开放置,数据需要挂载到外部的文件

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker search mysql
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Pull complete 
93619dbc5b36: Pull complete 
99da31dd6142: Pull complete 
626033c43d70: Pull complete 
37d5d7efb64e: Pull complete 
ac563158d721: Pull complete 
d2ba16033dad: Pull complete 
0ceb82207cd7: Pull complete 
37f2405cae96: Pull complete 
e2482e017e53: Pull complete 
70deed891d42: Pull complete 
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# 

详细运行流程:

-d      # 后台运行
-p      # 端口隐射
-v      # 卷挂载
-e      # 环境配置
--name  # 容器的名字
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker run -d -p 3344: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

image-20230421152343034

再此查看发现已经形成了数据卷挂载到了外部:

image-20230421152652279

5.4 具名挂载与匿名挂载:

# 匿名挂载
-v 容器内路径(不指定主机的路径)
docker run -d -P --name nginx01 -v /etc/nginx nginx     # -P 随机指定端口
[root@iZ2ze6y7ulztxu0enw2s8sZ data]# docker volume ls
DRIVER    VOLUME NAME
local     1c76bca13ae3c096e7409995cb6644a8eeaa3601bd0cd54865864672ed9e65d0
local     17dc3ab8640c521aa44970d006abb5e6cf4c8d85e2a88a55c9b5fe0b073ecd00

# 这里发现有很多的VOLUME NAME其实就是真实存在的目录,因为我们-v后面只写了容器内路径并没有写容器外的路径

[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
26da1ec7d4994c76e80134d24d82403a254a4e1d84ec65d5f286000105c3da17
[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
26da1ec7d499        nginx               "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds        0.0.0.0:32769->80/tcp   nginx02
486de1da03cb        nginx               "/docker-entrypoint.…"   3 minutes ago       Up 3 minutes        0.0.0.0:32768->80/tcp   nginx01
[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker volume ls
DRIVER              VOLUME NAME
local               561b81a03506f31d45ada3f9fb7bd8d7c9b5e0f826c877221a17e45d4c80e096
local               36083fb6ca083005094cbd49572a0bffeec6daadfbc5ce772909bb00be760882
local               juming-nginx
# 通过-v 卷名:容器内的路径
# 查看一下这个卷
# docker volume inspect juming-nginx
 
[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker volume inspect juming-nginx
[
  {
      "CreatedAt": "2020-08-12T18:15:21+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/xxxxx/_data

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

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

拓展:

# 通过 -v 容器内容路径 ro rw 改变读写权限
ro  readonly    # 只读
rw  readwrite   # 可读可写
 
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
 
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内容无法操作

6. DockerFile:

紧跟第五小节方式一:

方式二:采用DockerFile的方式来进行

6.1 初识DockerFile:

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

通过这个脚本可以生成镜像,镜像是一层层的,脚本一个个的命令,每一个命令都是一层!

[root@iZ2ze6y7ulztxu0enw2s8sZ docker-test-volume]# vim dockerfile1
# 创建一个dockerfile文件, 名字可以随机
# 文件的内容 指定(大写) 参数
 
FROM centos
 
VOLUME ["volume01", "volume02"]
 
CMD echo "----end----"
CMD /bin/bash
 
# 这里的每一个命令都是镜像的一层!
[root@iZ2ze6y7ulztxu0enw2s8sZ docker-test-volume]# ls
dockerfile1
[root@iZ2ze6y7ulztxu0enw2s8sZ docker-test-volume]# cat dockerfile1 
FROM centos

VOLUME ["volume01","volume2"]

CMD echo "-----end-----"

CMD /bin/bash

[root@iZ2ze6y7ulztxu0enw2s8sZ docker-test-volume]# 
[root@iZ2ze6y7ulztxu0enw2s8sZ docker-test-volume]# docker build -f dockerfile1 -t liuyucheng/centos:1.0 .

image-20230421161032141

image-20230421162120342

这个卷和外部一定有一个同步的目录!

docker inspect [contained ID]

image-20230421162308410

6.2 数据卷容器:

解决的是多个Mysql同步数据的问题!

也就是利用一个父容器给另外多个子容器提供数据,实现数据的共享,因此此时的父容器叫作数据卷容器。

image-20230421162807863

我们首先建立两个容器:

docker run -it --name docker01 liuyucheng/centos:1.0
docker run -it --name docker2 --volumes-from docker01  liuyucheng/centos:1.0

测试:在docker01的volume01目录中创建文件,在docker2中是否会被自动创建同步,答案是可以

image-20230421164045207

结论

容器间的数虽然是依赖关系,但是只要更新就是双向拷贝概念,父容器删除文件,依赖父容器的子容器会依然持有响应的文件。

容器之间配置信息的传递, 数据卷容器的生命周期一直持续到没有容器使用为止。

但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!

6.3再理解DockerFile:

dockerFile是用来构建docker镜像的文件!命令参数脚本!

步骤:

1.编写一个dockerFile文件
2.docker build构建一个镜像
3.docker run 运行镜像
4.docker push发布镜像(Docker Hub, 阿里云镜像)

查看centos镜像制作方式:

image-20230421190403506

image-20230421190430839

很多官方镜像都像是基础包,很多功能都不具备,我们通常会自己搭建自己的镜像!官方既然可以制作镜像,能我们一样可以!

6.4 DockerFile的构建过程:

基础知识:

(1)每个保留关键字(指令)都是必须大写字母
(2)执行从上到下顺序执行
(3)# 表示注释
(4)每个指令都会创建提交一个新的镜像层,并提交!

img

dockerFile是面向开发的, 我们以后要发布项目, 做镜像, 就需要编写dockefile文件, 这个文件十分简单!

Docker镜像逐渐成为企业的交互标准,必须要掌握!

步骤:开发,部署, 运维..... 缺一不可!

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

DockerImages: 通过DockerFile构建生成的镜像, 最终发布和运行的产品!

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

6.5 DockerFile指令说明:

image-20230421192652691

FROM            # 基础镜像,一切从这里开始构建
MAINTAINER      # 镜像是谁写的, 姓名+邮箱
RUN             # 镜像构建的时候需要运行的命令
ADD             # 步骤, tomcat镜像, 这个tomcat压缩包!添加内容
WORKDIR         # 镜像的工作目录
VOLUME          # 挂载的目录
EXPOSE          # 保留端口配置
CMD             # 指定这个容器启动的时候要运行的命令,只有最后一个会生效可被替代
ENTRYPOINT      # 指定这个容器启动的时候要运行的命令, 可以追加命令
ONBUILD         # 当构建一个被继承DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY            # 类似ADD, 将我们文件拷贝到镜像中
ENV             # 构建的时候设置环境变量!

6.6 构建自己的centos镜像:

官方所给出的centos镜像没有vim命令,没有ifconfig判定自己IP地址命令,因此需要自己构建自己的镜像:

FROM centos:7

MAINTAINER liuyucheng<cqlyc1117@163.com>

ENV MYPATH /usr/local (希望已进入centos系统就显示的所在目录)

WORKDIR $MYPATH

RUN yum -y install vim

RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash

image-20230421195457803

我们再次进入自己所制作的centos镜像:

docker run -it mycentos:1.0

命令均可以运行了:

image-20230421195849636

我们还可以通过命令来了解镜像制作的历史步骤:

docker history [contained ID]

6.7 将centos镜像进行发布

1.发布镜像到DockerHub

(1)地址:What is Docker Hub? | Docker 注册自己的账号

(2)确定自己账号是否可以登录:

image-20230422095009606

(3)在我们自己的服务器上提交自己的镜像:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker login --help

Usage:  docker login [OPTIONS] [SERVER]

Log in to a registry.
If no server is specified, the default is defined by the daemon.

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username

image-20230422095417901

采用将镜像进行上传:

# push到我们的服务器上
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker push mycentos:1.0
The push refers to repository [docker.io/library/mycentos]
a7bd9a2294ff: Preparing 
d37958739774: Preparing 
5f70bf18a086: Preparing 
174f56854903: Preparing 
denied: requested access to the resource is denied

# push镜像的问题?
The push refers to repository [docker.io/1314520007/diytomcat]
An image does not exist locally with the tag: 1314520007/diytomcat
 
# 解决,增加一个tag
docker tag diytomcat 1314520007/tomcat:1.0

image-20230422095736354

增加tag信息:

image-20230422100648041

一般dockerHub上传都很慢,我们需要耐心的等待.

2.将我们的镜像发布到阿里云镜像服务上
1.登录阿里云
2.找到容器镜像服务
3.创建命名空间
4.创建容器镜像

(1)创建命名空间:

image-20230422101925138

(2)创建容器镜像:

image-20230422102204483

image-20230422102227715

(3)点击仓库名称可以很清楚的看到如何一步步制作自己的镜像并发布到阿里云镜像服务当中

(4)镜像真的推送成功以后就会在镜像版本栏目有对应自己的镜像

6.8 小结:

image-20230422103409386

7. Docker 的网络原理:

7.1 Docker0网络:

image-20230422104720809

三个网络:
docker是如何处理容器的网络访问的?

我们在测试Kibana连接ES时就留下了一个问题:

image-20230422105042058

# 查看容器内的网络地址 IP addr:
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# 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
46: eth0@if47: <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

注意这里可能会报以下错误:

因为我们下载的Tomcat是纯净的系统

[root@localhost ~]# docker exec -it tomcat01 ip addr
OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown

解决方案参考博客:

(90条消息) Docker 报错:OCI runtime exec failed: exec failed: unable to start container process: exec: “xxx“: exec_GaleTeng的博客-CSDN博客

# 会发现容器启动的时候得到一个eth0@if47 ip地址,其实这就是docker分配的
# 思考一个问题:linux能不能ping通容器?
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# 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.039 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.041 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.046 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.049 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.046 ms
64 bytes from 172.17.0.2: icmp_seq=6 ttl=64 time=0.059 ms
64 bytes from 172.17.0.2: icmp_seq=7 ttl=64 time=0.050 ms
64 bytes from 172.17.0.2: icmp_seq=8 ttl=64 time=0.044 ms
64 bytes from 172.17.0.2: icmp_seq=9 ttl=64 time=0.045 ms
64 bytes from 172.17.0.2: icmp_seq=10 ttl=64 time=0.044 ms
64 bytes from 172.17.0.2: icmp_seq=11 ttl=64 time=0.048 ms
64 bytes from 172.17.0.2: icmp_seq=12 ttl=64 time=0.046 ms
64 bytes from 172.17.0.2: icmp_seq=13 ttl=64 time=0.049 ms
64 bytes from 172.17.0.2: icmp_seq=14 ttl=64 time=0.046 ms
--- 172.17.0.2 ping statistics ---
29 packets transmitted, 29 received, 0% packet loss, time 28000ms
rtt min/avg/max/mdev = 0.039/0.048/0.059/0.006 ms
# linux可以ping通docker容器内部
原理

我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是veth-pair技术!

我们再次测试:ip addr:

image-20230422140904507

# 我们发现这个容器带来网卡,都是一对对的
# veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
# 正因为有这个特性,veth-pair充当一个桥梁, 连接各种虚拟网络设备
# OpenStac, Docker容器之间的链接,OVS的链接, 都是使用veth-pair技术

再准备一个tomcat03:

image-20230422143028534

我们测试一下Tomcat02与Tomcat03能否能ping的通:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker exec -it tomcat02 ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.049 ms
^C
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.049/0.060/0.079/0.013 ms

结论是:容器与容器之间是可以相互ping通的。

先来查看下容器的信息:

image-20230422143634767

绘制一个网络模型图:

image-20230422144801106

结论:tomcat02与tomcat03是共用一个路由器,都是docker0

所有容器不指定网络的情况下,都是docker0路由的,docker会给我门容器分配一个默认的可用的IP

注意docker分配IP时候给我们显示的是采用CIDR无分类域间路由表示法。

思考一个场景:我们编写一个微服务, database url = ip;如果不重启项目,但是我们docker中ip地址改变,我们希望微服务的Mybatis中参数配置也需要动态更新。
类似:
 SpringCloudAlibaba中:Feign:我们采用的是根据服务名来进行远程访问,而不是根据IP地址

因为我们先试一下能否根据names 来ping通:发现不可行

image-20230422150506075

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# 

解决方案:采用 --link:

[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker run -d -P  --name tomcat05 --link tomcat03 tomcat
3a2bcaba804c5980d94d168457c436fbd139820be2ee77246888f1744e6bb473
[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker ps
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED             STATUS             PORTS                                         NAMES
77ece71ab4f4   tomcat    "catalina.sh run"   10 minutes ago      Up 10 minutes      0.0.0.0:32771->8080/tcp, :::32771->8080/tcp   tomcat05
b44e777d68b9   tomcat    "catalina.sh run"   11 minutes ago      Up 11 minutes      0.0.0.0:32770->8080/tcp, :::32770->8080/tcp   tomcat04
33967ef8891b   tomcat    "catalina.sh run"   About an hour ago   Up About an hour   0.0.0.0:32769->8080/tcp, :::32769->8080/tcp   tomcat03
5c3ab0050e8e   tomcat    "catalina.sh run"   4 hours ago         Up 4 hours         0.0.0.0:32768->8080/tcp, :::32768->8080/tcp   tomcat02
[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker exec -it tomcat05 ping tomcat03
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.129 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.100 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.110 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.107 ms
 
# 反向可以ping通吗?
[root@iZ2zeg4ytp0whqtmxbsqiiZ ~]# docker exec -it tomcat03 ping tomcat05
ping: tomcat03: Name or service not known

我们需要查看一下当前docker0一些信息:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
05af09696ded   bridge    bridge    local
24589a199216   host      host      local
3db1180720b1   none      null      local
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker network inspect 05af09696ded

image-20230422153011022

其实这个tomcat05就是在本地配置了tomcat03的配置:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker exec -it tomcat05 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	tomcat03 33967ef8891b
172.17.0.5	77ece71ab4f4

本质探究:--link 就是我们在hosts配置中增加了一个172.17.0.3 tomcat03 33967ef8891b

我们现在使用docker已经不建议使用--link了!

我们自定义网络不使用docker0

7.3 自定义网络:

容器互联:

查看所有的docker网络

image-20230422154135159

网络模式:

bridge: 桥接模式,桥接 docker 默认,自己创建的也是用brdge模式
none: 不配置网络
host: 和宿主机共享网络
container:容器网络连通!(用的少, 局限很大)

测试

# 我们直接启动的命令默认有一个 --net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
 
# docker0特点,默认,容器名不能访问, --link可以打通连接!
# 我们可以自定义一个网络!
# --driver bridge
# --subnet 192.168.0.0/16 可以支持255*255个网络 192.168.0.2 ~ 192.168.255.254
# --gateway 192.168.0.1
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
16632a0c84f979c2c412541d0493d4aa718f1de114d8950d5a4da1626c34d5f5
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
05af09696ded   bridge    bridge    local
24589a199216   host      host      local
16632a0c84f9   mynet     bridge    local
3db1180720b1   none      null      local
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# 

测试看自己的网络:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "16632a0c84f979c2c412541d0493d4aa718f1de114d8950d5a4da1626c34d5f5",
        "Created": "2023-04-22T15:49:38.492953555+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# 

在自己创建测网络下创建两个tomcat容器:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
9662fbba0282c21a72221e112f9dbcfedfc0793baee4a5d7be49f69ace8f55bc
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED         STATUS        PORTS                                         NAMES
9662fbba0282   tomcat    "catalina.sh run"   2 seconds ago   Up 1 second   0.0.0.0:32772->8080/tcp, :::32772->8080/tcp   tomcat-net-01
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
0d3617644b16dc02e5603b496ac1186c1ca850b2f22c42462052b329f73b1a42
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                                         NAMES
0d3617644b16   tomcat    "catalina.sh run"   2 seconds ago    Up 1 second     0.0.0.0:32773->8080/tcp, :::32773->8080/tcp   tomcat-net-02
9662fbba0282   tomcat    "catalina.sh run"   25 seconds ago   Up 24 seconds   0.0.0.0:32772->8080/tcp, :::32772->8080/tcp   tomcat-net-01
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "16632a0c84f979c2c412541d0493d4aa718f1de114d8950d5a4da1626c34d5f5",
        "Created": "2023-04-22T15:49:38.492953555+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "0d3617644b16dc02e5603b496ac1186c1ca850b2f22c42462052b329f73b1a42": {
                "Name": "tomcat-net-02",
                "EndpointID": "74aabe369e9a76c889cd939c6ae15f69a09561a8fe39df7766969edfcae419e4",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "9662fbba0282c21a72221e112f9dbcfedfc0793baee4a5d7be49f69ace8f55bc": {
                "Name": "tomcat-net-01",
                "EndpointID": "44e32396dd0c02437db46a2588335eb7134d3c1803f36d76fc0cfabac7c02ef1",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
}

我们再次测试:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.046 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.045 ms
64 bytes from 192.168.0.3: icmp_seq=4 ttl=64 time=0.046 ms
64 bytes from 192.168.0.3: icmp_seq=5 ttl=64 time=0.045 ms
64 bytes from 192.168.0.3: icmp_seq=6 ttl=64 time=0.046 ms
64 bytes from 192.168.0.3: icmp_seq=7 ttl=64 time=0.068 ms
^C
--- 192.168.0.3 ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 5999ms
rtt min/avg/max/mdev = 0.045/0.051/0.068/0.009 ms
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.035 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.047 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.049 ms
^C
--- tomcat-net-02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.035/0.043/0.049/0.006 ms
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# 

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

好处:

redis - 不同的集群使用不同的网络,保证集群时安全和健康的

mysql - 不同的集群使用不同的网络,保证集群时安全和健康的

即redis所有的节点处于假设192.161.0.0,mysql所有的节点处于192.161.0.0,他们之间可以互联嘛?

7.4 网络联通:

先配置环境:

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                                         NAMES
0d3617644b16   tomcat    "catalina.sh run"   22 minutes ago   Up 22 minutes   0.0.0.0:32773->8080/tcp, :::32773->8080/tcp   tomcat-net-02
9662fbba0282   tomcat    "catalina.sh run"   22 minutes ago   Up 22 minutes   0.0.0.0:32772->8080/tcp, :::32772->8080/tcp   tomcat-net-01
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker run -d -P --name tomcat01 tomcat
c4a46b91068e0c72e3e7c5f03a019b15405164474a2ce227a12c3ff43459cb67
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker run -d -P --name tomcat02 tomcat
e9cc9677d0cf954f65106ace36b70ef87ea5c8f0ad9e414c65e750698a8dad93
[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                                         NAMES
e9cc9677d0cf   tomcat    "catalina.sh run"   6 seconds ago    Up 5 seconds    0.0.0.0:32775->8080/tcp, :::32775->8080/tcp   tomcat02
c4a46b91068e   tomcat    "catalina.sh run"   12 seconds ago   Up 12 seconds   0.0.0.0:32774->8080/tcp, :::32774->8080/tcp   tomcat01
0d3617644b16   tomcat    "catalina.sh run"   23 minutes ago   Up 23 minutes   0.0.0.0:32773->8080/tcp, :::32773->8080/tcp   tomcat-net-02
9662fbba0282   tomcat    "catalina.sh run"   23 minutes ago   Up 23 minutes   0.0.0.0:32772->8080/tcp, :::32772->8080/tcp   tomcat-net-01

方法:
image-20230422162850550

image-20230422162925600

测试打通tomcat01到mynet:

image-20230422163125615

[root@iZ2ze6y7ulztxu0enw2s8sZ ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.063 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.048 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=4 ttl=64 time=0.051 ms
^C
--- tomcat-net-01 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.048/0.053/0.063/0.005 ms

posted @ 2023-04-22 16:43  LycCj  阅读(368)  评论(0编辑  收藏  举报