Docker

Docker

概述

安装时把原始环境一模一样的复制过来,只需要一次配置好环境,换到别的机子上就可以一键部署好

三要素

  • 仓库:集中存放镜像文件的场所
  • 镜像:只读的模板
  • 容器:镜像的实例

虚拟机与容器虚拟化

  • 虚拟机:带环境安装的一种解决方案
    • 在一种操作系统里运行另一种操作系统
    • 资源占用多,冗余步骤多,启动慢
  • Linux容器:对进程进行隔离
    • 没有硬件虚拟,较为轻便
    • 容器间互相隔离

安装

镜像加速配置

启动Docker后台容器(测试运行hello-world)

  • docker run hello-world

底层原理

  • Docker是CS结构,守护进程运行在主机上,通过Socket连接从客户端访问,守护进程接收客户端命令并管理运行在主机上的容器

Docker和VM

  • Docker
    • 与宿主共享OS
    • 镜像小
    • 几乎无额外性能损失
    • 轻便灵活
    • 面向软件开发者
    • 快速部署
  • VM
    • 宿主机OS上运行虚拟机OS
    • 镜像大
    • 需要额外的CPU,内存消耗
    • 与虚拟化技术耦合度高
    • 面向硬件运维者
    • 部署较慢

命令

帮助

  • docker version
  • docker info
  • docker --help

镜像

  • 列出本地主机上的镜像:docker images
    • -a:列出本地所有的镜像(含中间映像层)
    • -q:只显示镜像ID
    • --digests:显示镜像的摘要信息
    • --no-trunc:显示完整的镜像信息
  • 查找镜像:docker search [OPTIONS] 镜像名字
    • --no-trunc:显示完整的镜像描述
    • -s:列出收藏数不小于指定值的镜像
    • --automated:只列出automated build类型的镜像
  • 下载镜像:docker pull 镜像名字[:TAG]
    • docker pull tomcat等价于docker pull tomcat:latest
  • 删除镜像:docker rmi 镜像名字ID
    • docker rmi -f 镜像ID:删除单个
    • docker rmi -f 镜像名1:TAG 镜像名2:TAG:删除多个
    • docker rmi -f $(docker images -qa):删除全部

容器

  • 新建并启动容器:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

    • --name="容器新名字":为容器指定一个名称
    • -d:后台运行,返回容器ID(守护式容器)
    • -i:以交互模式运行容器,通常与-t同时使用
    • -t:为容器重新分配一个伪输入终端,通常与-i同时使用
    • -P:随机端口映射
    • -p:端口映射,有一下四种格式
      • ip:hostPort:containerPort
      • ip::containerPort
      • hostPort:containerPort
      • containerPort
    1
    2
    docker run -it -p 8888:8080 tomcat
    # Docker对外暴露的端口号8888与Tomcat服务的端口8080映射
  • 列出当前所有正在运行的容器:docker ps [OPTIONS]

    • -a:列出当前所有正在运行+历史上运行过的容器
    • -l:显示最近创建的容器
    • -n:显示最近n个创建的容器
    • -q:静默模式,只显示容器编号
    • --no-trunc:不截断输出
  • 退出容器

    • 方式1,容器停止退出:exit
    • 方式2,容器不停止退出:ctrl+P+Q
  • 启动容器:docker start 容器ID或者容器名

  • 重启容器:docker restart 容器ID或者容器名

  • 停止容器:docker stop 容器ID或者容器名

  • 强制停止容器:docker kill 容器ID或者容器名

  • 删除已停止的容器:docker rm 容器ID

    • 一次性删除多个容器
      • docker rm -f $(docker ps -a -q)
      • docker ps -a -q | xargs docker rm
  • 重要

    • run的时候一定要加--privileged=true,否则服务容易出错
    • 启动守护式容器:docker run -d 容器名
      • 后台运行的容器必须有一个前台进程,若不是一直挂起的命令就会自动退出
    • 查看容器日志:docker logs -f -t --tail 容器ID
      • -t:加入时间戳
      • -f:跟随最新的日志打印
      • --tail 数字:显示最后多少条
    • 查看容器内运行的进程:docker top 容器ID
    • 查看容器内部细节:docker inspect 容器ID
    • 进入正在运行的容器并以命令行交互
      • docker exec -it 容器ID bashShell命令
        • docker exec -t 容器ID bashShell命令:容器中运行命令并直接返回
      • 重新进入:docker attach 容器ID
      • 上述两个区别
        • attach直接进入容器启动命令的终端,不会启动新的进程
        • exec是在容器中打开新的终端,并且可以启动新的进程
    • 从容器内拷贝文件到主机上:docker cp 容器ID:容器内路径 目的主机路径

