zoukankan      html  css  js  c++  java
  • Docker杂谈

    一、为什么要用容器

    1、上线流程繁琐
        传统的项目上线要经历开发—测试—申请资源—审批—部署—测试等环节
    2、资源利用率低 普通服务器利用率低,造成过多浪费(低于过20%的开销的服务不在少数)
    3、扩容/缩容不及时 业务高峰和低谷扩容/缩容流程繁琐,不能及时有效的处理
    4、服务器环境臃肿 为了节约资源,一台服务器跑了N多个项目,而且的项目历史悠久,换了一波又一波维护人员,对维护、迁移带来各种困难(有些历史项目没人敢动)
    5、环境不一致 通常线上出了问题,研发的口头禅是:我本地是正常的,到了你的环境就出问题了,肯定是你运维的环境问题,各种甩锅此批彼伏...

    二、Docker是什么

    • 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源
    • 是一种基于操作系统级的虚拟化技术
    • 依赖于Linux内核特性,Namespace(资源隔离)和Cgroups(资源限制)
    • 一个简单的应用程序打包工具,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,解决了传统项目因环境不一致产生的各种问

    三、Docker的核心组件

    • Docker Daemon:docker的守护进程,负责与Docker Client交互,并管理镜像、容器实例 
    • 镜像:类似于重装系统的ISO或ghost文件。同样的docker中的镜像也是系统(可能少了内核)和一些软件或者服务的结合体,通过镜像我们可以运行很多个容器
    • 容器:docker的运行实例,如果把镜像看作是maven的打包阶段,那么容器就是打出来的jar包运行的结果
    • 仓库:存放镜像的地方。分为公有仓库(docker hub) 和私有仓库
    • Containerd:是一个简单的守护进程,向上给Docker Daemon提供接口,向下通过containerd-shim结合runC管理容器 
      • /usr/bin/containerd
      • /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
      • containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/df1a012ccfbb0192ceb7368c80ac9c51426d83a9eb7b2e962f33fa09d6ce6274 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
    • runC:一个命令行工具,它根据OCI标准来创建和运行容器

    三、docker和虚拟机的区别

    虚拟机:

    1. 基础设施:它可以是个人电脑、数据中心的服务器,亦或者是云主机
    2. 主操作系统:俗称宿主机系统,可以macOS、windows或者某个Linux发行版
    3. 虚拟机管理系统:利用Hypervisor,可以在主操作系统上运行多个不同的从操作系统,比如macOS的HypeKit,支持Windows的Hyper-V以及支持Linux的KVM,还有windows上的virtualBox和VMware 硬件级的EXSI
    4. Guest OS:假设需要运行相互隔离的应用,则需要使用Hypervisor启动三个GuestOS,也就是三个虚拟机,这些虚拟机都非常大,会消耗宿主机的各种资源
    5. 各种依赖:每个GuestOS是一个全新的操作系统,需要安装各种依赖
    6. 系统级隔离:每个GuestOS完全隔离

    Docker:

    1. 主操作系统:所有主流Linux发行版都可以运行Docker,对于macOS和Windows也有一些办法运行docker
    2. Docker守护进程:Docker取代了Hypervisor,它是运行在操作系统之上的后台进程,负责管理docker容器
    3. 各种依赖:对于docker,应用所有的依赖都打包在Docker镜像中,docker容器基于docker镜像创建的
    4. 应用:应用的源代码与它所需的依赖都打包在镜像中,保证了运行环境的一致性
    5. 进程级隔离:不同应用运行不同的容器中,它们是相互隔离的

    Docker有着小巧、迁移部署快速、运行高效等特点,但隔离性比服务器虚拟化差:不同的集装箱属于不同的运单(Docker上运行不同的应用实例),相互独立(隔离)。但由同一个库管人员管理(主机操作系统内核),因此通过库管人员可以看到所有集装箱的相关信息(因为共享操作系统内核,因此相关信息会共享)。

    虚拟化就好比在码头上(物理主机及虚拟化层),建立了多个独立的“小码头”—仓库(虚拟机)。其拥有完全独立(隔离)的空间,属于不同的客户(虚拟机所有者)。每个仓库有各自的库管人员(当前虚拟机的操作系统内核),无法管理其它仓库。不存在信息共享的情况

    因此,我们需要根据不同的应用场景和需求采用不同的方式使用Docker技术或使用服务器虚拟化技术。例如一个典型的Docker应用场景是当主机上的Docker实例属于单一用户的情况下,在保证安全的同时可以充分发挥Docker的技术优势。对于隔离要求较高的环境如混合用户环境,就可以使用服务器虚拟化技术。正则科技提供了丰富的Docker应用实例,满足您的各种应用需求,并且支持在已经安装了自在(Isvara)服务器虚拟化软件的主机上同时使用服务器虚拟化技术和Docker技术提供不同技术场景。

     四、docker安装

    docker版本

    • 社区版(Community  Edition  CE)
    • 企业版(Enterprise Editon    EE)

    支持平台

    • 各种发型版的Linux
    • Mac
    • Windows
    # 安装依赖包
    yum install -y yum-utils
    # 添加Docker软件包源
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

    # 安装Docker CE yum install -y docker-ce
    # 启动Docker服务并设置开机启动 systemctl start docker systemctl enable docker
    https:
    //docs.docker.com/engine/install/centos/ 官方文档:https://docs.docker.com 阿里云源:http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

    五、镜像管理

      1.镜像是什么

      •   一个分层存储的文件,不是一个单一的文件
      •   一个项目完整运行环境
      •   一个镜像可以创建多个容器
      •   一种标准化交付
      •   一个不包含Linux内核而又精简的Linux操作系统

      2.镜像从哪里来

    Docker Hub是有Docker公司负责维护的公共镜像仓库,包含大量的容器镜像,Docker工具默认从这个公共镜像库获取
    
    地址:https://hub.docker.com/
    配置镜像加速器
    以阿里云为例:
    登录控制台—容器镜像服务—镜像加速器 此页面可以看到加速器的地址
     cat /etc/docker/daemon.json 
    {
        "registry-mirrors": ["https://knh15e9b.mirror.aliyuncs.com"]
    }

      3.镜像与容器的联系  

      

      4,镜像常用的管理命令

    Usage:    docker image COMMAND
    
    Manage images
    
    Commands:
      build       Build an image from a Dockerfile  #构建来自Dockerfile
      history     Show the history of an image      #查看镜像历史(层级)
      import      Import the contents from a tarball to create a filesystem image    # 导入容器文件系统tar归档文件并创建镜像
      inspect     Display detailed information on one or more images # 显示镜像的详细信息
      load        Load an image from a tar archive or STDIN  #加载镜像来自tar归档的或标准输入
      ls          List images  #列出当前系统上的镜像
      prune       Remove unused images  #移除没有标记或者没有任何容器引用的镜像
      pull        Pull an image or a repository from a registry #从镜像仓库拉取镜像
      push        Push an image or a repository to a registry  #推送镜像到镜像仓库
      rm          Remove one or more images   #删除一个或多个镜像
      save        Save one or more images to a tar archive (streamed to STDOUT by default)  # 保存一个或多个镜像到tar归档文件
      tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE    #创建一个引用源镜像标记目标镜像

      5.镜像存储的核心技术1:联合文件系统(UnionFS)

      • Union文件系统是一种分层、轻量级并且高性能的文件系统
      • 它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下
      • Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像可以制作各种具体的应用镜像
      • 镜像是只读的  如果要修改镜像内容,需要通过dockerfile重新打包
    [
        {
            "Id": "sha256:f35646e83998b844c3f067e5a2cff84cdf0967627031aeda3042d78996b68d35",
            "RepoTags": [
                "nginx:latest"
            ],
            "RepoDigests": [
                "nginx@sha256:ed7f815851b5299f616220a63edac69a4cc200e7f536a56e421988da82e44ed8"
            ],
            "Parent": "",
            "Comment": "",
            "Created": "2020-10-13T08:39:44.146921461Z",
            "Container": "30fd95c5c49c51e06f02efdb7f6cf22adc04ac7e88eb0ccd0ec3e3f40adae506",
            "ContainerConfig": {
                "Hostname": "30fd95c5c49c",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "ExposedPorts": {
                    "80/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "NGINX_VERSION=1.19.3",
                    "NJS_VERSION=0.4.4",
                    "PKG_RELEASE=1~buster"
                ],
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "#(nop) ",
                    "CMD ["nginx" "-g" "daemon off;"]"
                ],
                "ArgsEscaped": true,
                "Image": "sha256:f85f5bff1b6ddc8f428f8528f19c24e9c2284fec8ce02dbc1899b971f4b525cf",
                "Volumes": null,
                "WorkingDir": "",
                "Entrypoint": [
                    "/docker-entrypoint.sh"
                ],
                "OnBuild": null,
                "Labels": {
                    "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
                },
                "StopSignal": "SIGTERM"
            },
            "DockerVersion": "18.09.7",
            "Author": "",
            "Config": {
                "Hostname": "",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "ExposedPorts": {
                    "80/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "NGINX_VERSION=1.19.3",
                    "NJS_VERSION=0.4.4",
                    "PKG_RELEASE=1~buster"
                ],
                "Cmd": [
                    "nginx",
                    "-g",
                    "daemon off;"
                ],
                "ArgsEscaped": true,
                "Image": "sha256:f85f5bff1b6ddc8f428f8528f19c24e9c2284fec8ce02dbc1899b971f4b525cf",
                "Volumes": null,
                "WorkingDir": "",
                "Entrypoint": [
                    "/docker-entrypoint.sh"
                ],
                "OnBuild": null,
                "Labels": {
                    "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
                },
                "StopSignal": "SIGTERM"
            },
            "Architecture": "amd64",
            "Os": "linux",
            "Size": 132861270,
            "VirtualSize": 132861270,
            "GraphDriver": {
                "Data": {
                    "LowerDir": "/data/docker/overlay2/9a7891c56c2c5d6dce8e6ea6908f46457bf3073c1750fa4e2f83da5ecebac600/diff:/data/docker/overlay2/b882d0d8e96dc7e32eaa9692c2668dc267b8593a9003ee7839934db27b4114c7/diff:/data/docker/overlay2/46e4bd643cdd4ad59126fb76f42c36ca80c7211049e462411e41c6659c2ec1b5/diff:/data/docker/overlay2/228cf784c84527507350240ac39d525961ec00c0faace0c26e3fab1c799da5b9/diff",
                    "MergedDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/merged",
                    "UpperDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/diff",
                    "WorkDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/work"
                },
                "Name": "overlay2"
            },
            "RootFS": {
                "Type": "layers",
                "Layers": [
                    "sha256:d0fe97fa8b8cefdffcef1d62b65aba51a6c87b6679628a2b50fc6a7a579f764c",
                    "sha256:f14cffae5c1add412127e0704008bb8e730773c0945345c9ea61b7e6eabea8e5",
                    "sha256:280ddd108a0a0ef53ed20d6715facc1cdd9497ef05cad03c3e5b73521a588511",
                    "sha256:fe08d9d9f18556ca241f00b6efd6c7b25767463084e14c05da9e535c0782409c",
                    "sha256:cdd1d8ebeb066bd40f9be824201afe18f0d4fe93b8462353921f0277c09e1289"
                ]
            },
            "Metadata": {
                "LastTagTime": "0001-01-01T00:00:00Z"
            }
        }
    ]
    View Code

      

      6.镜像存储的核心技术2:写时复制(COW)

      • 当docker第一次启动容器时,初始读写层是空的。当文件系统发生变化时,这些变化都会应用到读写层
      • 需要修改容器层(读写)里的文件时,会先把镜像里要写的文件复制到自己的文件系统中进行修改,这个机制就是写时复制(Copy-On-Write)
      • 写时复制配合分层机制减少了镜像对磁盘空间的占用和容器启动时间。

          

    "GraphDriver": {
        "Data": {
            "LowerDir": "/data/docker/overlay2/9a7891c56c2c5d6dce8e6ea6908f46457bf3073c1750fa4e2f83da5ecebac600/diff:/data/docker/overlay2/b882d0d8e96dc7e32eaa9692c2668dc267b8593a9003ee7839934db27b4114c7/diff:/data/docker/overlay2/46e4bd643cdd4ad59126fb76f42c36ca80c7211049e462411e41c6659c2ec1b5/diff:/data/docker/overlay2/228cf784c84527507350240ac39d525961ec00c0faace0c26e3fab1c799da5b9/diff",
            "MergedDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/merged",
            "UpperDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/diff",
            "WorkDir": "/data/docker/overlay2/ec42c26408c19e79c6a80d4bdacb42efdc641c0947afb3386d5b70a5a974151d/work"
        },
        "Name": "overlay2"
    }
    
    LowerDir:镜像层  这一层只读
    UpperDir:容器层  这一层可读写
    MergeDir:挂载点 当文件系统挂载后,在merge目录下将同时看到来自各lower和upper目录下的内容,并且用户无法(无需)感知这些文件分别来自lower,哪些来自upper,用户看见的只是一个普通的文件系统根目录而已 
    联合文件系统和写时复制原理都是由overlay2文件存储驱动来实现的 
    docker info |grep Stor
    Storage Driver: overlay2

    六、容器管理

    1.创建容器的常用选项

     2.创建容器时可以根据实际情况做资源限制

    docker run -itd --name centos-init --memory="1024m" --memory-swap="2048m" --oom-kill-disable   centos
    
    docker ps -a | awk '{print $1,$NF}'|grep centos-init 
    70e98a309acc centos-init
    
    docker stats 70e98a309acc
    CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
    70e98a309acc        centos-init         0.00%               1.52MiB / 1GiB      0.15%               0B / 0B             0B / 0B             1

    #内存限制已生效
    OOM事件
    
    OOM(Out Of Memory)内存不足,通常是由于某些不稳定的进程占用过多的内存造成,在Docker中称为OOM事件,当容器使用的内存过多时就会发生OOM事件,
    
    这个事件是由Linux内核的内存管理机制发起,并将是使用占用内存过多的容器Kill掉,保证系统的可持续运行。Linux内核为了保证系统的稳定性而将内存划分为两大部分用户空间与内核空间
    
    用户空间是提供给用户进程所使用的内存空间。内核空间是仅提供给内核运行的空间。用户的进程是无法访问内核空间,而内核是可以访问用户空间与内核空间。
    OOM事件

    3.管理容器

    # cp 宿主机和容器之间互拷贝文件
    Usage:    docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
        docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
    
    Options:
      -a, --archive       Archive mode (copy all uid/gid information)
      -L, --follow-link   Always follow symbol link in SRC_PATH
    
    # exec  在容器里执行命令
    1).进入容器
    docker exec -it 容器id/NAMES  /bin/bash 

     4.NameSpace

    在容器化中,一台物理机可以运行多个不同的操作系统,那就需要解决"隔离性”,彼此感知不到对方的存在,有问题互不影响
    
    Linux内核从2.4.19版本开始引入namespace概念,其目的是将特定的全局系统资源通过抽象方法使得namespace中的进程看起来拥有自己的隔离资源。docker就是借助这个机制实现了容器资源的隔离
    
    Linux的NameSpace机制提供了6种不同命名空间:
        IPC:隔离进程间通信
        MOUNT:隔离文件系统挂载点(一个容器是一个独立的操作系统)
        NET:隔离网络协议栈
        PID:隔离进程号,进程命名空间是一个父子结构,子空间对父空间可见
        USER:隔离用户
        UTS:隔离主机名和域名

    ls /proc/$$/ns
    ipc mnt net pid user uts

     5.CGroups

    docker利用namespace实现了容器隔离,但是namespace不能对容器做资源限制,比如cpu、内存
    
    如果某一个容器属于CPU密集型任务,那么会影响其他容器使用CPU,导致多个容器相互影响并抢占资源,这就要用到CGroups(Control Groups),限制容器资源
    
    CGroups:所有的任务就是运行在系统中的一个进程,而CGroups以某种标准将一组目标进行资源分配和控制,例如CPU、memory、net等,并且可以动态配置
    
    docker update --help 
    
    Usage:    docker update [OPTIONS] CONTAINER [CONTAINER...]
    
    Update configuration of one or more containers
    
    Options:
          --blkio-weight uint16        Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
          --cpu-period int             Limit CPU CFS (Completely Fair Scheduler) period
          --cpu-quota int              Limit CPU CFS (Completely Fair Scheduler) quota
          --cpu-rt-period int          Limit the CPU real-time period in microseconds
          --cpu-rt-runtime int         Limit the CPU real-time runtime in microseconds
      -c, --cpu-shares int             CPU shares (relative weight)
          --cpus decimal               Number of CPUs
          --cpuset-cpus string         CPUs in which to allow execution (0-3, 0,1)
          --cpuset-mems string         MEMs in which to allow execution (0-3, 0,1)
          --kernel-memory bytes        Kernel memory limit
      -m, --memory bytes               Memory limit
          --memory-reservation bytes   Memory soft limit
          --memory-swap bytes          Swap limit equal to memory plus swap: '-1' to enable unlimited swap
          --pids-limit int             Tune container pids limit (set -1 for unlimited)
          --restart string             Restart policy to apply when a container exits
    
    
    CGroups主要功能:
        限制进程组使用的资源数量:可以为进程组设定使用上限,例如内存
        进程组优先控制:可以为进程组分配特定的CPU、磁盘io吞吐量
        记录进程组使用的资源数量:例如记录某个进程组使用的CPU时间
        进程组控制:可以将进程组挂起和恢复            
    
    # 查看cgroups可控制的资源:ll /sys/fs/cgroup/
    blkio:块设备io
    cpu:限制CPU时间片的分配,与cpuacct挂载同一目录
    cpuacct:生成cgroup中的任务占用cpu资源的报告,与CPU挂载同一目录
    cpuset:给cgroup中的任务分配独立的CPU和内存节点
    devices:允许或拒绝cgroup中的任务访问设备
    freezer:暂停/恢复cgroup中的任务
    hugetlb:限制使用的内存页数量
    memory:对cgroup中任务的可用内存进行控制,兵自动生成资源占用报告
    net_cls:使用等级标识符标记网络数据包,这让Linux流量控制程序可以识别来自特定cgroup任务的数据包,并进行网络限制
    net_prio:允许基于cgroup设置网络流量优先级
    perf_event:允许使用perf工具来监控cgroup
    pids:限制任务数量
    
    
    容器实际资源限制位置:
    /sys/fs/cgroup/<资源名>/docker/<容器ID>

    七、容器数据持久化

    docker提供三种方式将数据从宿主机挂载到容器中:
        volumes:docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)
    bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中
    tmpfs:挂载存储在主机系统的内存中,而不会写入宿主机文件系统。如果不希望将数据持久化存储,可以使用tmpfs,同时避免写入容器可写层提高性能

    1.volumes   

    由docker负责创建、管理。docker  volume
    
    默认情况下创建的volume本质上还是宿主机文件系统的一个目录,与普通目录无本质区别。
    一个volume可以同时供多个container使用,如果没有container使用volume,它不会自动删除,需要运行docker volume prune明确删除
    
    通过使用第三方提供的volume driver,用户可以将数据持久化到远程主机或者云存储中,也就是说存储空间可以不由宿主机提供
    docker volume --help 
    
    Usage:    docker volume COMMAND
    
    Manage volumes
    
    Commands:
      create      Create a volume
      inspect     Display detailed information on one or more volumes
      ls          List volumes
      prune       Remove all unused local volumes
      rm          Remove one or more volumes
    # 创建volume
    docker volume create nginx-vol
    
    # 查看volume的详细信息
    docker volume inspect nginx-vol 
    [
        {
            "CreatedAt": "2020-11-10T16:37:22+08:00",
            "Driver": "local",
            "Labels": {},
            "Mountpoint": "/data/docker/volumes/nginx-vol/_data",
            "Name": "nginx-vol",
            "Options": {},
            "Scope": "local"
        }
    ]
    
    # 如果修改了Docker Root的目录,则对应相关目录都会被修改
    
    # 用volume创建个容器
        docker run -itd --name nginx --mount src=nginx-vol,dst=/usr/share/nginx/html nginx  
        
        docker run -itd --name nginx -v nginx-vol:/usr/share/nginx/html nginx
    
    # 删除volume
    docker stop nginx     # 停止使用该卷的容器
    docker rm -f nginx    # 删除使用该卷的容器
    docker volume rm nginx-vol   # 再删除此卷

    # 如果指定的卷不存在,则自动创建

    2.bind mounts

    本质上是宿主机、container之间共享宿主机文件系统。这种持久化的方法更导致container与宿主机的偶合过于紧密,所以不推荐使用
    # 用卷创建一个容器
    docker run -itd --name=nginx --mount type=bind,src=/root/www,dst=/usr/share/nginx/html nginx
    
    docker run -itd --name=nginx1 -v /root/www:/usr/share/nginx/html nginx 
    
    # 验证 
    docker inspect nginx 
    [
        {
            "Id": "324328596c9bbdb97c436b0399147d68a484ca6764f8fe34403a794b1c44ffbc",
            "Created": "2020-11-10T09:03:08.761761701Z",
            "Path": "/docker-entrypoint.sh",
            "Args": [
                "nginx",
                "-g",
                "daemon off;"
            ],
            "State": {
                "Status": "running",
                "Running": true,
                "Paused": false,
                "Restarting": false,
                "OOMKilled": false,
                "Dead": false,
                "Pid": 6828,
                "ExitCode": 0,
                "Error": "",
                "StartedAt": "2020-11-10T09:03:09.281253027Z",
                "FinishedAt": "0001-01-01T00:00:00Z"
            },
            ..........
            "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/root/www",
                    "Destination": "/usr/share/nginx/html",
                    "Mode": "",
                    "RW": true,
                    "Propagation": "rprivate"
                }
            ],
            ...........
    ]

    # 如果源文件/目录没有存在,会报错,如下
    docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /root/www.

    # 如果目标在容器中是非空目录,则该目录现有内容被隐藏

    应用场景

    volume:
        • 多个运行容器之间共享数据, 多个容器可以同时挂载相同的卷。
        • 当容器停止或被移除时,该卷依然存在。
        • 当明确删除卷时, 卷才会被删除。
        • 将容器的数据存储在远程主机或其他存储上(间接)
        • 将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes/)
    
    bind mounts
        • 从主机共享配置文件到容器。默认情况下,挂载主机/etc/resolv.conf到每个容器,提供DNS解析。
        • 在Docker主机上的开发环境和容器之间共享源代码。例如,可以将Maven target目录挂载到容器中,每次在Docker主机
    上构建Maven项目时,容器都可以访问构建的项目包。
        • 当Docker主机的文件或目录结构保证与容器所需的绑定挂载一致时
    
    tmpfs:
        有特定的应用场景。比如docker可将用户名与密码等敏感数据保存在某个数据库中,当启动需要访问这些敏感数据的container或者service时,docker会在宿主机上创建一个tmpfs,然后将敏感数据从数据库读出写到tmpfs中,再将tmpfs mount到container中,安样能保证数据安全。当容器停止运行时,则相应的tmpfs也从系统中删除

    八、docker容器网络

    1.四种网络模式

    docker network --help 
    
    Usage:    docker network COMMAND
    
    Manage networks
    
    Commands:
      connect     Connect a container to a network
      create      Create a network
      disconnect  Disconnect a container from a network
      inspect     Display detailed information on one or more networks
      ls          List networks
      prune       Remove all unused networks
      rm          Remove one or more networks
    
    Run 'docker network COMMAND --help' for more information on a command.
    • bridge 

        -network=bridge
        默认网络,docker启动后会创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
        也可以自定义网络,相比默认的具备内部dns发现,可以通过容器名之间通信

    • host

        -network=host

        容器不会获得一个独立的notwork namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络都,其他都是隔离的

    • none

        --network=none

        获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置

    • container

        --network=container:Name/ID 

        与指定容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都是隔离的

    2.docker网络模型

    • veth pair

        成对出现的一种虚拟设备,数据从一端进,从另一端出。用于解决网络命名空间之间的隔离,每启动一个容器就会对应启动一个veth

    • docker0

        网桥是一个二层网络设备,通过网桥可以将Linux支持的不同端口连接起来,并实现类似交换机那样的多对多的通信

    3、容器网络访问原理

     

     九、定制容器镜像

    DockerFile常用指令

    • FROM

        构建新镜像是基于哪个镜像

        FROM centos:latest

    • RUN

        构建镜像时运行的shell命令

        shell格式:   

        RUN <命令行命令>    # <命令行命令> 等同于,在终端操作的 shell 命令。
        RUN yum install wget -y

       exec格式:
        RUN ["可执行文件","参数1","参数2"]
        RUN ["run.sh","release","V0.2"] #等同于./run.sh release V0.2    
       *****注意:Dockerfile的指令每执行一次都会在docker上新建一层,所以过多无意义的层,会造成镜像膨胀过大,可以把要执行的shell命令通过&&连接起来放在一行执行
    • CMD

        类似于RUN指令,用于运行程序,但二者运行的时间点不同

      • CMD在docker run时运行
      • RUN在docker build时运行

        作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD指令指定的程序可被docker run命令行参数中指定要运行的程序覆盖 

        注意:如果dockerfile中存在多个CMD指令,仅最后一个生效

        格式:

      • CMD [“executable”,“param1”,“param2”] : exec形式(首选)  
      • CMD [“param1”,“param2”] : 作为ENTRYPOINT的默认参数 
      • CMD command param1 param2 : Shell形式 
    • ENTRYPOINT

        类似于CMD命令,但其不会被docker run的命令行参数指定的指令所覆盖,而且这些命令行参数会被当做参数传给ENTRYPOINT指令指定的程序

        但是,如果运行docker run时使用了--entrypoint选项,此选项的参数可当做要运行的程序覆盖ENTRYPOINT指令指定的程序

        优点:在执行docker run的时候可以指定enterpoint运行时所需的参数

        注意:如果Dockerfile中存在多个ENTRYPOINT指令,仅最后一个生效

        格式:

      • ENTRYPOINT ["executable", "param1", "param2"]
      • ENTRYPOINT command param1 param2

        可以搭配CMD命令使用:一般是变参才会使用CMD,这里的CMD等于是在给ENTRYPOINT传参

        可参考:https://www.runoob.com/docker/docker-dockerfile.html

    • LABEL

        标签:用于描述此镜像的作者以及作用,根据实际情况描述

    • EXPOSE

        仅仅是声明端口

        作用:

      • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射
      • 在运行时使用随机端口映射时,也就是docker run -p时,会自动映射EXPOSE的端口
    • ENV

        设置环境变量,可以在后续指令中调用这个环境变量

        ENV PATH $PATH:/usr/local/nginx/sbin
        示例:

          设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

          ENV NODE_VERSION 7.2.0

          RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz"

            && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
    • ADD

        解压压缩包并拷贝

        格式:

          ADD  src dest

          ADD  nginx-1.15.5.tar.gz  / 

    • COPY

        拷贝文件或目录到镜像中,一般用于项目镜像(将项目代码打包到镜像中)

        格式:

          COPY  src  dest

          COPY  nginx.conf  /usr/local/nginx/conf/nginx.conf

    • VOLUME

        定义匿名数据卷。在启动容器时忘记挂载数据卷,自动挂载到匿名卷

        作用:

      • 避免重要数据,因容器重启而丢失。这是非常致命的
      • 避免容器不断变大。例如日志目录

        格式:

          VOLUME  "目录的绝对路径"

          VOLUME "/usr/src/app/release/config" 
                 "/usr/src/app/release/logs"

    • USER

        为RUN  CMD和ENTRYPOINT执行命令时指定运行用户

    • WORKDIR

        为RUN CMD  ENTRYPOINT COPY 和ADD设置工作目录

    docker build构建镜像

    Usage:    docker build [OPTIONS] PATH | URL | -
    Options:
      -t --tag list     #镜像名称
      -f --file string   #指定Dockerfile文件的位置 dockerfile可以是远程位置的
      
      # docker build -t shykes/myapp .
      # docker build -t shykes/myapp -f /path/Dockerfile /path
      # docker build -t shykes/myapp http://www.example.com/Dockerfile
    FROM centos:7
    LABEL nginx  chunke_li
    RUN rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm && 
        yum install nginx -y 
    EXPOSE 80 
    CMD ["/usr/sbin/nginx","-g","daemon off;"]
    docker build -t nginx:v3 -f Dockerfile . 
    Sending build context to Docker daemon  2.048kB
    Step 1/5 : FROM centos:7
     ---> 7e6257c9f8d8
    Step 2/5 : LABEL nginx  chunke_li
     ---> Using cache
     ---> 99791e9a003e
    Step 3/5 : RUN rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm &&     yum install nginx -y
     ---> Using cache
     ---> 36a9fe459afb
    Step 4/5 : EXPOSE 80
     ---> Using cache
     ---> 3f0083ee6294
    Step 5/5 : CMD ["/usr/sbin/nginx","-g","daemon off;"]
     ---> Running in 3ed93f11530d
    Removing intermediate container 3ed93f11530d
     ---> 46f08f11c53f
    Successfully built 46f08f11c53f
    Successfully tagged nginx:v3
    编写Dockerfile最佳实践:
    • 减少镜像层:一次RUN指令形成新的一层,尽量shell命令都写在一行,减少镜像层
    • 优化镜像大小:一次性RUN形成新的一层,如果没有在同一层删除,无论文件是否最后删除,都会带到下一层,所以在每一层清理对应的残留数据,减小镜像大小
    • 减少网络传输时间:例如软件包、仓库等
    • 多阶段构建:代码编译、部署在一个Dockerfile中完成,指挥保留部署阶段产生数据
    • 选择最小的基础镜像:例如alpine
  • 相关阅读:
    查看mongodb的状态
    superset----缓存之redis
    superset--presto sql
    linux----之tcpdump小用
    Git版本回退的最佳方式
    SpringBoot 热部署
    不使用Tomcat,手写简单的web服务
    Spring Security 入门
    Maven总结
    git高级用法
  • 原文地址:https://www.cnblogs.com/lichunke/p/13931240.html
Copyright © 2011-2022 走看看