美文网首页
Dokcer 的镜像和Dockerfile

Dokcer 的镜像和Dockerfile

作者: wayyyy | 来源:发表于2018-09-23 23:44 被阅读0次
    Docker镜像原理
    镜像分层.png
    • base 镜像
      base镜像又2层含义:

      1. 不依赖其他镜像,从stratch构建
      2. 其他镜像可以已之为基础进行扩展
        base镜像一般是各种linux发行版,比如Ubuntu,centos。
    • 镜像的分层结构
      为什么要采用分层的结构,其中之一的好处就是:共享资源
      有多个镜像都从相同的base镜像构建而来,那么Docker host只需要在磁盘上保存一份base镜像,同时在内存种也只需要加载一份base镜像,就可以为所有的镜像服务。而且,镜像的每一层都可以被共享。

      那么,这时也许会问另一个问题了:如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,那么会影响到其他的容器吗?
      答案是不会,因为容器利用了copy-on-write技术。当容器启动时,一个新的可写层会被加载到镜像的顶部。这一层叫做"容器层","容器层"之下都称作镜像层。

      所有对容器的改动都只会发生在容器层,只有容器层是可写的,容器层下面都是可读的。


    相关命令
    • 列出镜像

      # docker images  # 列出镜像
        REPOSITORY          TAG         IMAGE ID          CREATED             SIZE
        docker.io/python    3.7         db1c801f1c06      3 months ago        926 MB
        docker.io/mysql     latest      102816b1ee7d      3 months ago        486 MB
        docker.io/ubuntu    latest      ea4c82dcd15a      5 months ago        85.8 MB
      

      本地镜像都保存在 Docker 宿主机的 /var/lib/docker 目录下。

      镜像从仓库中下载下来,镜像保存在仓库中,而仓库存在于 Registry 中,默认的 Registry 是由 Dokcer 公司来运营的公共 Registry 服务,即 Docker Hub。

      Docker Hub 中有2种类型的仓库,用户仓库和顶层仓库,用户仓库的镜像都是由Docker用户创建的,而顶层仓库是由Docker内部的人来管理。

      用户仓库名的命名由用户名和仓库名两部分组成的。如 jamtur01/puppet。

      每个镜像仓库都可以存放很多镜像。为了区分同一仓库的不同镜像,Docker提供了标签的功能,通过在仓库名后面加上一个冒号和标签名来指定该仓库中的某一镜像。如果没有指定标签,那么Docker会自动下载latest标签的镜像。

      # docker run -ti --name new_container ubuntu:12.04 /bin/bash # 使用ubuntu:12.04镜像
      
    • 拉取镜像

      # docker pull ubuntu:12.04
      

      通过pull命令先将镜像拉取到本地,可以节省用一个新镜像启动一个容器的所需的时间(用Docker run命令从镜像启动一个容器时,如果该镜像不在本地,Docker会先从Docker Hub下载该镜像)

    • 查找镜像

      # docker search ubuntu
        INDEX       NAME                    DESCRIPTION                                     STARS    OFFICIAL  AUTOMATED
        docker.io   docker.io/ubuntu        Ubuntu is a Debian-based Linux operating s...   9369     [OK]       
        ....    
      

      可以利用该命令来查找所有Docker Hub上公共的可用镜像。

    • 删除镜像

      # docker rmi ubuntu:12.04
      
    • 导出镜像

      docker save -o ubuntu_img.tar ubuntu
      
    • 导入镜像

      docker load -i ubuntu_img.tar
      

    构建镜像

    前面是拉取已经构建好的带有定制内容的 Docker 镜像,那么如何修改和管理自己的镜像,并且更新和管理这些镜像呢?有以下2种方法:

    1. 使用 docker commit 命令
    2. 使用 docker build 命令 和 Dockerfile文件
    • 用Docker的commit命令创建镜像

      1. 运行容器
      2. 修改容器
      3. 将容器保存为新的镜像
      # docker run -i -t ubuntu /bin/bash   # 创建一个容器
      # apt-get -yqq update && apt-get -y install apache2   # 安装apache2软件包(容器内的shell)
      # docker commit jack/apche2:webserver # 提交定制容器
      
    • 用Dockerfile构建镜像
      并不推荐使用docker commit的方法来构建镜像,相反,推荐使用Dcokerfile的定义文件和 docker build命令来构建镜像。

      FROM ubuntu
      RUN apt-get update && apt-get install -y vim
      

      Dockerfile 由一系列的指令和参数组成。每条指令,如FROM,都必须为大写字母。

      Dockerfile 中的指令会按顺序从上到下执行,所以应该更具需要合理安排指令的顺序。

      每条指令都会创建一个新的镜像层并对镜像进行提交。Docker 大体上按照如下流程执行Dockerfile中的指令:

      1. Docker 从基础镜像运行一个容器
      2. 执行一条指令,对容器做出修改
      3. 执行类似docker commit操作,提交一个新的镜像层
      4. Docker 再基于刚提交的镜像运行一个新的容器
      5. 执行Dockerfile中的下一条指令,直到所有指令都执行完毕
      • 构建镜像
        # docker build -t ubuntu-with-vim .
           Sending build context to Docker daemon  2.048kB
        1  Step 1/2 : FROM ubuntu
             ---> ccc6e87d482b
        2  Step 2/2 : RUN apt-get update && apt-get install -y vim
        2a   ---> Running in 31978802f893
            ...
        2b  Setting up vim (2:8.0.1453-1ubuntu1.1) ...
            ...
            ---> aa94ecc262e6
        2c  Removing intermediate container 31978802f893
            Successfully built aa94ecc262e6
            Successfully tagged ubuntu-with-vim:lates
        
        1. 执行FROM,将ubuntu作为base镜像,ubuntu镜像ID为ccc6e87d482b
        2. 执行RUN,安装vim
          2a. 启动ID为31978802f893的临时容器,在容器种安装vim
          2b. 安装成功后,将容器保存为镜像,其ID为aa94ecc262e6
          2c. 删除临时容器31978802f893,镜像aa94ecc262e6构建成功
          1.jpg
          可以用docker history查看镜像的分层构建历史。
      ````
      docker build --no-cache -t="Jack/static_web:v1" 
      ````
      `-t`标志为新镜像设置了仓库和名称。
    

    Dockerfile 中的常用命令
    • FROM
      Dockerfile文件的第一条指令必须是FROM,其后可以是各种镜像的操作指令,最后是CMD或ENTRYPOINT指定容器启动时执行的命令。

    • MAINTAINER

    • CMD 和 ENTRYPOINT
      CMD指令和ENTRYPOINT指令的作用都是为镜像指定容器启动后的命令。

      • CMD
        支持三种格式:

        1. CMD ["executable", "param1", "param2"] 使用 exec 执行,推荐方式。
        2. CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用。
        3. CMD ["param1", "param2"] 提供给 ENTRYPOINT 的默认参数。

        启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令,如果指定了多条命令,只有最后一条会被执行。
        如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

      • ENTRYPOINT
        支持两种格式:

        1. ENTRYPOINT ["executable", "param1", "param2"]
        2. ENTRYPOINT command param1 param2(shell中执行)

        配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。
        每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。

      • 测试1

        • test.sh
          #!/bin/bash
          echo "args: ${@}"
          
        • Dockerfile
          FROM ubuntu
          MAINTAINER 123@123.com
          
          ADD test.sh /
          RUN chmod +x /test.sh
          
          CMD ["/test.sh"]
          
        • 测试结果
          # docker build -t=test1:latest .
          # docker run --rm -ti test1
            args:  
          # docker run --rm -ti test1 /bin/bash -c "echo hello world"
            hello world
          
          可见docker run命令启动容器时指定的运行命令可以覆盖Dockerfile文件中CMD指令指定的命令。
      • 测试2

        • Dockerfile
          FROM ubuntu
          MAINTAINER 123@123.com
          
          ADD test.sh /
          RUN chmod +x /test.sh
          
          ENTRYPOINT ["/test.sh"]
          
        • 测试结果
          # docker build -t=test2:latest .
          # docker run --rm -ti test2
            args:  
          # docker run --rm -ti test2 /bin/bash -c "echo hello world"
            args: /bin/bash -c echo hello world
          
          docker run命令指定的容器运行命令不能覆盖Dockerfile文件中ENTRYPOINT指令指定的命令,反而被当做参数传递给ENTRYPOINT指令指定的命令。
      • 测试3

        • Dockerfile
          FROM ubuntu
          MAINTAINER 123@123.com
          
          ADD test.sh /
          RUN chmod +x /test.sh
          
          ENTRYPOINT ["/test.sh", "arg1"]
          CMD ["arg2"]
          
        • 测试结果
          # docker build -t=test3:latest .
          # docker run --rm -ti test3
            args: arg1 arg2  
          # docker run --rm -ti test3 arg3
            args: arg1 arg3
          
          上面第一个容器的运行结果可以看出CMD指令为ENTRYPOINT指令设置了默认参数;从第二个容器的运行结果看出,docker run命令指定的参数覆盖了CMD指令指定的参数。
      • 注意:
        CMD指令为ENTRYPOINT指令提供默认参数是基于镜像层次结构生效的,而不是基于是否在同个Dockerfile文件中。意思就是说,如果Dockerfile指定基础镜像中是ENTRYPOINT指定的启动命令,则该Dockerfile中的CMD依然是为基础镜像中的ENTRYPOINT设置默认参数。

    • COPY 和 ADD

    • EXPOSE

    • VOLUME

    • ENV

    • LABEL

    分发镜像
    利用Dockerfile制作镜像
    • centos
    FROM centos
    
    RUN yum update -y
    RUN yum install -y vim tcpdump  iproute iproute-doc nc
    
    • 构建镜像
      docker build --no-cache -t="centos_net" ./

    相关文章

      网友评论

          本文标题:Dokcer 的镜像和Dockerfile

          本文链接:https://www.haomeiwen.com/subject/lvfcoftx.html