美文网首页程序员Kuberne...
Docker最新版19.03 详细教程

Docker最新版19.03 详细教程

作者: Linux丶晨星 | 来源:发表于2020-06-30 14:39 被阅读0次

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

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

    image

    概念

    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-node02
    
    LAN
    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 
    do
     sshpass -p123456 ssh-copy-id -o StrictHostKeyChecking=no 172.16.0.$ip
    done
    
    sh 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-node02
    
    for 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
    
    image

    配置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 ~]#
    

    容器资源限制的参数

    image

    列出所有的运行的容器

    #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
    
    image

    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
    
    image

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

    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容器的内存占用情况太大

    image
    # 关闭刚刚启动的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
    
    image
    [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容器

    # 运行一台kibana7.6.2的容器,并添加到elasticsearch容器的网络中,使用--link或者创建自定义网络
    docker run -d --name kibana --link elasticsearch -p 5601:5601 kibana:7.6.2
    
    # 访问查看;选择一个样本数据进行测试是否与es连接
    



    五、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

    image image image

    2.Rancher

    Rancher是一个开源的企业级容器管理平台。通过Rancher,企业不必自己使用一系列的开源软件去从头搭建容器服务平台。Rancher提供了在生产环境中使用管理DockerKubernetes的全栈化容器部署与管理平台。

    docker run -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher:v2.0.0
    docker logs -f rancher
    

    https://192.168.0.10

    3. cAdvisor

    cAdvisorGoogle开发的容器监控工具。

    • 监控 Docker Host cAdvisor 会显示当前 host 的资源使用情况,包括 CPU、内存、网络、文件系统等。
    • 监控容器 点击 Docker Containers 链接,显示容器列表。点击某个容器,比如 sysdig,进入该容器的监控页面。

    以上就是 cAdvisor 的主要功能,总结起来主要两点:

    • 展示 Host 和容器两个层次的监控数据。
    • 展示历史变化数据。

    由于cAdvisor提供的操作界面略显简陋,而且需要在不同页面之间跳转,并且只能监控一个 host,这不免会让人质疑它的实用性。但 cAdvisor 的一个亮点是它可以将监控到的数据导出给第三方工具,由这些工具进一步加工处理。

    我们可以把 cAdvisor 定位为一个监控数据收集器,收集和导出数据是它的强项,而非展示数据。 cAdvisor 支持很多第三方工具,其中就包括Prometheus

     docker run   --volume=/:/rootfs:ro   --volume=/var/run:/var/run:rw   --volume=/sys:/sys:ro   --volume=/var/lib/docker/:/var/lib/docker:ro   --volume=/dev/disk/:/dev/disk:ro   --publish=8080:8080   --detach=true   --name=cadvisor   google/cadvisor:latest
    
    image.png

    六、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容器

    image
    image

    新建一个数据库 test

    image
    # 查看主机映射目录也已经同步了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

    image

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

    # 如何确定是具名挂载还是匿名挂载,还是指定路径挂载?
    -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、私有仓库)

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

    image

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

    2. Dockerfile构建

    基础知识

    • 每个指令都必须是大写字母
    • 执行从上到下顺序执行
    • "#"表示注释
    • 每一个指令都会创建提交一个新的镜像层,并提交!
    • 在 Docker 17.05 以上版本中,可以使用多阶段构建 来减少所构建镜像的大小。
    image
    • 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包)
    
    image

    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 $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 "."最后的"."号,其实是在指定镜像构建过程中的上下文环境的目录
    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
    

    查看镜像的构建历史记录

    image

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

    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的压缩包

    image

    2. 编写dockerfile文件

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

    image
    [root@k8s-master tomcat]# cat Dockerfile
    FROM centos
    MAINTAINER lichenxing<245684979@qq.com>
    
    COPY readme.txt /usr/local/readme.txt
    
    ADD 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 $MYPATH
    
    ENV 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/bin
    
    EXPOSE 8080
    
    CMD /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
    
    image

    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端口

    image

    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
    
    image

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

    • 在主机的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/

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

    image

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

    [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-store
    
    Login Succeeded
    
    # 为封装好的镜像打一个标签
    # 这里要注意 给自己镜像命名的时候格式应该是: docker注册用户名/镜像名,不然是push不上去的
    [root@k8s-master tomcat]# docker tag diytomcat:latest 245684979/diytomcat:1.0
    
    image
    [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就可以看到了

    image

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

    登陆阿里云

    找到容器镜像服务

    创建命名空间

    创建容器镜像

    浏览操作指南

    image
    [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"]}
    

    十、企业级镜像仓库 Harbor

    https://github.com/goharbor/harbor/tree/release-2.0.0

    Habor是由VMWare公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的 企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访 问控制 ,AD/LDAP集成以及审计日志等,足以满足基本企业需求。

    官方安装文档

    下载地址:https://github.com/goharbor/harbor/releases

    软件版本

    • 在Linux主机上: docker 17.06.0-ce +和docker-compose 1.18.0+

    1. 安装

    #安装docker compose
    yum install -y docker-compose
    docker-compose --version
    docker-compose version 1.18.0, build 8dd22a9
    
    #这里使用1.9版本的harbor
    tar xf harbor-offline-installer-v1.9.1.tgz -C /opt/
    cd /opt/harbor/
    
    # 修改配置文件
    vim harbor.yml
    hostname: 192.168.0.10
    harbor_admin_password: 123456
    
    #执行prepare脚本
    ./prepare
    
    #执行脚本
    sh install.sh 
    [Step 0]: checking installation environment ...
    Note: docker version: 19.03.11
    Note: docker-compose version: 1.18.0
    [Step 1]: loading Harbor images ...
    

    2. 访问

    admin 123456

    3. 推送镜像

    docker tag nginx:1.18.0 192.168.0.10/library/nginx:1.18.0
    
    #修改daemon.json配置文件,指定仓库IP为192.168.0.10
    vim /etc/docker/daemon.json
    {
      "registry-mirrors": ["https://registry.docker-cn.com"],
      "insecure-registries": ["192.168.0.10"]
    }
    systemctl restart docker
    docker-compose up -d
    

    4. 添加新用户

    #登陆普通用户guest
    [root@k8s-master harbor]# docker login 192.168.0.10
    Username: guest
    Password:   #Lcx123456
    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
    

    推送镜像

    #推送其他镜像到harbor
    ##nginx
    [root@k8s-master harbor]# docker push 192.168.0.10/library/nginx:1.18.0 
    The push refers to repository [192.168.0.10/library/nginx]
    97d4365452ad: Pushed 
    d1c9311342b8: Pushed 
    edf3aa290fb3: Pushed 
    1.18.0: digest: sha256:15b2135c75230e8282f9c3039fd50f22e90929eafc827f6b8d629bbe190c33d0 size: 952
    
    ## php
    docker tag php:v2 192.168.0.10/library/php:v2
    docker push 192.168.0.10/library/php:v2 
    
    ## tomcat
    docker tag tomcat:v2 192.168.0.10/library/tomcat:v2
    docker push 192.168.0.10/library/tomcat:v2 
    
    ## mysql
    docker tag mysql:5.7 192.168.0.10/library/mysql:5.7
    docker push 192.168.0.10/library/mysql:5.7 
    

    5. 创建私有项目project

    #登出
     docker logout
     >/root/.docker/config.json
     #登陆admin用户
    WARNING: Error loading config file: /root/.docker/config.json: EOF
    Username: admin
    Password: #123456
    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
    
    #上传一个镜像
    docker tag tomcat:v2 192.168.0.10/project/tomcat:v2
    docker push 192.168.0.10/project/tomcat:v2
    

    十一、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 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
    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 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_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查看。

    image

    --link 容器互联

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

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

    # 创建俩台容器 tomcat01和tomcat02
     docker run -it -d -P --name tomcat01 245684979/diytomcat:1.0
     docker 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 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

    image
    # 运行一个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 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
        inet6 ::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 1000
        link/ether 00:0c:29:8a:1a:eb brd ff:ff:ff:ff:ff:ff
        inet 192.168.0.10/24 brd 192.168.0.255 scope global eth0
           valid_lft forever preferred_lft forever
        inet6 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 1000
        link/ether 00:0c:29:8a:1a:f5 brd ff:ff:ff:ff:ff:ff
        inet 172.16.0.10/24 brd 172.16.0.255 scope global eth1
           valid_lft forever preferred_lft forever
        inet6 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:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
        inet6 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:ff
        inet 172.20.0.1/16 brd 172.20.255.255 scope global br-45945e527658
           valid_lft forever preferred_lft forever
        inet6 fe80::42:16ff:fe06:bdc9/64 scope link 
           valid_lft forever preferred_lft forever
    

    3. Container 模式

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

    image
    # 运行一个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 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
    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:ff
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_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 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
    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:ff
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    

    4. None模式

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

    image
    # 运行一个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 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
    

    5. 网络连通

    image
    image
    # 用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
    
    image
    # 一个容器 两个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 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
    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 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_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 0
        inet 172.20.0.4/16 brd 172.20.255.255 scope global eth1
           valid_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.conf
    
    docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
    -v /mydata/redis/node-2/data:/data \
    -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.30.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
    -v /mydata/redis/node-3/data:/data \
    -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.30.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
    -v /mydata/redis/node-4/data:/data \
    -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.30.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
    -v /mydata/redis/node-5/data:/data \
    -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.30.0.15 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.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:6379
       slots:[0-5460] (5461 slots) master
    M: 18eeb76c35d2185d39ecf0700cb486446f78065d 172.30.0.12:6379
       slots:[5461-10922] (5462 slots) master
    M: 89a2b7bc56f838794f3b4492745f33a55f2af842 172.30.0.13:6379
       slots:[10923-16383] (5461 slots) master
    S: 22acd8c91964e59f767fe95468210e876b65aa63 172.30.0.14:6379
       replicates 89a2b7bc56f838794f3b4492745f33a55f2af842
    S: 7d37c75d6f6868e0eb50505763c6dcca533a7252 172.30.0.15:6379
       replicates ef62648c7f22c87109e3a4004e0b7b2a9717c5ca
    S: c9726603df7d4a132ce012dd68ad829a69553ec9 172.30.0.16:6379
       replicates 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"
    
    image
    部署redis集群完成!

    十二、 Docker Compose

    Docker MachineDocker官方编排(Orchestration)项目之一,负责在多种平台上快速安装 Docker 环境。

    Docker Machine项目基于Go语言实现,目前在Github上进行维护。

    Docker Machine是 Docker 官方提供的一个工具,它可以帮助我们在远程的机器上安装 Docker,或者在虚拟机 host 上直接安装虚拟机并在虚拟机中安装 Docker。我们还可以通过 docker-machine命令来管理这些虚拟机和 Docker。

    yum install -y docker-compose
    

    编写一个可道云的yml

    [root@k8s-master docker]# cat docker-compose/wordpress/docker-compose.yml 
    version: '3'
    
    services:
       db:
         image: mysql:5.7
         volumes:
           - db_data:/var/lib/mysql
         restart: always
         environment:
           MYSQL_ROOT_PASSWORD: somewordpress
           MYSQL_DATABASE: wordpress
           MYSQL_USER: wordpress
           MYSQL_PASSWORD: wordpress
    
       wordpress:
         depends_on:
           - db
         image: wordpress:latest
         volumes:
           - web_data:/var/www/html
         ports:
           - "89:80"
         restart: always
         environment:
           WORDPRESS_DB_HOST: db
           WORDPRESS_DB_USER: wordpress
           WORDPRESS_DB_PASSWORD: wordpress
    volumes:
        db_data:
        web_data:
    
    #启动
    docker-compose up 
    #后台启动
    docker-compose up -d
    

    十三、 Docker Swarm

    Swarm是使用SwarmKit构建的 Docker 引擎内置(原生)的集群管理和编排工具。提供 Docker 容器集群服务,是 Docker 官方对容器云生态进行支持的核心方案。

    使用它,用户可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机,快速打造一套容器云平台。Swarm mode 内置 kv 存储功能,提供了众多的新特性,比如:具有容错能力的去中心化设计、内置服务发现、负载均衡、路由网格、动态伸缩、滚动更新、安全传输等。使得 Docker 原生的 Swarm 集群具备与MesosKubernetes竞争的实力。

    十四、Prometheus监控


    请看文章连接

    相关文章

      网友评论

        本文标题:Docker最新版19.03 详细教程

        本文链接:https://www.haomeiwen.com/subject/babcfktx.html