Docker核心技术基础

docker简介

前置知识

  • linux命令

  • git

  • Docker相关开发语言和技术

    • Swarm
    • Compose
    • mesos
    • Machine
    • k8s
    • CI/CD jenkins整合

是什么

  • 问题:为什么会有Docker出现

    • 开发和运维环境的 差异导致部署失败

    • 出于高并发以及快速响应的需要 系统新功能需要快速上线(秒级)

    • 软件可以带环境安装

      • 安装的时候,把原始环境一模一样地复制过来 开发人员利用Docker可以消除协作编码时“在我的机器上可以正常工作”的问题
  • Docker理念

    • 打破代码即应用的理念 变成镜像即应用
    • 一次构建,处处运行
  • 一句话

    • 是解决了运行环境和配置问题的软件容器, 是方便做持续集成并有助于整体发布的容器虚拟化技术

能干嘛

  • 之前的虚拟机技术

    • 虚拟机是带环境安装的一种解决方案

    • 它可以在一种操作系统里面运行另一种操作系统,应用程序对此毫无感知。虚拟机看上去跟真实系统完全一样,对于底层系统来说,虚拟机就是一个普通文件,不需要就可以删除。 这类虚拟机完美地运行了另一套系统,能够使应用程序、操作系统和硬件三者之间的逻辑不变

    • 缺点:

      • 资源占用多
      • 冗余步骤多
      • 启动慢
  • 容器虚拟化技术

    • Linux发展了另一种虚拟化技术,LXC

    • Linux容器不是模拟一个完整地操作系统,而是对进程进行隔离 容器和虚拟机不同,不需要捆绑一个完整的操作系统,只需要软件工作所需要的库资源和设置

    • 重点就是容器是共用操作系统内核的,不进行硬件虚拟

    • 每个容器是相互隔离的,每个容器都有自己的文件系统,容器之间进程不会相互影响,能够区分计算资源

  • 开发/运维(DevOps)

    • 开发自运维

    • 一次构建,随处运行 一次构建是指开发工程师做一次构建 无需运维工程师再做构建 随处运行是指对于这个构建的交付物,可以随处运行

      • 更快捷的应用交付和部署
      • 更便捷的升级和扩缩容
      • 更简单的系统运维
      • 更高效的计算资源利用
  • 企业级

    • 新浪

      • Docker、Mesos等容器新技术使得 对应用进行大规模动态调度成为可能
    • 美团

    • 蘑菇街

去哪下

  • 官网

    • docker官网:http://www.docker.com
    • docker中文网站:https://www.docker-cn.com
  • 仓库

Docker安装

前提说明

  • Centos Docker安装

    • Centos7 (64bit)

    • Centos6.5(64bit)或更高

  • 前提条件

    • Centos7 系统为64位,内核版本为3.10以上
    • Centos6.5 或更高版本,系统为64位,内核版本为2.6.32-431或更高版本
  • 查看自己的内核版本

    • Centos 6

      • uname -r
        用于打印当前操作系统相关信息 (内核版本号、硬件架构、主机名称和操作系统类型)

      • lsb_release -a

      • 看明细

    • Centos 7

      • cat /etc/redhat-release

