Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

基于 Dockerfile 的镜像生成

  • Dockerfile

    • 镜像的描述文件,定义了如何基于base镜像逐层构建出Docker镜像
  • base镜像

    • 不依赖其他镜像,从scratch构建
      • 以CentOS镜像为例,仅有三行
        FROM scratch
        ADD centos-7-docker.tar.xz /
        CMD ["/bin/bash"]
        
        • 会添加tar包,并自动解压到/根目录下,生成/dev/proc/bin等目录
    • 大小只有 几十 或 几百MB
      • 为什么这么小?
      • 因为打包的只是rootfs,底层直接用Host宿主机的kernel
  • 镜像的生成原理——逐层构建

    • 基于base镜像,用一条条命令构造出一个个镜像层,往上堆叠
      • 可通过 history指令 查看已有镜像的堆叠层次
        docker history <image_id>或镜像名
        
    • 好处
      • 具备缓存特性,可共享资源
        • 多个镜像中,由底层到中间某层若内容相同,则硬盘可以只保存一份,直接利用
          • 实现机制
            • 根据每一层堆上去后的已知所有层的sha值去做记录和比较
          • 比如base镜像就可以只存一份
          • 但如果中间多了一层不一样,就算上面全部一样,此特性也会失效
            • 因为sha值的机制,多了的一层,导致后面计算出的所有层sha值都都是全新的
        • 可以加上--no-cache禁用此特性
    • 注意
      • 镜像层不允许被修改
      • 镜像启动生成容器后,所有修改都只会发生在更上层的容器层
      • 两种层次,联合在一起组成统一的文件系统,访问时会从最上层的容器层开始向下找,以最先找到的为准
  • 镜像的生成方法——两种

    • 【不建议】docker commit
      • 步骤+例子
        • 1.根据 base镜像 运行容器
          docker run -it ubuntu
          
        • 2.进入容器内,做修改操作(比如安装软件,添加文件)
          apt-get install -y vim
          
        • 3.将容器保存为新的镜像
          docker commit <container_id>或容器名 新镜像名
          
    • 【推荐】Dockerfile
      • 步骤+例子
        • 1.编写 Dockerfile文件,记录镜像构建要做的修改操作
          # 文件内容
          FROM ubuntu
          RUN apt-get install -y vim
          
        • 2.用 build命令 执行文件
          docker build -t 新镜像名 .
          
          • 会出现一系列step,中途会生成临时容器,在里面执行,等待直到出现successfully即可
          • 参数
            • -t 指定新镜像的名字
            • . 指定 build context 为宿主机的工作目录
              • 会在这里面搜寻Dockerfile文件
              • 指令中的 src相对路径 会根据这个目录 组合扩展成 绝对路径
              • 注意
                • 这里会把 build context 内的所有文件和子目录,全部发送到 docker 进行处理,所以要确保这个目录的纯净,否则构建会缓慢
              • 也可以用-f指定文件在 build context 下相对的真实位置
                • 好处
                  • 允许 Dockerfile 在任意子目录内,且为任意名字
  • 文件中常用的指令

    • 基本

      • FROM

        • 指定base镜像
      • WORKDIR

        • 指定后面指令在容器内的工作目录
          • 指令中的 dest相对路径 会根据这个目录 组合扩展成 绝对路径
        • 好处
          • 避免了RUN cd … && do-something的难看写法
          • 【注意!!!】 这里如果分两行写,RUN cd … 和 RUN do-something,是达不到想要的目的的!!,cd在这里会失效,因为两个RUN代表两层,第一层的cd改变,不会被继承到第二层,每一层都会从WORKDIR重新开始!!!
      • ENV

        • 设置环境变量,可以被紧跟其后的命令使用
          ENV MY_VERSION RUN apt-get install -y mypackage=$MY_VERSION
          
    • 文件操作

      • COPY

        • 将文件从 build context 复制到镜像
          • 下面的 src 只能指定 build context 中的文件和目录
        • 两种书写方式
          • Shell格式
            COPY src dest
            
          • Exec格式
            COPY ["src", "dest"]
            
      • ADD

        • 也是将文件从 build context 复制到镜像
        • 区别在于,如果 src 是归档文件(tar、zip等),会被自动解压到 dest
    • 指令运行

      • RUN
        • 指定构建时在容器中要运行的命令
        • 常用于安装软件
      • CMD
        • 指定等容器启动时运行的命令
        • 可以有多个CMD,但只有最后一个生效
        • 可以被docker run命令后的参数替换掉
      • ENTRYPOINT
        • 也是指定等容器启动时运行的命令
        • 也是可以有多个CMD,但只有最后一个生效
        • 这里同样也有Shell和Exec格式的区别
          • 例子1
            
            
  • 文件中不常用的指令

    • EXPOSE
      • 指定容器中的进程会监听的端口
        EXPOSE 3000
        
        • 可以顺便学习ARG,指定构建过程的参数(它与ENV有区别,因为不会出现在容器运行时)
          ARG port=3000
          EXPOSE $port