镜像

概述

  • 用来打包软件运行环境和基于运行环境开发的软件,它支持对文件系统的修改作为一次提交来层层叠加,联合文件系统是Docker镜像的基础

原理

  • 最底层是bootfs,bootfs上一层是rootfs

    1
    2
    3
    4
    Tomcat
    JDK
    CentOS
    Kernel

commit

  • docker commit:提交容器副本使之成为一个新的镜像

    • docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]

      1
      docker commit -m "With vim, dataVolumeContainer1 and dataVolumeContainer2" -a "PhineasZ" 3051806a3837 pz/debian-vim:1

容器数据卷

概述

  • 容器的持久化,类似于Redis里的rdb和aof文件。可以使容器之间继承+共享数据
  • 数据卷可在容器之间共享或重用数据
  • 卷中的更改可以直接生效
  • 数据卷中的更改不会包含在镜像的更新中
  • 数据卷的生命周期一致持续到没有容器使用它为止

容器内添加数据卷方法

  • 直接命令添加

    • 命令:docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名

      1
      docker run -it -v /myDataVolume:/dataVolumeContainer debain
      • 查看数据卷是否挂载成功:docker inspect 容器名

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        "Volumes": {
        "/dataVolumeContainer": "myDataVolume"
        }
        "VolumesRW": {
        "/dataVolumeContainer": true
        }
        ……
        "HostConfig": {
        "Binfs": [
        "/myDataVolume:/dataVolumeContainer"
        ],
        ……
        }
      • 容器和宿主机之间数据共享。容器停止退出后,主机修改后数据也同步

    • 命令(对容器只读):docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名

      1
      docker run -it -v /myDataVolume:/dataVolumeContainer:ro debain
      • 只允许主机单向传给容器
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      "Volumes": {
      "/dataVolumeContainer": "myDataVolume"
      }
      "VolumesRW": {
      "/dataVolumeContainer": false
      }
      ……
      "HostConfig": {
      "Binfs": [
      "/myDataVolume:/dataVolumeContainer:ro"
      ],
      ……
      }
  • DockerFile添加

    • 根目录下新建mydocker文件夹并进入

    • File构建

      1
      2
      3
      4
      5
      FROM debian
      # 可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷
      VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
      CMD echo "finished,--------success1"
      CMD /bin/bash
    • build后生成镜像

      1
      docker build -f /Users/mousse/Docker/Dockerfile -t pz/debian .
    • run容器

    • 宿主机上的文件夹自动生成默认地址

  • Docker挂载主机目录Docker访问出现connot open directory .: Permission denied的解决办法:在挂在目录后多加一个--privileged=true

    1
    docker run -it -v /myDataVolume:/dataVolumeContainer --privileged=true debain

数据卷容器

  • 命名的容器挂载数据卷,其它容器通过挂载这个父容器实现数据共享,挂载数据卷的容器称之为数据卷容器

  • 容器间传递共享

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

    • 先启动一个父容器dc01,在dataVolumeContainer2新增内容

      1
      docker run -it --name dc01 pz/debian-vim:1
    • dc02/dc03继承自dc01:--volumes-from

      1
      2
      docker run -it --name dc02 --volumes-from dc01 pz/debian-vim:1
      docker run -it --name dc03 --volumes-from dc01 pz/debian-vim:1
    • dc01/dc02/dc03互相之间都能共享,dc01后也无妨

DockerFile

