安装Docker

安装

帮助文档

# 1. 卸载旧的版本
sudo 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. 设置镜像仓库
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo # 默认是国外的
    
sudo yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 推荐使用阿里云镜像
    
# 更新软件包索引
yum makecache fast
    
# 4. 安装docker docker-ce  社区 ee 企业版
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 5. 启动docker
systemctl start docker

# 6. 查看docker是否安装成功
docker version

image-20230704201451933

# 7. hello-world
docker run hello-world
# 8. 查看一下下载的这个 hello-world镜像
[root@centos-liunx-7 ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   12 months ago   13.3kB

了解: 卸载docker

# 1. 卸载依赖
sudo yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 2. 删除资源
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

# /var/lib/docker docker的默认工作路径

阿里云镜像加速

  1. 打开阿里云,找到镜像容器服务

    image-20221001232518233

  2. 找到镜像加速器

    image-20230704201206164

  3. 配置使用

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

回顾HelloWorld流程

image-20230704201057603

image-20230704201112141

底层原理

Docker是怎么工作的?

Docker是一个Client - Server结构的系统,Docker的守护进程运行在主机上.通过Scoket从客户端访问!

image-20230704201256778

Docker为什么比VM快?

  1. Docker有着比虚拟机更少的抽象层
  2. docker利用的是宿主机的内核, vm需要Guest OS

    image-20230704201321810

    所以说,新建一个容器的时候,docker不需要向虚拟机一样重新加载一个操作系统内核,避免引导.虚拟机是加载Guest OS,分钟级别的,而docker是利用 宿主机的操作系统,省略了这个复杂的过程,秒级!

Docker的常用命令

帮助命令

docker version     # 显示docker的版本信息
docker info           # docker的系统信息,包裹镜像和容器的数量
docker 命令 --help  # 万能命令

帮助文档的地址: https://docs.docker.com/engine/reference/commandline/docker/

镜像命令

docker images 查看所有本地的主机上的镜像

[root@centos-liunx-7 /]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   12 months ago   13.3kB

# 解释
REPOSITORY    镜像的仓库源
TAG            镜像的标签
IMAGE ID    镜像的ID
CREATE        镜像的创建时间
SIZE        镜像的大小

# 可选项
  -a, --all             显示所有镜像
  -q, --quiet           只显示镜像的ID

docker search 镜像的搜索命令

# docker search 镜像名称
[root@centos-liunx-7 /]# docker search mysql
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   13234     [OK]       
mariadb                         MariaDB Server is a high performing open sou…   5062      [OK]       
phpmyadmin                      phpMyAdmin - A web interface for MySQL and M…   640       [OK]       
percona                         Percona Server is a fork of the MySQL relati…   588       [OK]       
bitnami/mysql                   Bitnami MySQL Docker Image                      77                   [OK]


# 可选项
    -f stars=3000  # 搜索出来的镜像就是stars大于3000的
[root@centos-liunx-7 /]# docker search mysql -f stars=3000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   13234     [OK]       
mariadb   MariaDB Server is a high performing open sou…   5062      [OK] 

下载镜像 docker pull

# 下载镜像  docker pull 镜像名[:tag]
[root@centos-liunx-7 /]# docker pull mysql
Using default tag: latest    # 如果不写 tag,默认就是latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete     # 分层下载,docker image的核心 联合文件系统
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 pull mysql 等价于 docker pull docker.io/library/mysql:latest

# 指定版本下载
[root@centos-liunx-7 /]# 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

docker rmi 删除镜像

[root@centos-liunx-7 /]# docker rmi -f 镜像ID    # 删除指定的容器
[root@centos-liunx-7 /]# docker rmi -f 镜像ID 容器ID 容器ID # 删除多个容器
[root@centos-liunx-7 /]# docker rmi -f $(docker images -aq)    # 删除全部的容器

容器命令

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

docker pull centos

新建容器并启动

docker run [可选参数] image

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

# 测试,启动并进入容器
[root@centos-liunx-7 /]# docker run -it centos /bin/bash
[root@ab7ab1d9dc9b /]# ls    # 查看容器内的centos,基础版本,很多命令是不完善的
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 从容器中退回主机
[root@ab7ab1d9dc9b /]# exit
exit
[root@centos-liunx-7 /]# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

列出所有的运行中的容器

# docker ps 命令
    # 列出当前正在运行的容器
-a  # 列出当前正在运行的容器+带出历史运行过的容器
-n=? # 显示最近创建的容器
-q  # 只显示容器的编号

[root@centos-liunx-7 /]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED             STATUS                         PORTS     NAMES
ab7ab1d9dc9b   centos         "/bin/bash"   6 minutes ago       Exited (0) 2 minutes ago                 frosty_feistel
e19001022375   feb5d9fea6a5   "/hello"      About an hour ago   Exited (0) About an hour ago             romantic_antonelli

退出容器

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

删除容器

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

启动和停止容器的操作

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

常用其他命令

后台启动容器

# 命令 docker run -d 镜像名!
[root@centos-liunx-7 ~]# docker run -d centos

# 问题docker ps,发现 centos 停止了

# 常见的坑: docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻定制,就是没有程序了

查看日志命令

docker logs -f -t -n 条数 容器ID
    -t        显示日期+时间
    -n 10    显示最近10条

查看容器中的进程信息 ps

# 命令 docker top 容器ID
[root@centos-liunx-7 ~]# docker top 293933b1a937
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                5269                5251                0                   11:46               pts/0               00:00:00            /bin/bash
[root@centos-liunx-7 ~]

查看镜像的元数据

# 命令 docker inspect 容器id
# 测试
[root@centos-liunx-7 ~]# docker inspect 293933b1a937
[
    {
        "Id": "293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23",
        "Created": "2022-10-02T03:46:19.579531063Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 5269,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-10-02T03:46:19.862987449Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23/hostname",
        "HostsPath": "/var/lib/docker/containers/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23/hosts",
        "LogPath": "/var/lib/docker/containers/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23/293933b1a937a488e012418414479f162d5b6bec3c01d054f4f30296f2ec9f23-json.log",
        "Name": "/romantic_cohen",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": [
            "d959bc38ccb4a8f5f7f048538a5683e29f9091d6c7a2662b8afd0e207fdc93f8",
            "9b3b78add31342988b556a4f1d50dab6e343e01922bf2d0d630cf57552c21d21"
        ],
        "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/c6552c7ff8fbafce9987c79b65f8007433b054ec7d7718627b036db45665f2e3-init/diff:/var/lib/docker/overlay2/d60d4305d3caf9a7a1b2b1a4f8cea9d0972e6672ea996ea443730d0f414b2147/diff",
                "MergedDir": "/var/lib/docker/overlay2/c6552c7ff8fbafce9987c79b65f8007433b054ec7d7718627b036db45665f2e3/merged",
                "UpperDir": "/var/lib/docker/overlay2/c6552c7ff8fbafce9987c79b65f8007433b054ec7d7718627b036db45665f2e3/diff",
                "WorkDir": "/var/lib/docker/overlay2/c6552c7ff8fbafce9987c79b65f8007433b054ec7d7718627b036db45665f2e3/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "293933b1a937",
            "Domainname": "",
            "User": "",
            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "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": "da5bbf74792f2eb5e8ad6160bb67301616f79f8f2424b19171d7ee5e8582553d",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/da5bbf74792f",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "a274ca41faf2a0e7dae8088cb5c78862a090d39535ec91c4eae676837be0a3a7",
            "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": "1db544b9e9042fcde5347650f180de98bc17f8499545c386ccc2bd19507e420f",
                    "EndpointID": "a274ca41faf2a0e7dae8088cb5c78862a090d39535ec91c4eae676837be0a3a7",
                    "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
                }
            }
        }
    }
]
[root@centos-liunx-7 ~]# 

