zoukankan      html  css  js  c++  java
  • 第四节:docker镜像原理剖析和制作镜像两种方式 (通过容器 和 通过Dockerfile)

    一. docker镜像原理剖析

    灵魂三问:

    1. docker 镜像的本质是什么?

    2. docker中一个centos镜像大约200M左右,为什么一个centos系统的iso安装文件要好几个G?

    3. docker中一个tomcat镜像大约500M左右,为什么一个tomcat安装包不足100M呢?

    1. 操作系统扫盲

      操作系统由:进程调度子系统、进程通信子系统、内存管理子系统、设备管理子系统、文件管理子系统、网络通信子系统、作业控制子系统组成。

      Linux的文件管理子系统由bootfs和rootfs组成。

    (1). bootfs:包含bootloader(引导加载程序)和 kernel(内核)

    (2). rootfs: root文件系统,包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc等标准目录和文件

    PS: 不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos等

    2. 镜像原理

    (1). Docker镜像是由特殊的文件系统叠加而成,最底端是 bootfs,并使用宿主机的bootfs;第二层是 root文件系统rootfs,称为base image;然后再往上可以叠加其他的镜像文件。

    (2). 统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。

    (3). 一个镜像可以放在另一个镜像的上面。位于下面的镜像称为父镜像,最底部的镜像成为基础镜像。

    (4). 当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器。

     

    3. 解答灵魂三问

    (1). docker 镜像的本质是什么?

    答:是一个分层的文件系统。

    (2). docker中一个centos镜像大约200M左右,为什么一个centos系统的iso安装文件要好几个G?

    答:centos的iso文件包括bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs。

    (3). docker中一个tomcat镜像大约500M左右,为什么一个tomcat安装包不足100M呢?

    答:docker中的镜像是分层的,tomcat虽然只有70多M,但是它需要依赖父镜像和基础镜像,所有整个对外暴露的tomcat镜像大约500M左右。

    二. 容器转为镜像

    1. 容器变为镜像

    (1). 指令

    docker commit <containerId> 镜像名称:版本号

    注:不加版本号的话,默认为latest

      将容器制作为镜像,容器内挂载目录(数据卷)下的文件不会被包含!!!其它非挂在目录下的文件都会被一起打包转为容器。

    (2). 案例

     在一个名为mycentoscon1的centos容器中的工作目录下,新建一个11.txt文件,然后把这个容器转为一个镜像,名为myowincentos1。

     

    2. 如何移动迁移镜像

    (1). 把镜像制成压缩包

    指令:

    docker save -o 压缩文件名称 镜像名称:版本号

    (2). 再把压缩包转为镜像

     指令:

    docker load -i 压缩文件名称

    三. 通过Dockerfile制作镜像

    1. 制作镜像的指令

    docker build -f dockerfile文件路径 -t 镜像名称:版本号 .

     (1).  -f dockerfile文件路径 : dockerfile文件可以自定义命名,比如:ypfdockerfile,只要指定路径即可。

     注:如果在当前目录下,且名字就叫 Dockerfile,可以省略 【 -f dockerfile文件路径】  简版指令为 【docker build -t 镜像名称:版本号 .】

     (2). 如果不指定版本号,默认为latest

     (3). 指令最后必须有: 1个空格+1个点

    2. 什么是Dockerfile文件 

    Dockerfile 是一个文本文件包含了一条条的指令,每一条指令构建一层,基于基础镜像,最终构建出一个新的镜像。他有以下作用

    (1).对于开发人员:可以为开发团队提供一个完全一致的开发环境。

    (2).对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了。

    (3).对于运维人员:在部署时,可以实现应用的无缝移植。

    一张图说明几个核心配置

    分享几个Dockerfile案例: 

    A.自己制作一个nginx镜像

    FROM centos:7.6
    RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
    WORKDIR /nginx
    COPY nginx-1.15.2.tar.gz /nginx
    RUN tar -zxvf  nginx-1.15.2.tar.gz
    RUN cd nginx-1.15.2 && ./configure && make && make install
    EXPOSE 8080
    COPY nginx.sh /nginx.sh
    RUN chmod 755 /nginx.sh
    CMD [“/nginx.sh”]

    B.自己制作一个core webapi镜像

    #1.依赖两个基础镜像
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim 
    FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster 
    
    #2.制作人
    MAINTAINER ypf <ypf@qq.com>
    
    #3.指定程序运行的端口(也可以在项目中通过UseUrls指定, 或者发布容器的时候通过--env ASPNETCORE_URLS=xxx动态指定) 
    ENV ASPNETCORE_URLS=http://*:9000
    
    #4.容器对外暴露的端口
    EXPOSE 9000
    
    #5.指定默认工作目录
    WORKDIR /userapi
    
    #6. 将当前目录(Dockerfile文件下)的所有文件拷贝到镜像的userapi工作目录下
    COPY . /userapi/
    
    #7.启动容器的时候执行shell命令:dotnet webapi1.dll,即运行该项目
    ENTRYPOINT ["dotnet", "webapi1.dll"]

    C. 自定义一个centos镜像 

    #1.定义依赖镜像(宿主机中没有话则去下载)
    FROM centos:7
    
    #2.定义作者信息(可以不写)
    MAINTAINER ypf <ypf@qq.com>
    
    #3. 执行安装vim的命令(-y表示安装过程中不提示)
    RUN yum install -y vim 
    
    #4. 定义默认的工作目录
    WORKDIR /ypfusr
    
    #5 定义容器启动执行的命令
    CMD /bin/bash

    3. 剖析

    (1). FROM 

     定义构建新镜像所需依赖的父镜像(基础镜像)。

    FROM centos:7.6

    (2). MAINTAINER  或 LABEL

     定义镜像的作者。

    MAINTAINER ypf <ypf@qq.com>
    # 或者用 LABEL (推荐)
    LABEL maintainer="ypf"

    (3) .ENV

     设置环境变量

    # 设置asp.net项目启动端口为8000(程序中不设置的情况下用)
    ENV ASPNETCORE_URLS=http://*:8000 
    # 设置Java环境
    ENV JAVA_HOME /usr/local/jdk1.11.0
    # 设置mysql的密码
    ENV MYSQL_ROOT_PASSWORD 123456

    (4). EXPOSE

      声明容器运行的端口。

    PS:在通过docker run 指令构建容器的要通过-p 将宿主机的端口和容器端口进行映射。

    (5). RUN

     指定构建镜像所需要运行的shell命令

    #解压并安装
    RUN tar -zxvf  nginx-1.15.2.tar.gz
    RUN cd nginx-1.15.2 && ./configure && make && make install
    # 安装vim
    RUN yum install -y vim

    (6). WORKDIR

     指定工作目录,发布成容器时,默认进入的就是这里指定目录。

    #定义默认的工作目录
    WORKDIR /ypfusr

    (7). VOLUME

     指定生成容器时挂载宿主机的目录

    VOLUME ["/var/lib/mysql"]

    注:基本上不在Dockerfile文件中使用,而是在构建容器的时候通过 -v 指令来设置。 

    (8) . ADD

     拷贝文件或目录到镜像中  (此处要测试一下,如果镜像中的目录不存在是否会自动创建???)

    #将当前目录中xx1.tar.gz 复制到镜像中的/home/test文件夹下,并自动解压
    ADD xx1.tar.gz /home/test
    #下载xx2到镜像中的/home/test文件夹中
    ADD https://xxx.com/xx2.tar.gz /home/test
    #将当前目录下的start.sh 复制到镜像中的目录中
    ADD ./start.sh  /start.sh

    PS:当拷贝的是压缩包或者URL的时候,会自动解压或自动下载。

    (9). COPY

     拷贝文件或目录到镜像中,同ADD,但不支持自动下载和解压。

    # 将当前目录下的start.sh 复制到镜像中的目录中
    COPY ./start.sh /start.sh

    注:ADD和COPY的共同特点是 只能复制Dockerfile所在目录下的文件,如果目标镜像中的路径不存在,会自动创建。

    (10). CMD

     启动容器时执行的shell命令。

    # 启动容器时候下面指令效果等效:
    # ENTRYPOINT ["dotnet", "webapi1.dll"]
    # ENTRYPOINT dotnet webapi1.dll
    # CMD ["dotnet", "webapi1.dll"]
    # CMD dotnet webapi1.dll

    (11). ENTRYPOINT

     启动容器时执行的shell命令。同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序

    # 启动容器时候下面指令效果等效:
    # ENTRYPOINT ["dotnet", "webapi1.dll"]
    # ENTRYPOINT dotnet webapi1.dll
    # CMD ["dotnet", "webapi1.dll"]
    # CMD dotnet webapi1.dll

    注:如果存在多个ENTRYPOINT,仅最有一个生效。

    (12).  HEALTHCHECK

     健康检查

    HEALTHCHECK --interval=5m --timeout=3s --retries=3 
    CMD curl -f http:/xxxx/ || exit 1

     参数说明:

     --interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒

     -- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒

     -- start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒

     -- retries=N (default: 3):认为检测失败几次为宕机,默认3次

    一些返回值的说明:

      0:容器成功是健康的,随时可以使用

      1:不健康的容器无法正常工作

      2:保留不使用此退出代码

    (13).  USER

     为RUN、CMD、ENTRYPOINT执行shell命令指定用户

    USER <user>[:<usergroup>]
    USER <UID>[:<UID>]
    USER ypf

    (14).  ARG

     构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

     构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

    格式:ARG <参数名>[=<默认值>]
    #Dockerfile文件中
    ARG user=ypf #构建镜像的时候覆盖 docker build --build-arg user=lmr webapi1 .
     

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    python模板引擎Cheetah的安装
    cocos2d 动作
    【leetcode】合并两个有序数组
    【leetcode】合并二叉树
    【leetcode】合并两个有序链表
    【leetcode】链表的中间结点
    【leetcode】使用最小花费爬楼梯
    【leetcode】栈的最小值
    【leetcode】最小绝对差
    【leetcode】玩筹码
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/13643320.html
Copyright © 2011-2022 走看看