Docker的基本组成

  • 镜像

    • 就是一个只读的模板,java中的Class。镜像可以用来创建Docker容器,一个镜像可以创建很多的容器
  • 容器

    • 镜像的实例,java中的instance Docker利用容器独立运行的一个或者一组应用 容器可以被启动、开始、停止、删除。 每一个容器都是相互隔离的、保证安全的平台

    • 可以把容器看作是简易版的Linux环境(包括root用户权限、进程空间、用户控件和网络空间)和运行在其中的应用程序

    • 容器的定义和镜像几乎是一样的,也是一堆层的统一视角,唯一却别在与容器的最上层是可读可写的

  • 仓库

    • 仓库是集中存放镜像文件的场所

    • 仓库和仓库注册服务器是有区别的

      • 仓库注册服务器上往往存放着多个仓库 每个仓库又包含了多个镜像,每个镜像 有不同的标签(tag)
    • 仓库分为公开仓库和私有仓库两种形式

    • 最大的公开仓库是Docker Hub (https://hub.docker.com) 它存放了数量庞大的镜像供用户下载 国内的公开仓库包括阿里云、网易云等

  • 小结

    • Docker本身是一个容器运行载体或者称之为管理引擎 我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个环境就称之为image镜像文件。只有通过这个镜像文件才能生成Docker容器,image文件可以看作是容器的模板。Docker根据image文件生成容器的实例。同一个image文件,可以生成多个同时运行的容器实例
    • imags文件生成的容器实例,本身也是一个文件,称之为镜像文件
    • 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是容器
    • 仓储就是存放一堆镜像文件的地方,我们可以把镜像发布到仓储中,需要的时候从仓储中拉下来就可以了

安装步骤

  • Centos6.8 安装docker

    • yum install -y epel-release

      • Docker使用EPEL发布,RHEL系的OS首先要确保已经持有EPEL 仓库,否则先检查OS的版本,再安装相应的EPEL包
    • yum install -y docker-io

    • 安装后的配置文件:/etc/sysconfig/docker

    • 启动Docker后台服务: service docker start

    • docker version验证

  • Centos7安装docker (64位操作系统)

  • yum makecache fast

  • 安装社区版docker

    • sudo yum -y install docker-ce
  • 启动docker

    • sudo systemctl start docker
  • 确认docker安装成功

    • sudo docker run hello-world

    • 配置镜像加速

    • 卸载 systemctl stop docker yum -y remove docker-ce rm -rf /var/lib/docker

永远的HelloWorld

(这个阶段需要配置阿里云镜像 因为这个阶段需要拉取各种镜像)

  • 所谓的配置镜像是指 配置dockerhub的镜像站点

  • 阿里云镜像加速

    • 是什么

    • 注册一个属于自己的阿里云账户(可复用淘宝帐户)

    • 获得加速器地址链接

    • 配置本机docker运行镜像加速器

      • centos6.8

        • 您可以通过修改配置文件/etc/sysconfig/docker来使用加速器(这个文件是docker的配置文)将获得的自己帐户下的阿里云加速地址配置进other_args="–register-mirror=https://****.mirror.aliyuncs.com"service docker restart
      • centos7

        • 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
          1
          2
          3
          4
          5
          6
          7
          8
          
          sudo mkdir -p /etc/docker
          sudo tee /etc/docker/daemon.json <<-'EOF'
          {
            "registry-mirrors": ["https://********.mirror.aliyuncs.com"]
          }
          EOF
          sudo systemctl daemon-reload
          sudo systemctl restart docker
          
    • 重新启动Docker后台服务

      • service docker restart(centos6.8)
      • systemctl restart docker(centos7)
    • Linux系统下配置完加速器需要检查是否生效

      • ps -ef|grep docker

        • 看是否有阿里云网址在后面 (只支持centos6)
  • 网易云加速

    • 基本同阿里云

      • 地址变成https://hub-mirror.c.163.com
  • 启动Docker后台容器(测试运行hello world)

    • docker run helloworld

      • 相当于docker run helloworld:latest
    • run干了什么

      • 先在本地找helloworld这个镜像
      • 如果找不到,就去仓库中去找,找到后pull到本地
      • 根据这个镜像启动一个容器

底层原理

  • Docker是怎么工作的

    • Docker是一个CS结构的系统,Docker守护进程运行在主机上,然后通过socket连接从客户端访问,守护进程从客户端接收命令并管理运行在主机上的容器。容器,是一个运行时环境
  • Docker为什么比vm快

    • docker有着比虚拟机更少的抽象层。docker不需要实现硬件资源虚拟化,docker上的程序直接使用的是实际物理机的硬件资源,因此在cpu、内存利用率上docker有明显的优势
    • docker利用的是宿主机的内核,而不是vm的内核,所以加载docker容器会很快。那这就是说,centos上的容器只能跑在centos的机器上

docker常见命令

帮助命令

  • docker version

    • 检查docker版本
  • docker info

    • 检查docker详细信息

      • 可以看到镜像存储的目录
      • 可以看到镜像站点的网址
  • docker –help

    • docker [OPTIONS] COMMAND [arg…]

镜像命令

  • docker images

    • 列出本地主机上的镜像

      • REPOSITORY:表示镜像的仓库源
      • TAG:镜像的标签
      • IAMGE ID :镜像的ID
      • CREATED:镜像创建时间
      • SIZE:镜像大小
      • 同一个仓库源可以有多个TAG,代表这个仓库源的不同版本,我们使用REPOSITORY:TAG来定义不同的镜像。 如果你不指定一个镜像的版本标签,例如你只是用ubantu,docker默认将使用ubantu:latest镜像
    • OPTIONS说明

      • -a:列出本地所有的镜像(含中间镜像层)
      • -q: 只显示镜像ID
      • –digest:显示镜像的摘要信息
      • –no-trunc:显示完整的镜像信息
      • 常见用法
  • docker search 某个镜像名

    • 网站

      • https://hub.docker.com

      • 注意:查询是从https://hun.docker.com上查询 下载则是从阿里云上下载,前提是配置了镜像网站

    • 命令

      • docker search [OPTIONS] 镜像名字

      • OPTIONS说明

        • –no-trunc:显示完整地镜像描述
        • -s : 列出收藏数不小于指定值的镜像
        • –automated:只列出automated build类型的镜像
  • docker pull 某个镜像名

    • 下载镜像

    • docker pull 镜像名字:[TAG]

      • 如果省略TAG,则默认为latest
  • docker rmi 某个镜像id(或唯一镜像名)

    • 删除镜像

      • docker rmi -f 强制删除
      • 当镜像有相对应的容器在运行时,可以强制删除
    • 删除单个镜像

    • 删除多个镜像

      • docker rmi -f 镜像名1:TAG 镜像名2:TAG
    • 删除全部镜像

      • docker rmi -f $(docker images -qa)
  • 思考

    • 思考是否会有docker commit/docker push命令?

容器命令

  • 有镜像才能创建容器,这是根本前提

    • docker pull centos
  • 新建并启动容器

    • docker run [OPTIONS] IMAGE [COMMAND] [arg…]

      • OPTIONS说明

        • 有些是一个减号,有些是两个减号

        • –name=“容器新名字”:为容器指定一个 名称

        • -d :后台运行容器,并返回容器ID,也即启动守护式容器

        • -i: 以交互模式运行容器,通常和-t同时使用

        • -t:为容器重新分配一个伪输入终端,通常与-i同时使用

        • -P: 随机端口映射

        • -p: 指定端口映射,有四种格式

          • ip:hostPort:containerPort
          • ip:containerPort
          • hostPort:containerPort
          • containerPort
      • 启动交互式容器

        • docker run -it centos /bin/bash

          • 使用镜像centos:latest以交互模式启动一个容器,在容器中执行/bin/bash命令
  • 列出当前所有正在运行的容器

    • docker ps [OPTIONS]

      • OPTIONS说明

        • -a : 列出当前所有正在运行的容器+历史上运行过的容器

        • -l : 显示最近创建的容器

        • -n: 显示最近n个创建的容器

          • docker ps -n 5
        • -q: 静默模式,只显示容器编号

        • –no-trunc :不截断输出

  • 退出容器

    • 两种退出方式

      • exit 容器停止退出
      • ctrl+P+Q 容器不停止退出
  • 启动容器

    • docker start 容器ID或者容器名
  • 重启容器

    • docker restart 容器ID或者容器名
  • 停止容器

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

    • docker kill 容器ID或者容器名
  • 删除已停止的容器

    • docker rm 容器ID或者容器名

      • docker rm -f $(docker ps -qa)
      • docker ps -qa |xargs docker rm
  • 重要内容

    • 启动守护式容器

      • docker run -d 镜像名
        • docker run -d centos 即是使用镜像centos:latest以后台模式启动一个容器
        • 然而Docker容器后台运行,必须有一个前台进程容器运行的命令如果不是那些一直挂起的命令(比如运行top、tail),就会自动退出
        • 这是由docker的机制决定的,因此,最好是将你要运行的程序以前台进程的形式运行
    • 查看容器日志

      • docker logs -f -t –tail 容器ID

        • -t 加入时间戳
        • -f 跟随最新的日志打印
        • –tail 数字 显示最后多少条日志
      • docker run -d centos /bin/sh -c “while true ;do echo hello zzyy;sleep 2;done”

    • 查看容器内部运行的进程

      • docker top 容器ID
    • 查看容器内部细节

      • docker inpsect 容器ID
      • 该命令相当于查看容器本身的各种属性,内容以json串的形式返回
    • 进入正在运行的容器并以命令行交互

      • docker exec -it 容器ID bashshell

        • 优选这个命令

        • 变体

          • docker exec -t 容器名 命令

            • docker exec -t **** ls -l /tmp
            • 直接在容器中执行ls -l /tmp,但不需要返回容器中的伪终端相当于在宿主机中直接执行了容器中的命令
          • docker exec -t 容器ID /bin/bash

            • 等价于docker exec -it 容器ID
      • 重新进入docker attach 容器ID

      • 上述两个命令的区别

        • attach 直接进入容器启动命令的终端,不会启动新的进程

          • 所以如果启动命令阻塞比较严重的时候,所有attach的终端都会同时阻塞而且启动命令如果有打印的时候,所有attach的终端都会同时打印
        • exec 是在容器中打开新的终端,并且可以启动新的进程

          • 因此这个命令会更好一些
    • 从容器内拷贝文件到主机上

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

小总结

  • 常用命令图

  • 常用命令简介

Docker镜像

是什么

  • UnionFS(联合文件系统)

    • UnionFS是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来层层的叠加,同时可以将不同的目录挂载到统一个虚拟文件系统下。Union文件系统是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种集体的应用镜像
    • 特点:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
  • Docker镜像加载原理

    • docker的镜像实际上是有一层一层的文件系统组成,这种层级的文件系统叫UnionFS
    • bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,linux刚启动的时候会加载bootfs文件系统,在Docker镜像的最底层就是bootfs。这一层与我们典型的Linux/unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs
    • rootfs(root file system)在bootfs智商。包含的就是典型的linux系统中的/dev、/proc、/bin、/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如centos等
    • 对于一个精简的os,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs
  • 分层的镜像

    • 例如,在下载的过程中可以看到docker的镜像是一层一层的在下载
  • 为什么Docker镜像要采用这种分层结构呢

    • 最大的好处:共享资源
    • 比如:有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保存一份base镜像,同时内存中也只需加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享

特点

  • 镜像都是只读的,当容器启动的时候,一个新的可写层被加载到镜像的顶部,这一层通常能被称作“容器层”。“容器层”之下的都叫“镜像层”

Docker镜像commit操作补充

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

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

  • 这是制作镜像的一种方式,另外还有一种方式就是使用dockerfile

  • 案例演示

    • 从Hub上下载tomcat镜像到本地并成功运行

      • docker run -it -p 8080:8080 tomcat

        • -p 主机端口:docker容器端口

        • -P 随机分配端口

          • docker run -P tomcat
        • -i 交互

        • -t 终端

    • 故意删除上一步镜像生产tomcat容器的文档

    • 也即当前的tomcat运行实例是一个没有文档内容的容器以它为模板commit一个没有doc的tomcat新镜像

    • 启动这个新的镜像,并和原来的相比,发现新的容器中就没有doc文档

  • docker run -d -p 6666:8080 tomcat 后台启动tomcat容器

Docker 四种网络模式

host模式

容器与宿主机共享网络,也就是容器端口跟数据端口一致,通过访问宿主机端口可以直接访问容器。

启动方式:

container模式

none模式

bridge模式

Docker容器数据卷

是什么

  • docker理念

    • 将运用于运行的环境打包形成容器,运行可以伴随容器,但是我们对数据的要求希望是持久化的
    • 容器之间希望有可能共享数据
  • Docker容器产生的数据,如果不通过dockercommit生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除之后,数据自然也就不存在了

  • 为了保存数据,在docker中我们使用卷

  • 类俗语Redis中的RDB和AOF

能干嘛

  • 主要功能

    • 容器中数据的持久化
    • 容器间继承和共享数据
  • 功能介绍

      • 卷是目录或者文件,存在于一个或者多个容器中,由Docker挂载到容器,但不属于联合文件系统,因此能够绕过UnionFileSystem,提供一些用于持续存储或共享数据的特性
    • 卷的设计目的

      • 设计卷的目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷
    • 特点

      • 数据卷可在容器之间共享或者重用数据
      • 卷中的更改可以直接生效
      • 数据卷中的更改不会包含在镜像的更新中
      • 数据卷的生命周期一直持续到没有容器使用它为止

数据卷

  • 容器内添加

    • 直接命令添加

      • 命令

        • docker run -it -v /宿主机绝对目录:/容器内目录 镜像名
      • 查看数据卷是否挂载成功

        • docker inspect 容器ID 可以查看
      • 容器和宿主机之间数据共享

      • 容器停止退出后,宿主机修改后数据是否同步

        • 启动镜像生成容器并设置数据卷,然后在数据卷中新建、修改文件宿主机和容器都会同步
        • 接着,容器退出,继续在宿主机的数据卷目录中修改、更新、删除文件
        • 然后再start刚才退出的容器
        • 在容器退出期间,宿主机中对数据卷更新的操作更继续同步到再次start的容器数据卷中
      • 命令(带权限)

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

          • readOnly
        • 查看读写权限 docker inspect 容器ID

          • VolumesRW 是否为true
    • DockerFile添加

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

      • 可在DockerFile中使用VOLUME指令来给镜像添加一个或者多个数据卷

        • VOLUME["/dataVolumnContainer",“dataVolumeContainer2”,"/dataVolumeContainer3"]这是在一个容器中添加了多个数据卷,它们都指向宿主机的同一个目录
        • 处于可移植和分享的考虑,用-v主机目录:容器目录这种方式不能够直接在DockerFile中使用因为主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录
      • File构建

        • #volume test
          1
          2
          3
          4
          
          FROM centos
          VOLUME["dataVolumeContainer1","/dataVolumeContainer2"]
          CMD echo "finished,---------success1"
          CMD /bin/bash
          
      • build后生成镜像

        • 得到一个新的镜像

        • docker build -f /mydockerfile -t nicole/centos .

          • 这个.是什么意思???

            • 代表使用当前路径的 Dockerfile 进行构建
      • run容器

      • 通过上述步骤,容器内的卷目录地址已经知道,对应的主机目录地址是什么呢??

        • 可以通过docker inspect 容器ID查看宿主机对应的数据卷路径地址
        • 主机对应默认地址
    • 备注

      • Docker挂载主机目录Docker访问出现cannot open directory:: Permission denied 解决办法:在挂载目录后多加一个 –privileged=true参数据可

数据卷容器

  • 是什么

    • 命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器
  • 总体介绍

    • 以上一步新建的镜像nicole/centos为模板并运行容器dc01/dc02/dc03

    • 这三个容器已经具备数据卷

      • /dataVolumeContainer1
      • /dataVolumeContainer2
  • 容器间传递共享(–volumes-from)这是一种命令行上的类似继承的写法

    • 先启动一个父容器dc01

      • 在容器dc01中,在/dataVolumeContainer2目录中新增内容
    • dc02/dc03继承自dc01

      • –volume-from

      • 命令

        • docker run -it –name dc02 –volume-from dc01 nicole/centos
      • 分别进入dc02/dc03容器中,然后分别在/dataVolumeContainer2各自新增内容

    • 回到dc01可以看到02/03各自添加的都能共享了

    • 删除dc01,dc02修改之后,dc03可否访问?

      • 可以的
    • 删除dc02后dc03可否访问?

      • 可以的
    • 新建dc04继承dc03后再删除dc03

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

这是个星形的关联结构

Dockerfile解析

是什么

  • DockerFile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本

  • 构建三步骤

    • 编写DockerFile文件

      • docker build

        • docker run
  • 文件什么样

    • hub.docker.com中可以看到

    • FROM scratch

      • scratch是祖先镜像类,即基础镜像所有镜像的最底层的祖先

DockeFile构建过程解析

  • dockerfile内容基础知识

    • 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
    • 指令按照从上到下,顺序执行
    • #表示注释
    • 每条指令都会创建一个新的镜像层,并对镜像进行提交
  • Docker执行Dockerfile的大致流程

    • docker从基础镜像运行一个容器
    • 执行一条指令并对容器作出修改
    • 执行类似docker commit的操作提交一个新的镜像层
    • docker再基于刚提交的镜像运行一个新的容器
    • 执行dockerfile中的下一条指令制导所有的指令都执行完成
  • 小总结

    • 从应用软件的角度来看,Dockerfile\Docker镜像\Docker容器分别代表了软件的三个不同阶段
    • Dockerfile是软件的原材料
    • Docker镜像是软件的交付品
    • Docker容器则可以认为是软件的运行态
    • Dockerfil面向开发、Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合理充当Docker体系的基石
    • 容器是直接提供服务的,某种程度上,容器替代了进程的概念

DockerFile体系结构

(保留字指令)

  • FROM

    • 基础镜像,当前新的镜像是基于哪个镜像
  • MAINTAINER

    • 镜像的维护者姓名和邮箱
  • RUN

    • 镜像在构建的时候需要运行的命令(注意是构建的时候)
  • EXPOSE

    • 镜像宣称对外暴露的端口
  • WORKDIR

    • 指定在创建容器后,终端默认登录进来的工作目录,相当于登录用户的初始落脚点
  • ENV

    • 用来在构建镜像过程中设置环境变量
    • 例如:ENV MY_PATH /usr/mytest 这个环境变量可以在后续的任何RUN指令中使用,和就如同在命令前面指定了环境变量前缀一样,也可以在其他指令中直接使用这些环境变量,如 WORKDIR $MT_PATH
  • ADD

    • 将宿主机目录下的文件拷贝进镜像且add命令会自动处理URL和解压tar压缩包
  • COPY

    • 类似ADD,拷贝文件和目录到镜像中将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置

      • COPY src dest
      • COPY [“src”,“dest”]
  • VOLUME

    • 容器数据卷,用于数据保存和持久化工作
  • CMD

    • 这个命令非常重要: 指定一个容器启动时需要运行的命令
    • DockerFile中可以有多个CMD/但是只有最后一个生效
    • dockerfile中指定的最后一个CMD命令会被docker run 之后的参数(这个参数也是启动时需要运行的命令)替代
  • ENTRYPOINT

    • 指定一个容器启动时要运行的命令
    • ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数
    • 如果dockerfile中使用ENTRYPOINT,那么在docker run之后的参数,会被添加到ENTRYPOINT后面的运行命令的后面,作为ENTRTYPOINT指定的运行命令的参数来起作用
  • ONBUILD

    • 当构建一个继承父镜像的子镜像时,父镜像的dockerfile文件中如果有ONBUILD,那么在构建子镜像的时候,这个onbuild会被触发
    • 注意:是在构建子镜像的过程中,将触发执行父镜像的dockerfile文件中的ONBUILD指令

案例

  • Base镜像(scratch)

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

      • FROM scratch
  • 自定义镜像myCentos

    • 编写

      • 先在Hub查找默认Centos镜像的DockerFile,并了解其中的内容

        • 现状

          • 初始Centos运行镜像时进的默认路径是/
          • 默认不支持vim
          • 默认不支持ifconfig
        • 需求

          • 登录后默认路径不是/
          • 支持vim编辑器
          • 支持查看网络配置ifconfig
      • 准备编写DockerFile文件

        • FROM centos 从本地镜像继承
        • ENV mypath /TMPWORKDIR $mypath
        • RUN yum install -y vim
        • RUN yum install -y net-tools
        • EXPOSE 80
        • CMD /bin/bash
      • myCentos内容dockerfile2

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        
        FROM centos
        MAINTAINER nicole<sadgump@163.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 "success-------ok"
        CMD /bin/bash
        
    • 构建

      • docker build -f dockerfile2 -t nicole/myCentos:1.0 .
    • 运行

      • docker run -it nicole/myCentos:1.0
    • 列出镜像的变更历史

      • docker history 镜像名
      • 通过这个命令可以查看一个镜像有多少层,每一层执行了什么指令因此这个命令也很重要
  • CMD/ENTRYPOINT镜像案例

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

    • CMD

      • DockerFile中可以有多个CMD指令,但只有最后一个会生效

      • CMD会被docker run命令后面的命令覆盖

      • Case案例

        • tomcat的讲解演示

          • docker run -it -p 8888:8080 tomcat ls -l
          • 使用上面的命令启动容器,tomcat就会根本不启动原因就在于tomcat镜像中指定了启动容器时要执行catalina.sh run但这个命令被docker run -it -p 8888:8080 ls -l这个启动命令中的ls -l替换掉了
    • ENTRYPOINT

      • docker run 之后的字符串会被当作参数传递给ENTRYPOINT,之后形成新的命令组合

      • Case案例

        • 制作CMD版可以查询IP信息的容器

          1
          2
          3
          
          FROM centos
          RUN yum install -y curl
          CMD ["curl","-s","http://ip.cn"]
          
          • curl命令简介

            • curl命令可以用来执行下载、发送各种http请求,指定http头部操作,如果系统没有curl可以使用yum install -y curl安装,也可以下载安装

            • curl将下载文件输出到stout

            • 使用命令

            • 上述介绍的是curl的最简单使用方法,用这个命令获取的http://curl.haxx.se指向的页面。同样,如果这里的url指向的是一个文件或者一幅画,都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将只显示文件正文,即html文档。如果要显示全部信息(包括头部),请加参数-i

        • 问题

          • 如果我们希望显示HTTP头信息,就需要加上-i参数

          • 所以我们会希望这么做:docker run -it mycentos -i 也就是希望在启动命令后面加上-i,以期望从外部把参数带入

            • 然而这样就完蛋了-i会把dockerfile中的CMD [“curl”,"-s",“http://ip.cn”] 整个替换掉,但是-i又不是一个命令,所以外部传入的命令就出错了
        • WHY

          • 我们可以看到可执行文件找不到的错误:executable file not found
          • 因为“跟在镜像名后面的是command,运行时会替换CMD的默认值”因此这里的-i替换了原来的CMD,而不是添加在原来的curl -s http://ip.cn后面。但是-i根本不是命令,所以自然找不到
          • 如果我们希望加入-i参数,就必须重新完整的输入整个命令$docker run myip curl -s http://ip.cn
        • 制作ENTRYPOINT版查询IP信息的容器

          1
          2
          3
          
          FROM centos
          RUN yum install -y curl
          ENTRYPOINT ["curl","-s","http://ip.cn"]
          
          • 然后使用docker run -it mycentos -i这样的命令启动容器, 这样就没有问题了
          • docker run -it mycentos -i的-i会被添加到ENTRYPOINT [“curl”,"-s",“http://ip.cn”]中形成ENTRYPOINT [“curl”,"-s","-i",“http://ip.cn”] 也就是等价于CMD curl -s -i http://ip.cn
  • 自定义镜像Tomcat9

    • mkdir -p /nicole/mydockerfile/tomcat9

    • 在上述目录下touch c.txt

      • 新建这个文本文件是为了演示COPY指令在构建镜像的过程中,将本地的c.txt文件copy到镜像中
    • 将jdk和tomcat安装的压缩包拷贝到上述目录中

      • apache-tomcat-9.0.8.tar.gz
      • jdk.8u171-linux-x64.tar.gz
    • 在nicole/mydockerfile/tomcat9目录下新建Dockerfile文件

      • DockerFile文件内容
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        
        FROM centos
        MAINTAINER nicole<sadgump@163.com>
        #把宿主机当前上下文的c.txt拷贝到容器的/usr/local路径下
        COPY c.txt /usr/local/container.txt
        #把java与tomcat添加到容器中
        ADD jdk-8u171-linux-x64.tar.gz /usr/local/
        ADD apache-tomcat-9.0.8.tar.gz /usr/local/
        #安装vim编辑器
        RUN yum install -y vim
        #设置工作访问时候的workdir路径,即登录落脚点
        ENV MYPATH /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 /usr/local/apache-tomcat-9.0.8
        ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
        ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
        #设置容器运行时监听的端口
        EXPOSE 8080
        #启动时运行tomcat
        #ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh"]
        #CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]
        CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/logs/catalina.out
        
        • 比较重要的是几个环境变量的设置
    • 构建

      • docker build -f Dockerfile -t nicole/myTomcat:1.0 .
    • run

      1
      2
      3
      4
      5
      6
      
      docker run -d -p 9080:8080 
      --name nicoleTomcat 
      -v /nicole/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test 
      -v /nicole/mydockerfile/tomcat9/logs:/usr/local/apache-tomcat-9.0.8/logs 
      --privileged=true 
      nicoleTomcat
      
        - 备注
      
        	- 子主题 1
      
      • 最好养成启动容器时就做数据卷的习惯,因为
      • 1、容器中的文件写性能不高
      • 2、数据可能需要做持久化
    • 验证

      • 浏览器访问即可
    • 结合前述的容器卷将测试的web应用test发布

      • 这个功能是利用run做数据卷来实现的数据卷将容器中的webapps/test映射到本地的某个test目录上
      • 因此只要在本地的test目录上部署应用,就相当于在容器中部署了这个应用
      • 视频中重启了容器,目的是想重启tomcat也许是想使得部署的test应用生效,但我觉得这个部署应该是实时生效的,不需要重启tomcat,也就是不需要重启容器

小总结

Docker常用安装

总体步骤

  • 搜索镜像
  • 拉取镜像
  • 查看镜像
  • 启动镜像
  • 停止镜像
  • 移除镜像

安装Tomcat

  • docker hub上面查找tomcat镜像

    • docker search -s 5 tomcat

      • 搜索五星以上的tomcat
      • 即使配置了阿里云镜像地址,也是在dockerhub上查找镜像
  • 从docker hub上拉取tomcat镜像到本地

    • docker pull tomcat

      • 如果配置了阿里云镜像站点,就从阿里云镜像站点拉取镜像到本地否则就从dockerhub上拉取镜像到本地
  • doceker images查看是否成功拉取tomcat镜像到本地

  • 使用tomcat镜像创建容器(也称运行镜像)

    • docker run -it -p 8080:8080 tomcat

      • -p 主机端口:docker容器端口
      • -P 随机分配端口 ( 这里没有指定容器的端口,是不是从dockerfile中的EXPOSE确定了容器的暴露端口?)
      • -i 交互
      • -t 伪终端

安装MySQL

  • docker hub上面查找mysql镜像

  • 从docker hub或者阿里云加速器站点拉取mysql镜像到本地,标签为5.6

    • docker pull mysql:5.6
  • 使用mysql5.6镜像创建容器(也叫运行镜像)

    • 使用mysql镜像

      1
      2
      3
      4
      5
      6
      
      docker run -p 12345:3306 --name mysql 
      -v /nicole/mysql/conf:/etc/mysql/conf.d 
      -v /nicole/mysql/logs:/logs
      -v /nicole/mysql/data:/var/lib/mysql
      -e MYSQL_ROOT_PASSWORD=12345
      -d mysql:5.6
      
      • 需要注意下面几点 1、配置文件地址、日志文件地址、数据文件地址 2、上面这些需要常常写入的文件,都要做数据卷映射到本地,否则会有写入性能问题 3、配置文件也要做数据卷,因为方便修改 4、-e 初始化root的密码,这个要注意(讲师一带而过,但这个很重要)

      • 进入容器 docker exec -it 容器ID /bin/bash

        • mysql -uroot -p
    • 外部win10也来连接运行在docker上的mysql服务

      • 使用SQLYog可以连接宿主机的IP/docker映射出来的端口就可以访问mysql了
    • 数据备份小测试(可以不做)

      • docker exec mysql服务容器ID sh -c ’exec mysqldump –all-database -uroot -p"123456" ’ > /nicole/all-database.sql
      • 第二个exec是什么意思?
      • mysqldump出来的结果返回到宿主机,然后转存到宿主机上的all-database,sql文件中

安装Redis

  • 从docker hub上(阿里云加速器)上拉取redis镜像到本地,标签为3.2

  • 使用redis3.2镜像创建容器(也叫运行镜像)

    • 使用镜像

      1
      2
      3
      4
      5
      6
      
      docker run -p 6379:6379
      -v /nicole/myredis/data:/data
      -v /nicole/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf
      -d redis:3.2 
      redis-server /usr/local/etc/redis/redis.conf 
      --appendonly yes
      
    • 在主机/nicole/myredis/conf/redis.conf/目录下新建redis.conf文件

    • vim /nicole/myredis/conf/redis.conf/redis.conf文件

      • 这就是redis的配置文件可以拷贝标准配置文件
      • 视频中没有重启redis容器以使新的配置文件生效我觉得应该重启一下才对,最后这段视频讲得太仓促效果不是很好
    • 测试redis-client连接上来

      • docker exec -it redis容器ID redis-cli
    • 测试持久化文件生成

      • 看宿主机上的/data中是否有aof文件

这里的安装实际上是说把镜像从云上拉取到

本地,并且运行起来。并不是说在云上的镜像基础上制作自己的镜像

本地镜像发布到阿里云

本地镜像发布到阿里云流程

  • 流程图

镜像的生成方法

  • 编写DockerFile文件,经过构建后生成镜像

  • 从容器创建一个镜像 docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]]

    • OPTIONS说明

      • -a 提交的镜像作者
      • -m 提交使得说明文字

将本地镜像推送到阿里云

  • 本地镜像素材原型

  • 阿里云开发者平台

  • 创建仓库镜像

    • 命名空间
    • 仓库名称
  • 将镜像推送到registry

    • $ sudo docker login –username=******** registry.cn-hangzhou.aliyuncs.com

    • $ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/sadgump/nicole:[镜像版本号]

    • 这里的"镜像版本号"不一定是你本地的镜像的那个版本号可以任意取,最好是有意义的

    • $ sudo docker push registry.cn-hangzhou.aliyuncs.com/sadgump/nicole:[镜像版本号]

    • 这里的镜像版本号要和上一行命令中指定的镜像版本号保持一致否则会报出找不到镜像的错误

    • 这三行代码可以在你自己的阿里云容器仓库的说明页面上找到

    • 完整图示

  • 公有云可以查询到

    • 登录到阿里云镜像仓库中可以看到镜像已经上传
    • 图示
  • 查看详情

    • 从页面中可以查看镜像的详细信息
    • 图示

将阿里云上的镜像下载到本地

  • docker pull 镜像名[:TAG]