进入当前正在运行的容器

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

# 命令
docker exec -it 容器id bashShell

# 测试
[root@centos-liunx-7 ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
293933b1a937   centos    "/bin/bash"   22 minutes ago   Up 22 minutes             romantic_cohen
[root@centos-liunx-7 ~]# docker exec -it 293933b1a937 /bin/bash
[root@293933b1a937 /]# ps
   PID TTY          TIME CMD
    50 pts/3    00:00:00 bash
    64 pts/3    00:00:00 ps
[root@293933b1a937 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@293933b1a937 /]# ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 03:46 pts/0    00:00:00 /bin/bash
root         20      0  0 04:01 pts/1    00:00:00 /bin/bash
root         36      0  0 04:02 pts/2    00:00:00 /bin/bash
root         50      0  0 04:08 pts/3    00:00:00 /bin/bash
root         66     50  0 04:08 pts/3    00:00:00 ps -ef

# 方式二
docker attach 容器ID

# 测试
[root@centos-liunx-7 ~]# docker attach 293933b1a937
正在执行当前的代码...

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

从容器内拷贝文件到主机上

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

# 测试
[root@centos-liunx-7 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED       STATUS        PORTS     NAMES
293933b1a937   centos    "/bin/bash"   2 hours ago   Up 1 second             romantic_cohen
# 进入当前正在运行的容器
[root@centos-liunx-7 ~]# docker attach 293933b1a937
# 创建一个文件
[root@293933b1a937 /]# touch test.java
# 查看目录
[root@293933b1a937 /]# ls
bin  etc   lib      lost+found  mnt  proc  run   srv  test.java  usr
dev  home  lib64  media       opt  root  sbin  sys  tmp        var
# 退出容器
[root@293933b1a937 /]# exit
exit
# 从容器中拷贝文件到宿主机目录中
[root@centos-liunx-7 ~]# docker cp 293933b1a937:/test.java /
[root@centos-liunx-7 ~]# cd /
# 查看宿主机目录
[root@centos-liunx-7 /]# ls
bin   dev  home  lib64  mnt  proc  run   srv  test.java  usr
boot  etc  lib   media  opt  root  sbin  sys  tmp        var
[root@centos-liunx-7 /]# 

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

将宿主机的文件拷贝到容器中:docker cp 宿主机路径 容器编号:容器路径

docker cp /javadxy/software/apache-tomcat-8.5.20/webapps tomcat1:/usr/local/tomcat/

重要

学习方式: 将上课的内容自己敲一遍,记录笔记

作业练习

部署Nginx
# 1. 搜索镜像    search    #推荐使用hub.docker.com搜索镜像,docker hub中有详细的帮助文档和命令
[root@centos-liunx-7 ~]# docker search nginx
# 2. 下载镜像
[root@centos-liunx-7 ~]# docker pull nginx
# 3. 通过镜像运行容器
[root@centos-liunx-7 ~]# docker run -d -it --name nginx01 -p 5000:80 nginx
    -d                           后台运行
    -it                          交互模式
    --name                       给容器命名
    -p 宿主机端口:容器端口        指定端口号
# 4. 验证nginx是否启动成功
浏览器访问    宿主IP:5000

如果是使用阿里云服务器的需要把阿里云5000端口放行

思考: 我们每次需要修改Nginx配置文件的时候都需要进入容器去修改,可以不可以直接在宿主机中直接修改一个文件,容器中的配置文件也会跟着改变?

部署Tomcat
# 官方的使用
$ docker run -it --rm tomcat:9.0    
    --rm    # 在退出tomcat之后会将这个容器删除,一般用于测试


# 1. 搜索镜像
[root@centos-liunx-7 ~]# docker search tomcat
# 2. 下载镜像
[root@centos-liunx-7 ~]# docker pull tomcat:8.5  # 指定版本号下载
# 3. 通过镜像运行容器
[root@centos-liunx-7 ~]# docker run -d --name tomcat02 -p 8081:8080 tomcat:8.5
# 4. 测试Tomcat是否启动成功
浏览器访问    宿主IP:8081

# 发现问题,页面404,少了linux命令
# 因为阿里镜像的原因,它保证这个镜像可运行,保证镜像最小

# 页面404是因为webapps文件夹内没有文件
# 将webapps.dist中的文件拷贝到webapps中,在刷新网页
[root@centos-liunx-7 ~]# docker exec -it tomcat02 /bin/bash
root@492a85fba570:/usr/local/tomcat# ls
BUILDING.txt     LICENSE  README.md     RUNNING.txt  conf  logs        temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin          lib   native-jni-lib  webapps  work
root@492a85fba570:/usr/local/tomcat# cd webapps.dist/
root@492a85fba570:/usr/local/tomcat/webapps.dist# ls
ROOT  docs  examples  host-manager  manager
root@492a85fba570:/usr/local/tomcat/webapps.dist# cd ../
root@492a85fba570:/usr/local/tomcat# cd webapps
root@492a85fba570:/usr/local/tomcat/webapps# ls
root@492a85fba570:/usr/local/tomcat/webapps# cd ../
root@492a85fba570:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@492a85fba570:/usr/local/tomcat# cd webapps
root@492a85fba570:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager
root@492a85fba570:/usr/local/tomcat/webapps

思考问题: 我们每次部署Tomcat项目的时候也要进入到容器内部去部署项目,十分的麻烦.有没有一种技术,修改宿主机文件,容器内部的文件自动同步?

可视化

  • portainer(先用这个)
  • docker run -d -p 8088:9000 \
    --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • Rancher(CI/CD再用)

Portainer

  • 使用ip:8088进入
  • 设置密码
  • 选择本地
  • 进入面板

    image-20221002161040915

镜像原理之分层理解

  • 我们从Docker Hub下载的镜像是只读的
  • 在使用镜像启动容器之后,我们在基于容器之后的操作(比如修改了某些文件),可以理解成在容器上面加了一层,你的每一个操作,都是在这个容器之上叠加,这个就是镜像之联合文件系统

镜像原理之文件联合系统

  • 容器都是基于宿主机的内核启动的
  • 比如我们下载一个mysql(有6层)
  • 我们在下载一个redis,可能redis也有6层,而redis的前两层和刚才下载mysql的前两层是一样的
  • Docker 就会复用mysql的前两层文件就不会再去下载

Commit镜像

##  使用Tomcat镜像启动容器
[root@centos-liunx-7 ~]# docker run -it -d -p 8080:8080 tomcat:8.5
##  发现webapps中没有文件
[root@centos-liunx-7 ~]# docker exec -it 2883d64efa26 /bin/bash
root@2883d64efa26:/usr/local/tomcat# ls
BUILDING.txt     LICENSE  README.md     RUNNING.txt  conf  logs        temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin          lib   native-jni-lib  webapps  work
root@2883d64efa26:/usr/local/tomcat# cd webapps
root@2883d64efa26:/usr/local/tomcat/webapps# ls
##  将webapps.dist中的文件复制到webapps中
root@2883d64efa26:/usr/local/tomcat/webapps# cd ../
root@2883d64efa26:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@2883d64efa26:/usr/local/tomcat# ls webapps
ROOT  docs  examples  host-manager  manager
root@2883d64efa26:/usr/local/tomcat# 
##  这个时候我们以后都想使用这个镜像运行,就要提交镜像
[root@centos-liunx-7 ~]# docker ps
CONTAINER ID   IMAGE        COMMAND             CREATED         STATUS         PORTS                                       NAMES
2883d64efa26   tomcat:8.5   "catalina.sh run"   5 minutes ago   Up 5 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   kind_swanson
##  提交镜像
##  docker commit -m="提交的消息 webapps app" -a="作者" 容器id 容器名称:版本号
[root@centos-liunx-7 ~]# docker commit -m="add webapps app" -a="yiyu" 2883d64efa26 tomcat:1.0
sha256:53fb07d89492a1afd6fe1097252122e2b6a1a658adaa9157aecef0bbe4687e3b
[root@centos-liunx-7 ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
tomcat                1.0       53fb07d89492   2 seconds ago   683MB
nginx                 latest    605c77e624dd   9 months ago    141MB
tomcat                8.5       2d2bccf89f53   9 months ago    678MB
tomcat                latest    fb5657adc892   9 months ago    680MB
mysql                 latest    3218b38490ce   9 months ago    516MB
centos                latest    5d0da3dc9764   12 months ago   231MB
portainer/portainer   latest    580c0e4e98b0   18 months ago   79.1MB
[root@centos-liunx-7 ~]# 
    -a="作者"
    -m="提交的消息"

这个时候我们就可以使用提交好的镜像去启动一个容器,而且启动后的容器中的tomcat是有主页面的

容器数据卷

什么是容器数据卷?

当我们使用mysql镜像创建了一个容器,之后把容器删除之后,那么我们容器中的数据就丢失了.这个时候我们可以使用数据卷,将容器内的数据和本地数据连接起来,当容器中数据改变或者本地数据改变的时候,它们都会自动同步

使用容器数据卷

##  命令 docker run -d -it -v 宿主机目录:容器内部目录
[root@centos-liunx-7 home]# docker run -d -it -v /home/ceshi:/home centos
##  查看是否挂载成功
[root@centos-liunx-7 home]# docker inspect 容器id
"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/ceshi",
                "Destination": "/home",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
# 如果元数据中Mounts数组中有数据,表示挂载成功了
# 测试
# 在容器内部home目录下创建的文件,在宿主机/home/ceshi目录也会同步出来
# 反之,在/home/ceshi目录下创建或操作的文件,也会同步到容器内部

注意: 就算容器被关闭,在宿主机/home/ceshi目录下创建的文件依旧会同步到容器内部

image-20221002203232304

实战: 安装MySQL

# 下载镜像
docker pull mysql
# 启动
# 官方的启动命令 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 我们的启动命令
-it 交互模式
-d    后台运行
-v    数据卷挂载
-e    环境配置
--name    给容器命名
[root@centos-liunx-7 ceshi]# docker run -it -d -p 3310:3306 -v /home/mysql/data:/var/lib/mysql -v /home/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql

image-20221002210158172

使用Navicat连接MYSQL并创建一个数据库,linux中的数据也会随之改变

当我们删除容器时,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化

image-20221002210401960

具名挂载和匿名挂载

# 命令 具名挂载
# docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx nginx
    -P                        随机端口
[root@centos-liunx-7 data]# docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx nginx
df0f46eecd648da7709792285d70b58146c8885aab22e4bf8bd585b5e9208ed4
[root@centos-liunx-7 data]# docker volume ls
DRIVER    VOLUME NAME
local     7bd9c653cd464bd8dc902b0f70b97d09a3ce6d0db5de9ac874c6072a877b8920
local     51b6c469889451450ba07cf2a781dc1c34955a0c3f3e3aa251614c41f7319e85
local     735e477cfb34b3113a458940dc3ba47db0b3ccb73d2be80f24f4bef7488115a7
local     b4e659a7be46bf56c07f131c647a69b9bb3d568bbe52b3ee8fc8495f31d0a1c0
local     e29d1ac89192283e4ffc5c0e9d4bf8ac19740a1c8655be3a80673bde3e6d199a
local     juming-nginx
# 查看卷    docker volume ls
# 查看卷数据     docker volume inspect 卷名称
[root@centos-liunx-7 data]# docker volume inspect juming-nginx
[
    {
        "CreatedAt": "2022-10-02T21:21:28+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]
[root@centos-liunx-7 data]# 
# 如何查看是具名挂载和匿名挂载,还是指定路径挂载
    -v 卷名称:容器内路径            # 具名挂载
    -v 容器内路径                 # 匿名挂载
    -v 宿主机路径:容器内路径          # 指定路径挂载

image-20221002212803531

默认的挂载路径为 /var/lib/docker/volumes/xxxxx/_data

扩展

docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:rw nginx
# ro    readonly    #只读
# rw    readwrite    #可读可写
# 在只读的情况下不能在容器内容修改文件,只能在容器外修改
# 默认是rw(可读可写)

初识Dockerfile

Dockerfile就是用来构建docker镜像的构建文件!可以理解成一个命令脚本!

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

# 创建一个dockerfile文件,名字可以随机,建议 Dockerfile
# 文件中的内容 命令(是大写的) 
FROM centos
VOLUME ["volume1","volume2"]
CMD echo "----end----"
CMD /bin/bash

命令 构建

[root@centos-liunx-7 docker-volumn-file]# docker build -f dockerfile1 -t yiyu/centos:1.0 .
    -f Dockerfile文件的路径
    -t 镜像名称:版本号
    .构建到当前docker

image-20221003141418676

使用我们自己构建的镜像创建容器

[root@centos-liunx-7 docker-volumn-file]# docker run -it 9662d35446d3 /bin/bash
[root@86f89bc561de /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume1  volume2
# 发现多了2个文件夹,这两个文件夹就是我们在构建镜像时创建的数据卷

image-20221003141952849

# 使用命令 docker inspect 容器id 查看容器元数据发现已经自动挂载好了(匿名挂载)

image-20221003142157159

这就实现了我们在创建容器时自动挂载数据卷,而不用使用 -v 命令手动挂载

数据卷容器

# 命令 --volumes-from 父容器id

使用刚才构建的镜像创建两个容器并在第二个容器数据卷中创建文件,第一个容器中的数据卷会自动同步

拷贝机制

image-20221003151322134

多个mysql实现数据共享

[root@centos-liunx-7 ceshi]# docker run -it -d -p 3310:3306 -v /var/lib/mysql -v /etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql
[root@centos-liunx-7 ceshi]# docker run -it -d -p 3310:3306 --volumes-from mysql01 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 mysql
# 这个时候,可以实现两个容器数据共享

DockerFile

DockerFile的指令

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

image-20221003153824083

实战测试

创建自己的centos
[root@centos-liunx-7 dockerfile-work]# cat mydockerfile-centos 
FROM centos
MAINTAINER yiyu<318334629@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
#构建命令
docker build -f dockerfile文件路径 -t 镜像名称: .

遇到问题: vim和net-tools安装失败

# 运行自己构建的centos
[root@centos-liunx-7 dockerfile-work]# docker run -it mycentos:0.1
[root@5a47d68eaf04 local]# pwd
/usr/local
[root@5a47d68eaf04 local]# ls
bin  etc  games  include  lib  lib64  libexec  sbin  share  src
# 可以看到运行后的工作路径是/usr/local,说明上面写的命令是没问题的

实战:Tomcat镜像

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

    image-20221004103543446

  2. 编写dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件

    FROM centos
    MAINTAINET yiyu<318334629@qq.com>
    COPY readme.txt /usr/local/readme.txt
    ADD jdk-8u341-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.67.tar.gz /usr/local/
    RUN yum -y install vim
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    ENV JAVA_HOME /usr/local/jdk1.8.0_341
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.67
    ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.67
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_BASH/bin
    EXPOSE 8080
    CMD /usr/local/apache-tomcat-9.0.67/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.67/bin/
    logs/catalina.ou
  3. 构建镜像

    # docker build -t diytomcat .
  4. 启动镜像
  5. 访问测试
  6. 发布项目(由于做了卷挂载,我们之前在本地编写项目就可以发布了)
<web-app
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                        http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    id="WebApp_ID" version="4.0">
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello,yiyu</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("-----my test web logs-----");
%>
</body>
</html>

发现: 项目部署成功,可以直接访问!

我们以后开发的步骤: 需要掌握Dockerfile的编写! 我们之后的一切都是使用docker镜像来发布运行

发布自己的镜像

Dockerhub
  1. 地址 https://hub.docker.com/ 注册自己的账号
  2. 确保账号可以登录
  3. 在我们服务器上提交自己的镜像

    [root@centos-liunx-7 tomcatlogs]# docker login --help
    
    Usage:  docker login [OPTIONS] [SERVER]
    
    Log in to a Docker 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
    [root@centos-liunx-7 tomcatlogs]# 
    [root@centos-liunx-7 tomcatlogs]# docker login -u chengxuyi
    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-store
    
    Login Succeeded
  4. 登录完毕后就可以提交镜像了,就是一步 docker push

    # push自己的镜像到服务器上
    [root@centos-liunx-7 tomcatlogs]# docker push diytomcat
    Using default tag: latest
    The push refers to repository [docker.io/library/diytomcat]
    3b80368c27b7: Preparing 
    a46e380f6b0d: Preparing 
    009bcb6b88ee: Preparing 
    74ddd0ec08fa: Preparing
    denied: requested access to the resource is denied # 拒绝
    
    # push镜像的问题
    [root@centos-liunx-7 tomcatlogs]# docker push chengxuyi/diytomcat:11
    The push refers to repository [docker.io/chengxuyi/diytomcat]
    An image does not exist locally with the tag: chengxuyi/diytomcat
    
    # 解决,增加一个 tag
    [root@centos-liunx-7 tomcatlogs]# docker tag 3962139fb78c chengxuyi/tomcat:0.9
    
    # docker push上去即可! 自己发布的镜像尽量带上版本号
    [root@centos-liunx-7 tomcatlogs]# docker push chengxuyi/tomcat:0.9
    The push refers to repository [docker.io/chengxuyi/tomcat]
    3b80368c27b7: Pushing   6.17MB/16.11MB
    a46e380f6b0d: Pushing  13.09MB/369.8MB
    009bcb6b88ee: Pushed 
    74ddd0ec08fa: Pushing  13.13MB/231.3MB

    提交的时候也是安装镜像的层级来进行提交的

阿里云镜像服务上
  1. 登录阿里云
  2. 找到容器镜像服务
  3. 创建命名空间

    image-20221004131931450

  4. 创建容器镜像仓库

    image-20221004132127737

  5. 浏览阿里云

    image-20221004132403262

    docker push registry.cn-hangzhou.aliyuncs.com/chengxuyi/yiyu:[镜像版本号]

    解决阿里云镜像无法push: CSDN

小结

image-20221004140049075

Docker网络

理解Docker网络0

清空所有环境

测试

image-20221004140928321

三个网络

# 问题: docker 是如何处理容器网络访问的?
# 查看容器的内部网络地址 ip addr
原理
  1. 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker就会有一个网卡docker0,桥接模式,使用的技术是 evth-pair 技术

    • 可以把docker的主网卡想成一个路由器,而每使用docker启动一个容器,docker就给给这个容器分配一个内网的IP地址
    • 每启动一个容器,就会多一对网卡
    # 我们发现这个容器带来的网卡,都是一对对的
    # evth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一端连着协议,一端彼此相连
    # 正因为有这个特效, evth-pair 充当一个桥梁,连接各种虚拟网络设备的
    # PoenStac,Docker容器之间的连接,OVS的连接,都是使用 evth-pair 技术
  2. 我们来测试下centos01和centos02是否可以ping通!

    [root@centos-liunx-7 /]# docker exec -it centos01 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
    84: eth0@if85: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    [root@centos-liunx-7 /]# docker exec -it centos02 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
    86: eth0@if87: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    [root@centos-liunx-7 /]# docker exec -it centos01 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.129 ms
    64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.085 ms
    64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.102 ms
    64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.104 ms
    64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.067 ms
    
    # 结论: 容器和容器之间是可以互相ping通的

    image-20221004143331557

    结论: centos01 和 centos02 是公用一个路由器, Docker0

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

小结

DOcker 使用的是Linux的桥接,宿主机中是一个Docker容器的网桥 docker0

image-20221004143820209

Docker中的所有的网络接口都是虚拟的.虚拟的转发效率高!

只要容器删除,对应的网桥一对就没了

--link

思考一个场景,我们编写了一个微服务,database url=ip, 项目不重启,数据ip换掉了,我们希望可以处理这个问题,可以通过名字来进行访问容器!
[root@centos-liunx-7 /]# docker exec -it tomcat02 ping tomcat01
Error: No such container: tomcat02
# 如何可以解决呢?
# 通过--link 就可以解决了网络联通问题
[root@centos-liunx-7 /]# docker run -d -it -P --name centos03 --link centos02 centos
1fccd0e0c5a2a1ea4886003d1a0021ea45fa9f1a93b0e0d263655da83f17b056
[root@centos-liunx-7 /]# docker exec -it centos02 ping centos01
ping: centos01: Name or service not known
[root@centos-liunx-7 /]# docker exec -it centos03 ping centos02
PING centos02 (172.17.0.3) 56(84) bytes of data.
64 bytes from centos02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.098 ms
64 bytes from centos02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.217 ms
64 bytes from centos02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.076 ms
# 反向可以ping通吗?
[root@centos-liunx-7 /]# docker exec -it centos02 ping centos03
ping: centos03: Name or service not known

image-20221004145102420

其实这个centos03就是在本地配置了centos02

# 查看 hosts 配置,在这里原理发现!
[root@centos-liunx-7 /]# docker exec -it centos03 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    centos02 080b56a86172
172.17.0.4    1fccd0e0c5a2

本质探究: --link就是在我们hosts配置中增加了一个172.17.0.3 centos02 080b56a86172

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

自定义网络!不使用docker0

docker0问题:他不支持容器名连接访问!

自定义网络

查看所有的docker网络

image-20221004145910391

网络模式

bridge: 桥接模式 docker(默认,自己创建也是用brideg模式)

none: 不配置网络

host: 和宿主机共享网络

container: 容器内网络连通(用的少!局限性很大)

测试

# 我们直接启动的命令 --net bridge ,而这个就是我们的docker0
 docker run -d -P --name centos01 --net bridge centos
 # docker0的特点: 默认,域名不能访问,--link可以打通连接
 # 我们 可以自定义一个网络
 # --driver bridge
 # --subnet 192.168.0.0/16 192.168.0.2 192.168.255.255
 # --gateway 192.168.0.1
 [root@centos-liunx-7 /]# docker network create --driver bridge  --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
2eda7ce36f8f3b6c6ac6af7ae95fc593367bd9d48d637110dbbce437ac0440e7
[root@centos-liunx-7 /]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
b3f10c44674d   bridge    bridge    local
89c2b174693d   host      host      local
2eda7ce36f8f   mynet     bridge    local
bf454ee5fa23   none      null      local
 

image-20221004150831010

[root@centos-liunx-7 /]# docker run -d -it -P --name centos-net-01 --net mynet centos
37e9334cd00053f9fcc003e58bb1e811fc11bdc9e0517301ef1920210d94fe77
[root@centos-liunx-7 /]# docker run -d -it -P --name centos-net-02 --net mynet centos
0f72e3f2d724eb2ba2e81e3ec6c4af1f1d364163e01e586a8ced56b2e8b982d0
[root@centos-liunx-7 /]# docker network inspect
"docker network inspect" requires at least 1 argument.
See 'docker network inspect --help'.
Usage:  docker network inspect [OPTIONS] NETWORK [NETWORK...]
Display detailed information on one or more networks
[root@centos-liunx-7 /]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "2eda7ce36f8f3b6c6ac6af7ae95fc593367bd9d48d637110dbbce437ac0440e7",
        "Created": "2022-10-04T15:05:56.551606092+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": {
            "0f72e3f2d724eb2ba2e81e3ec6c4af1f1d364163e01e586a8ced56b2e8b982d0": {
                "Name": "centos-net-02",
                "EndpointID": "f42ecdc2792113040e91efaca8ebe68c0982cb9e30ccff51a36c2c0219cd8ca5",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "37e9334cd00053f9fcc003e58bb1e811fc11bdc9e0517301ef1920210d94fe77": {
                "Name": "centos-net-01",
                "EndpointID": "7bb99f5c54a3aa0a71907a0dfdcecfd9f3166a5f80e3509b9e0ad6d0907d864c",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
# 再次测试ping连接
[root@centos-liunx-7 /]# docker exec -it centos-net-01 ping centos-net-02
PING centos-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.080 ms
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.065 ms
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.064 ms
# 现在不使用--link也可以ping名字了

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

好处:

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

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

网络连通

image-20221004151938110

# 测试打通 centos03 - mynet
[root@centos-liunx-7 /]# docker network connect mynet 56d4731f695f
[root@centos-liunx-7 /]# docker exec -it centos03 ping centos-net-01
PING centos-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.241 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.088 ms
# 连通之后就是将centos03 放到了 mynet 网络下
# 一个容器两个ip地址! 

image-20221004152324483

结论: 假设要跨网络操作别人,就需要使用docker network connect 连通!

实战: 部署Redis集群

image-20221004152720285

shell脚本

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

# 通过脚本创建六个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done



docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

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

# 创建集群
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:63
79 172.38.0.15:6379 172.38.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.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: e25f16e906ac90fe3e22475dcb7b7c1e51a3144e 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
M: a535292a5dfb31ce54f82828681d6b2472de3021 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 5b79173ce1dfc1355e57bcfc36c59ea0490da47d 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: baa3ab92abe356b23ad485c3c64528b181ca8981 172.38.0.14:6379
   replicates 5b79173ce1dfc1355e57bcfc36c59ea0490da47d
S: 7fc66da4754d9d363d90e8e4248ced7c8ec094f4 172.38.0.15:6379
   replicates e25f16e906ac90fe3e22475dcb7b7c1e51a3144e
S: c4dda1ab836499e84a48b26f762226b7010fec52 172.38.0.16:6379
   replicates a535292a5dfb31ce54f82828681d6b2472de3021
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: e25f16e906ac90fe3e22475dcb7b7c1e51a3144e 172.38.0.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: baa3ab92abe356b23ad485c3c64528b181ca8981 172.38.0.14:6379
   slots: (0 slots) slave
   replicates 5b79173ce1dfc1355e57bcfc36c59ea0490da47d
M: a535292a5dfb31ce54f82828681d6b2472de3021 172.38.0.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 5b79173ce1dfc1355e57bcfc36c59ea0490da47d 172.38.0.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: c4dda1ab836499e84a48b26f762226b7010fec52 172.38.0.16:6379
   slots: (0 slots) slave
   replicates a535292a5dfb31ce54f82828681d6b2472de3021
S: 7fc66da4754d9d363d90e8e4248ced7c8ec094f4 172.38.0.15:6379
   slots: (0 slots) slave
   replicates e25f16e906ac90fe3e22475dcb7b7c1e51a3144e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

docker 搭建redis集群完成

image-20221004154841709

我们使用docker之后,所有的技术都会慢慢的变得简单起来

SpringBoot微服务打包Docker镜像

  1. 构建springboot项目
  2. 打包应用
  3. 编写dockerfile
  4. 构建镜像
  5. 发布运行

以后我们使用了Docker之后,给别人交付的就是一个镜像即可!

最后修改:2023 年 07 月 04 日
如果觉得我的文章对你有用,请随意赞赏