概述

  • 用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本
  • 构建三步骤
    1. 编写Dockerfile文件
    2. docker build
    3. docker run

构建过程

  • 基础知识
    • 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
    • 指令按照从上到下,顺序执行
    • #表示注释
    • 每条指令都会创建一个新的镜像层,并对镜像进行提交
  • 大致流程
    1. docker从基础镜像运行一个容器
    2. 执行一条指令并对容器作出修改
    3. 执行类似docker commit的操作提交一个新的镜像层
    4. docker再基于刚提交的镜像运行一个新容器
    5. 执行dockerfile中的下一条指令直到所有指令都执行完成
  • 总结
    • DockerFile:软件原材料,面向开发
    • DockerImage:软件交付品,交付标准
    • DockerContainer:软件运行态,部署运维

体系结构(保留字指令)

  • FROM:基础镜像,当前新镜像是基于哪个镜像的
  • MAINTAINER:镜像维护者的姓名和邮箱地址
  • RUN:容器构建时需要运行的命令
  • EXPOSE:当前容器对外暴露出的端口
  • WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
  • ENV:用来在构建镜像过程中设置环境变量
  • ADD:将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
  • COPY:类似ADD,拷贝文件和目录到镜像中
    • 将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
    • COPY src dest
    • COPY ["src", "dest"]
  • VOLUME:容器数据卷,用于数据保存和持久化工作
  • CMD:指定一个容器启动时要运行的命令
    • Dockerfile 中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
  • ENTRYPOINT:指定一个容器启动时要运行的命令
    • ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数
  • ONBUILD:当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
    • 子镜像通过FROM继承

案例

  • Base镜像(scratch):Docker Hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的

  • 自定义镜像debian

    1
    2
    3
    4
    5
    6
    7
    8
    9
    FROM debian
    # VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
    # ENV mypath /home
    # WORKDIR $mypath
    RUN apt update
    RUN apt install vim -y
    RUN apt install net-tools -y
    # EXPOSE 80
    CMD /bin/bash
  • CMD/ENTRYPOINT镜像案例

    • 都是指定一个容器启动时要运行的命令

    • CMD

      • Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被 docker run之后的参数替换
    • ENTRYPOINT

      • docker run之后的参数会被当做参数传递给ENTRYPOINT,之后形成新的命令组合
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      # 制作CMD版可以查询IP信息的容器
      FROM debian
      RUN apt update
      RUN apt install curl -y
      CMD ["curl", "-s", "http://ip.cn"]

      # 如果我们希望显示 HTTP 头信息,就需要加上 -i 参数
      FROM debian
      RUN apt update
      RUN apt install curl -y
      ENTRYPOINT ["curl", "-s", "http://ip.cn"]
  • ADD/COPY镜像案例:自定义镜像Tomcat9

    • 将jdk和tomcat安装的压缩包拷贝进目录

      • apache-tomcat-9.0.8.tar.gz
      • jdk-8u171-linux-x64.tar.gz
      • copyFile.tar.gz
    • 目录下新建Dockerfile文件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      FROM debian
      MAINTAINER pz<pz@mousse.cc>
      COPY copyFile.tar.gz /usr/local/copyFile.tar.gz
      ADD jdk-8u171-linux-x64.tar.gz /usr/loacl
      ADD apache-tomcat-9.0.8.tar.gz /usr/loacl
      RUN apt update
      RUN apt install vim -y
      ENV /usr/local
      WORKDIR $MYPATH
      # 配置Java与Tomcat环境变量
      ENV JAVA_HOME /usr/local/jdk1.8.0_171
      ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
      ENV CATALINA_HOME /ust/local/apache=tomcat-9.0.8
      ENV CATALINA_BASE /ust/local/apache=tomcat-9.0.8
      ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
      # 运行容器时监听的端口
      EXPOSE 8080
      CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out
      1
      docker run -d -p 8081:8080 --name mytomcat9 -v /host/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test -v /host/mydockerfile/tomcat9/logs:/usr/local/apache-tomcat-9.0.8/apache-tomcat-9.0.8/logs --privileged=true pz/tomcat9

发布到云