Docker学习笔记三Docker镜像和仓库


  1. 什么是Docker镜像Docker镜像是由文件系统叠加而成。最底端是一个引导文件系统bootfs,第二层是root文件系统rootfs,第三层以后作为应用层。一 个镜像可以放到另一个镜像的顶部,位于下面的镜像称为父镜像,可以依次类推,直到镜像栈的最底部,最底部的镜像称为基础镜像。当从一个镜像启动容器 时,Docker会在该镜像的最顶层加载一个读写文件系统,我们想在Docker中运行的程序就是在这个读写层中执行的。当Docker第一次启动一个容器时,初始的读写层式空的。当文件系统发生变化时,这些变化都会应用到这一层,比如,如果想修改一个文件,这个文件 首先会从该读写层下面的只读层复制到该读写层,该文件的只读版本依然存在,但是已经被读写层中的该文件副本所隐藏,通常这种机制被称为写时复制, 这是使Docker如此强大的技术之一。每个只读层都是只读的,并且以后永远不会变化,当创建一个新容器时,Docker会构建出一个镜像栈,并在栈的最 顶端添加一个读写层。这个读写层再加上其下面的镜像层以及一些配置数据,就构成了一个容器。容器时可以修改的,它有自己的状态,并且是可以启动和停止的。 容器的这种特点加上镜像分层框架,使我们可以快速构建镜像并运行包含我们自己的应用程序和服务的容器。
  2. 列出,拉取Docker镜像
    $ docker images       
    REPOSITORY         TAG             IMAGE ID           CREATED             VIRTUAL SIZE
    centos             latest          3508c878e883       13 days ago         196.8 MB
    

    本地镜像保存在/var/lib/docker目录下,每个镜像都保存在Docker所采用的存储驱动目录下面,如aufs或者devicemapper。也可以在/var/lib/docker/containers目录下面看到所有的容器。

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

    $ docker pull centos
    $ docker pull ubuntu:12.04
    $ docker pull opensuse:latest
    

    拉取到的镜像会带一系列的标签名,我们可以在镜像名后面跟标签名指定启动的镜像版本

    $ docker run -t -i --name fours_docker ubuntu:12.04 /bin/bash
    $ docker run -t -i --name fours_docker centos:latest /bin/bash
    

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

    用户仓库的命名由用户名和仓库名两部分组成,如jam/puppet。顶层仓库只有仓库名。

  3. 查找镜像
    $ docker search puppet
    NAME                                    DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
    macadmins/puppetmaster                  Simple puppetmaster based on CentOS 6           21                   [OK]
    devopsil/puppet                         Dockerfile for a container with puppet ins...   18                   [OK]
    macadmins/munki-puppet                  Basic munki nginx image with Puppet used f...   7                    [OK]
    devopsil/puppet-yum                                                                     5                    [OK]                      
    

    返回如下信息

    • 仓库名
    • 镜像描述
    • 用户评价(Stars)——反应受欢迎程度
    • 是否官方(Officaial)
    • 自动构建(Automated)——表示这个镜像是由Docker Hub的自动构建流程创建的。
    $ docker run --name mypuppet -d macadmins/puppetmaster
    25041605a61ad1607e1770a3d3665546378ce52a6336df64f5c2aaa1e8c1c923
    
    $ docker exec -t -i mypuppet puppet --version
    3.7.4
    
    $ docker ps
    CONTAINER ID        IMAGE                    COMMAND                  CREATED              STATUS              PORTS               NAMES
    25041605a61a        macadmins/puppetmaster   "/usr/bin/puppet mast"   About a minute ago   Up About a minute   8140/tcp            mypuppet
    
  4. 构建镜像
    • 使用docker commit命令
    • docker build 命令和Dockerfile文件不推荐使用docker commit命令,而应该使用更灵活,更强大的Dockerfile来构建Docker镜像。

    下面开始介绍详细步骤:

    • 创建Docker Hub账号官方网站进行注册,然后验证
      Username: kaelwang
      Password: 
      Email: zb55@foxmail.com
      WARNING: login credentials saved in /root/.docker/config.json
      Login Succeeded
      

      个人认证信息会保存到$HOME/.dockercfg文件中。

    • 用Docker的commit命令创建镜像
      $ docker run -i -t --name myopensuse opensuse /bin/bash
      bash-4.2# zypper install nginx
      bash-4.2# exit
      exit
      $ docker commit -m="a new webdocker image" --author="Kael Wang" myopensuse kaelwang/nginx:webserver
      f06bb467c661f9721500d373959e4de640c69ef7b65056f4ccf51538555d5b72
      $ docker inspect kaelwang/nginx:webserver                        //查看详细信息
      $ docker run -t -i kaelwang/nginx:webserver /bin/bash            //运行新容器
      bash-4.2# rpm -qa | grep nginx
      nginx-1.8.1-5.1.x86_64
      
    • 用Dockerfile构建镜像并不推荐使用docker commit的方法来构建镜像,我们以后最好使用Dockerfile的定义文件和docker build命令构建镜像。Dockerfile使用基本的基于DSL语法的指令来构建一个Docker镜像,之后使用docker build命令基于该Dockerfile中的指令构建一个新的镜像。开始我们第一个Dockerfile
      $ mkdir webdocker
      $ cd webdocker/
      $ vi Dockerfile
      #Version:0.0.1
      FROM opensuse:latest
      MAINTAINER Kael Wang "zb55@foxmail.com"
      RUN ztpper install nginx
      RUN echo "Hi,I am in you container" \
      >>/srv/www/htdocs/index.html
      EXPOSE 80
      
    • 基于Dockerfile构建新镜像在Dockerfile创建好之后,我们通过docker build命令构建此新镜像
      docker build -t="kaelwang/webdocker" .
      Sending build context to Docker daemon 2.048 kB
      Step 1 : FROM opensuse:latest
       ---> 1621e06b2c3b
      Step 2 : MAINTAINER Kael Wang "zb55@foxmail.com"
       ---> Using cache
       ---> 4b37a947f6d7
      Step 3 : RUN zypper --non-interactive install nginx
       ---> Using cache
       ---> bdd4bd1574ea
      Step 4 : RUN echo "Hi,I am in you container" >/srv/www/htdocs/index.html
       ---> Running in 603c1fd9154b
       ---> 4519064e313b
      Removing intermediate container 603c1fd9154b
      Step 5 : EXPOSE 80
       ---> Running in 3d2050c3b3cf
       ---> a799facb760a
      Removing intermediate container 3d2050c3b3cf
      Successfully built a799facb760a
      
    • 指令失败时的情况依次执行Dockerfile文件中的内容,如果文件中出现错误,Docker会构建到错误处,我们可以通过docker run 命令来基于这次构建到错误处为止已经成功的最后一步创建的一个容器内进行调试,然后退出修改Dockerfile文件。
    • Docker和构建缓存由于每一步的构建过程都会将结果提交为镜像,所以Docker的构建镜像过程比较聪明,它会将之前的镜像层看作是缓存,Docker会从变化出的指令开始执行。然而,有些时候需要确保构建过程不会使用缓存,想要忽略缓存功能,可以使用
      $ docker build --no-cache -t="kaelwang/webdocker" .
      
    • 基于构建缓存的Dockerfile模板构建Docker缓存的好处就是我们可以实现简单的Dockerfile模板(比如在顶部增加包库或者更新包,从而尽可能确保缓存命中)。我们一般都会在自己的Dockerfile文件顶部使用相同的指令集模板,比如对Ubuntu
      From ubuntu:latest
      MAINTAINER Kael Wang "zb55@foxmail.com"
      ENV REFRESHED_AT 2016-07-01
      RUN apt-get -qq update                        
      

      ENV 环境变量中,REFRESHED_AT来设置该镜像模板最后的更新时间。

    • 查看新镜像
      $ docker images kaelwang/webdocker
      REPOSITORY           TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
      kaelwang/webdocker   latest              a799facb760a        6 minutes ago          213.1 MB
      $ docker history a799facb760a
      IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
      a799facb760a        6 minutes ago          /bin/sh -c #(nop) EXPOSE 80/tcp                 0 B                 
      4519064e313b        6 minutes ago          /bin/sh -c echo "Hi,I am in you container" >/   25 B                
      bdd4bd1574ea        6 minutes ago          /bin/sh -c zypper --non-interactive install n   115.4 MB            
      4b37a947f6d7        6 minutes ago          /bin/sh -c #(nop) MAINTAINER Kael Wang "zb55@   0 B                 
      1621e06b2c3b        4 days ago          /bin/sh -c #(nop) ADD file:4c338e205c079dbf5d   97.74 MB            
      5b3b6d462d10        5 weeks ago         /bin/sh -c #(nop) MAINTAINER Flavio Castelli    0 B
      
    • 从新镜像启动容器
      $ docker run -d -p 80 --name webdocker kaelwang/webdocker nginx -g "daemon off;"
      50d3ba4d4c88b83a4537c74bfa6e570e9319e20d3dff9c28986984e216724b65
      $ docker ps -l
      CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                   NAMES
      50d3ba4d4c88        kaelwang/webdocker   "nginx -g 'daemon off"   18 seconds ago      Up 17 seconds       0.0.0.0:32768->80/tcp   webdocker
      $ docker port 50d3ba4d4c88
      80/tcp -> 0.0.0.0:32768
      

      -p也可以指定IP,端口映射,如

      $ docker run -d -p 127.0.0.1:8080:80 --name webdocker kaelwang/webdocker nginx -g "daemon off;"
      

      验证一下nginx服务

      $ curl localhost:8080
      Hi,I am in you container
      
    • Dockerfile指令1.CMD。容器启动时要运行的命令,类似于run指定构建镜像时要运行的命令。CMD可以被docker run命令覆盖。Dockerfile中只能指定一条CMD命令,如果指定了多条CMD命令,也只有最后一条CMD指令会被使用。如果要想在容器运行时运 行多个进程或者多条命令,可以考虑使用类似Supervisor这样的服务管理工具。
      CMD ["/bin/bash","-l"]
      

      2.ENTRYPOINT。与CMD非常类似,只是不容易被docker run命令覆盖。实际上,docker run命令行中指定的任何参数都会被当成ENTRYPOINT指令中指定的命令。

      ENTRYPOINT ["/usr/sbin/nginx"]
      

      重新构建并启动容器

      $ docker run -t -i kaelwang/webdocker -g "daemo off;"
      

      docker run中的-g “daemon off”作为参数传递给ENTRYPOINT。 结合CMD和ENTRYPOINT完成一些巧妙的工作

      ENTRYPOINT ["/usr/sbin/nginx"]
      CMD ["-h"]
      

      这使得我们构建一个镜像,该镜像既可以运行一个默认的命令,同时该镜像也支持通过docker run命令为该镜像指定可覆盖的选项或者标志。但是如果你确实却要覆盖,你可以通过docker run 的–entrypoint标志覆盖Dockerfile中的ENTRYPOINT指令。 3.WORKDIR。指定一个工作目录。

      WORKDIR /opt/webapp/db
      RUN bundle install
      WORKDIR /opt/webapp
      ENTRYPOINT ["rackup"]
      

      4.ENV。设置环境变量。

      ENV RVM_PATH /home/rvm/
      

      5.USER.设置该镜像会以什么样的用户去运行。

      USER nginx:www
      

      6.VOLUME。指定镜像创建容器添加卷。一个卷是可以存在于一个或者多个容器内的特定的目录,这个目录可以绕过联合文件系统,并提供共享数据或 者对数据进行持久化的功能。卷功能让我们可以将数据,数据库或者其他内容添加到镜像中而不是提交创建到镜像中,并且允许我们在多个容器间共享这些内容。

      VOLUME ["/opt/project","/data","/home/wwwroot"]
      

      7.ADD。用来将构建环境下的文件和目录复制到镜像中,比如安装一个应用程序,指定文件位置和目的文件位置

      ADD software.lic /opt/application/software.lic
      ADD http://wordpress.org/latest.zip /root/wordpress.zip   //可以指定URL
      ADD laest.tar.gz /var/www/wordpress/                      //docker会自动将压缩文件解压到该目录                 
      

      8.COPY。类似于ADD,只是不会帮助你提取,解压等,只会单纯复制。 9.ONBUILD。为镜像添加触发器。当一个镜像被用做其它镜像的基础镜像时,该镜像中的触发器将会被执行。触发器会在构建过程中插入新指令,我们可以认为这些指令是跟进在FROM之后的。触发器可以是任何构建指令

      ONBUILD ADD . /app/src
      ONBUILD RUN cd /app/src && make
      
  5. 删除镜像
    $ docker rmi kaelwang/webdocker
    
  6. 运行自己的Docker Registry
    $ docker run -p 5000:5000 registry
    $ docker tag 50d3ba4d4c88 docker.example.com:5000/kaelwang/webdocker
    $ docker push docker.example.com:5000/kaelwang/webdocker
    $ docker run -t -i docker.example.com:5000/kaelwang/webdocker /bin/bash
    
分类: Docker

0 条评论

发表回复

Avatar placeholder

您的邮箱地址不会被公开。 必填项已用 * 标注