• 欢迎访问金笔头博客,这是一个菜鸟(伪)程序员的自留地,欢迎访问我的github:点击进入

Docker笔记(3)-关于镜像的一些操作

Docker eason 3327次浏览 0个评论 扫描二维码

前言

在之前的介绍中,我们知道镜像是 Docker 的三大组件之一。Docker 运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker 会从镜像仓库下载(默认是 Docker Hub 公共注册服务器中的仓库)。关于镜像,本文主要讲解以下内容:

Docker笔记(3)-关于镜像的一些操作

搜索镜像

用户无需登录即可通过docker search命令来查找官方仓库中的镜像,例如以 ubuntu 为关键词进行搜索:

$ sudo docker search ubuntu
NAME                                         DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                                       Ubuntu is a Debian-based Linux operating s...   5674      [OK]       
rastasheep/ubuntu-sshd                       Dockerized SSH service, built on top of of...   75                   [OK]
ubuntu-upstart                               Upstart is an event-based replacement for ...   70        [OK]       
consol/ubuntu-xfce-vnc                       Ubuntu container with "headless" VNC sessi...   45                   [OK]
ubuntu-debootstrap                           debootstrap --variant=minbase --components...   28        [OK]       
torusware/speedus-ubuntu                     Always updated official Ubuntu docker imag...   27                   [OK]
nuagebec/ubuntu                              Simple always updated Ubuntu docker images...   16                   [OK]
nickistre/ubuntu-lamp                        LAMP server on Ubuntu                           16                   [OK]
nimmis/ubuntu                                This is a docker images different LTS vers...   6                    [OK]
darksheer/ubuntu                             Base Ubuntu Image -- Updated hourly             2                    [OK]
jordi/ubuntu                                 Ubuntu Base Image                               1                    [OK]
admiringworm/ubuntu                          Base ubuntu images based on the official u...   1                    [OK]
labengine/ubuntu                             Images base ubuntu                              0                    [OK]
datenbetrieb/ubuntu                          custom flavor of the official ubuntu base ...   0                    [OK]
webhippie/ubuntu                             Docker images for ubuntu                        0                    [OK]
vcatechnology/ubuntu                         A Ubuntu image that is updated daily            0                    [OK]
lynxtp/ubuntu                                https://github.com/lynxtp/docker-ubuntu         0                    [OK]
teamrock/ubuntu                              TeamRock's Ubuntu image configured with AW...   0                    [OK]
forumi0721ubuntux64/ubuntu-x64-dev           ubuntu-x64-dev                                  0                    [OK]
konstruktoid/ubuntu                          Ubuntu base image                               0                    [OK]
forumi0721ubuntuaarch64/ubuntu-aarch64-dev   ubuntu-aarch64-dev                              0                    [OK]
forumi0721ubuntuarmhf/ubuntu-armhf-dev       ubuntu-armhf-dev                                0                    [OK]
esycat/ubuntu                                Ubuntu LTS                                      0                    [OK]
uvatbc/ubuntu                                Ubuntu images with unprivileged user            0                    [OK]
forumi0721ubuntux64/ubuntu-x64-dev-armbian   ubuntu-x64-dev-armbian                          0                    [OK]

可以看到返回了很多包含关键字的镜像,其中包括镜像名字、描述、星级(表示该镜像的受欢迎程度)、是否官方创建、是否自动创建。 官方的镜像说明是官方项目组创建和维护的,automated 资源允许用户验证镜像的来源和内容。 根据是否是官方提供,可将镜像资源分为两类。 一种是类似 ubuntu这样的基础镜像,被称为基础或根镜像。这些基础镜像是由 Docker 公司创建、验证、支持、提供。这样的镜像往往使用单个单词作为名字。 还有一种类型,比如 rastasheep/ubuntu-sshd 镜像,它是由 Docker 的用户创建并维护的,往往带有用户名称前缀。可以通过前缀 user_name/ 来指定使用某个用户提供的镜像,比如 rastasheep 用户。另外,在查找的时候通过 -s N 参数可以指定仅显示评价为 N 星以上的镜像。

下载镜像

使用docker pull命令从仓库下载(拉取)所需镜像,下面的例子将从 Docker Hub 仓库下载一个 Ubuntu 14.04 操作系统的镜像。

$ sudo docker pull ubuntu:14.04
[sudo] eason 的密码: 
14.04: Pulling from library/ubuntu
16da43b30d89: Pull complete 
1840843dafed: Pull complete 
91246eb75b7d: Pull complete 
7faa681b41d7: Pull complete 
97b84c64d426: Pull complete 
Digest: sha256:881befbe6f54c1e85029fe3a11554342bf765a0849600ecb8fa2f922798b4925
Status: Downloaded newer image for ubuntu:14.04

下载过程中,会输出获取镜像的每一层信息。 该命令实际上相当于 sudo docker pull registry.hub.docker.com/ubuntu:12.04 命令,即从注册服务器 registry.hub.docker.com 中的 ubuntu 仓库来下载标记为 12.04 的镜像。 有时候官方仓库注册服务器下载较慢,可以从其他仓库下载。 从其它仓库下载时需要指定完整的仓库注册服务器地址。

列出本地已有的镜像

使用 docker images 命令显示本地已有的镜像。

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              14.04               3f755ca42730        3 weeks ago         188 MB
hello-world         latest              c54a2cc56cbb        6 months ago        1.848 kB

在列出信息中,可以看到几个字段信息

  • REPOSITORY,来自于哪个仓库,比如 ubuntu
  • TAG,标记来自同一个仓库的不同镜像。例如 ubuntu 仓库中有多个镜像,通过 TAG 信息来区分发行版本,例如 10.04、12.04、12.10、13.04、14.04 等。
  • IMAGE ID,它的 ID 号(唯一)
  • CREATED,创建时间
  • SIZE,镜像大小

    创建镜像

    Docker仓库虽然已经有非常多的镜像可供下载,但是并不是每个镜像都能满足我们的需求,所以根据自己需要创建满足我们要求的镜像是非常有必要的。创建自己的镜像有两种方法:

  • 在已有镜像上进行更改来创建一个新镜像
  • 使用Dockerfile指令来创建一个镜像

下面分别记录这两种方法创建镜像的过程。

在已有镜像上进行更改来创建一个新镜像

前面我们已经从Docker Hub上下载了一个Ubuntu 14.04的镜像,这里我就直接在这个镜像上修改。当然在这之前你得先得启动这个镜像

$ sudo docker run -t -i ubuntu:14.04 /bin/bash
root@e3a697ac22fe:/# pwd
/
root@e3a697ac22fe:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr

参数解释:

  • -t 表示在新容器内指定一个伪终端或终端
  • -i 表示允许我们对容器内的STDIN进行交互
  • /bin/bash 这将在容器内启动bash shell

启动容器之后我们能看到有一个命令提示符root@e3a697ac22fe:/#,其中的e3a697ac22fe就是我们的容器ID,记住这个ID,后面我们会用到。

现在开始对其进行修改,比如我创建一个文件test.py

root@e3a697ac22fe:/# touch test.py
root@e3a697ac22fe:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  test.py  usr
boot  etc  lib   media  opt  root  sbin  sys  tmp      var
root@e3a697ac22fe:/# exit
exit
eason@eason:~$

上面使用touch命令创建了一个test.py文件,创建完成以后执行exit退出容器。刚刚虽然只是新建了一个文件,但其实我们的容器已经被改变了,我们可以使用docker commit命令来提交更新后的副本。

$ sudo docker commit -m "test modify a docker image" -a "eason" e3a697ac22fe eason/ubuntu14.04:v1.0
[sudo] eason 的密码: 
sha256:ecd7ef582302e0b1906ce258fa96381589ac3587fe8a42f205cd8a3bde7682e3

参数解释:

  • -m 指定提交的说明信息,跟我们使用的版本控制工具一样
  • -a 指定更新的用户信息
  • e3a697ac22fe 标识用来创建镜像的容器的ID
  • eason/ubuntu14.04 指定目标镜像的仓库名
  • v1.0 指定目标镜像的tag 信息

创建成功后会返回这个新创建镜像的 ID 信息。

使用docker images查看新创建的镜像

$ sudo docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
eason/ubuntu14.04   v1.0                ecd7ef582302        6 seconds ago       188 MB
ubuntu              14.04               3f755ca42730        3 weeks ago         188 MB
hello-world         latest              c54a2cc56cbb        6 months ago        1.848 kB

启动我们新建的镜像,我们能看到之前新建的那个文件

$ sudo docker run -t -i eason/ubuntu14.04:v1.0 /bin/bash
root@a7d23b1fe1d0:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  test.py  usr
boot  etc  lib   media  opt  root  sbin  sys  tmp      var
root@a7d23b1fe1d0:/#

至此,基于已有镜像创建新镜像的方法我们已经掌握。

使用Dockerfile指令来创建一个镜像

Dockerfile 是一个包含创建镜像所有命令的文本文件,通过docker build命令可以根据 Dockerfile 文件中的命令来构建镜像。其基本指令如下:

  • # 注释
  • FROM 告诉 Docker 使用哪个镜像作为基础
  • MAINTAINER 指定创建镜像的用户
  • ENV 指定一个环境变量,会被后续RUN指令使用,并在容器运行时保留
  • RUN 在当前镜像上执行指定指令,并提交为新的镜像

介绍完了基础指令,现在开始动手实践一下: 创建docker目录和dockerfile

$ mkdir docker
$ ls
docker PycharmProjects virtual 模板 图片 下载 桌面
examples.desktop softwares 公共的 视频 文档 音乐
$ cd docker/
$ touch dockerfile
$ ll
总用量 8
drwxrwxr-x 2 eason eason 4096 1月 10 20:39 ./
drwxr-xr-x 36 eason eason 4096 1月 10 20:38 ../
-rw-rw-r-- 1 eason eason 0 1月 10 20:39 dockerfile
$ vim dockerfile

编辑dockerfile文件

#这里我已之前下载好的Ubuntu14.04为基础创建新镜像
#为新镜像安装python开发环境,并安装python包管理工具pip
FROM ubuntu:14.04
MAINTAINER jinbitou <jinbitou@126.com>
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y python python-pip python-dev

编辑好dockerfile文件之后,使用docker build命令来开始构建镜像,具体用法如下:

$ docker build --help

Usage:    docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
      --build-arg value         Set build-time variables (default [])
      --cgroup-parent string    Optional parent cgroup for the container
      --cpu-period int          Limit the CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int           Limit the CPU CFS (Completely Fair Scheduler) quota
  -c, --cpu-shares int          CPU shares (relative weight)
      --cpuset-cpus string      CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string      MEMs in which to allow execution (0-3, 0,1)
      --disable-content-trust   Skip image verification (default true)
  -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
      --force-rm                Always remove intermediate containers
      --help                    Print usage
      --isolation string        Container isolation technology
      --label value             Set metadata for an image (default [])
  -m, --memory string           Memory limit
      --memory-swap string      Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --no-cache                Do not use cache when building the image
      --pull                    Always attempt to pull a newer version of the image
  -q, --quiet                   Suppress the build output and print image ID on success
      --rm                      Remove intermediate containers after a successful build (default true)
      --shm-size string         Size of /dev/shm, default value is 64MB
  -t, --tag value               Name and optionally a tag in the 'name:tag' format (default [])
      --ulimit value            Ulimit options (default [])

知道用法之后,我们开始执行

$ sudo docker build -t="eason/ubuntu14.04:v2.0" .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu:14.04
 ---> 3f755ca42730
Step 2 : MAINTAINER jinbitou <jinbitou@126.com>
 ---> Using cache
 ---> 78b1c1605692
Step 3 : RUN apt-get update && apt-get install -y curl
 ---> Running in 4a9ebf6e60a9
Ign http://archive.ubuntu.com trusty InRelease
Get:1 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB]
Get:2 http://archive.ubuntu.com trusty-security InRelease [65.9 kB]
Get:3 http://archive.ubuntu.com trusty Release.gpg [933 B]
Get:4 http://archive.ubuntu.com trusty-updates/main Sources [480 kB]
Get:5 http://archive.ubuntu.com trusty-updates/restricted Sources [5921 B]
Get:6 http://archive.ubuntu.com trusty-updates/universe Sources [216 kB]
Get:7 http://archive.ubuntu.com trusty-updates/main amd64 Packages [1166 kB]
Get:8 http://archive.ubuntu.com trusty-updates/restricted amd64 Packages [20.4 kB]
Get:9 http://archive.ubuntu.com trusty-updates/universe amd64 Packages [507 kB]
......
......
Setting up libpython-stdlib:amd64 (2.7.5-5ubuntu3) ...
Setting up manpages-dev (3.54-1ubuntu1) ...
Setting up python2.7 (2.7.6-8ubuntu0.3) ...
Setting up python-minimal (2.7.5-5ubuntu3) ...
Setting up python (2.7.5-5ubuntu3) ...
Setting up python-chardet (2.0.1-2build2) ...
Setting up python3-pkg-resources (3.3-1ubuntu2) ...
Setting up python-chardet-whl (2.2.1-2~ubuntu1) ...
Setting up python-colorama (0.2.5-0.1ubuntu2) ...
Setting up python-colorama-whl (0.2.5-0.1ubuntu2) ...
Setting up python2.7-dev (2.7.6-8ubuntu0.3) ...
Setting up python-dev (2.7.5-5ubuntu3) ...
Setting up python-distlib (0.1.8-1ubuntu1) ...
Setting up python-distlib-whl (0.1.8-1ubuntu1) ...
Setting up python-six (1.5.2-1ubuntu1) ...
Setting up python-html5lib (0.999-3~ubuntu1) ...
Setting up python-html5lib-whl (0.999-3~ubuntu1) ...
Setting up python-six-whl (1.5.2-1ubuntu1) ...
Setting up python-urllib3-whl (1.7.1-1ubuntu4) ...
Setting up python-requests-whl (2.2.1-1ubuntu0.3) ...
Setting up python-setuptools-whl (3.3-1ubuntu2) ...
Setting up python-pip-whl (1.5.4-1ubuntu4) ...
Setting up python-pkg-resources (3.3-1ubuntu2) ...
Setting up python-urllib3 (1.7.1-1ubuntu4) ...
Setting up python-requests (2.2.1-1ubuntu0.3) ...
Setting up python-setuptools (3.3-1ubuntu2) ...
Setting up python-pip (1.5.4-1ubuntu4) ...
Setting up python-wheel (0.24.0-1~ubuntu1) ...
Processing triggers for libc-bin (2.19-0ubuntu6.9) ...
Processing triggers for ca-certificates (20160104ubuntu0.14.04.1) ...
Updating certificates in /etc/ssl/certs... 173 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
 ---> c3541cf26a74
Removing intermediate container 70507abe51d9
Successfully built c3541cf26a74

其中 -t标记来添加TAG,指定新的镜像的用户信息。 “.” 是 Dockerfile 所在的路径(当前目录),也可以替换为一个具体的 Dockerfile 的路径。 可以看到 build 进程在执行操作。它要做的第一件事情就是上传这个 Dockerfile 内容,因为所有的操作都要依据 Dockerfile 来进行。 然后,Dockfile 中的指令被一条一条的执行。每一步都创建了一个新的容器,在容器中执行指令并提交修改。当所有的指令都执行完毕之后,返回了最终的镜像 id,这里是c3541cf26a74。所有的中间步骤所产生的容器都被删除和清理了。

新镜像创建完毕之后我们查看本地所有镜像

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
eason/ubuntu14.04   v2.0                c3541cf26a74        10 hours ago        396.8 MB
eason/ubuntu14.04   v1.0                ecd7ef582302        2 days ago          188 MB
ubuntu              14.04               3f755ca42730        3 weeks ago         188 MB
hello-world         latest              c54a2cc56cbb        6 months ago        1.848 kB

可以看到TAG为v2.0的为我们新建的镜像,测试我们刚新建的镜像是否包含pyhton和pip

$ sudo docker run -t -i eason/ubuntu14.04:v2.0 /bin/bash
root@f582553fc83e:/# python -V
Python 2.7.6
root@f582553fc83e:/# pip list
argparse (1.2.1)
chardet (2.0.1)
colorama (0.2.5)
html5lib (0.999)
pip (1.5.4)
requests (2.2.1)
setuptools (3.3)
six (1.5.2)
urllib3 (1.7.1)
wheel (0.24.0)
wsgiref (0.1.2)
root@f582553fc83e:/#

根据输出信息可知,新镜像已经安装好了python环境,并且也已经安装了pip工具。

上传镜像至远程仓库(Docker Hub)

用户可以通过docker push命令,把自己创建的镜像上传到远程仓库中来共享。例如,用户在 Docker Hub 上完成注册后,可以创建远程仓库,然后将自己的镜像推送到远程仓库中。在Docker Hub上注册和新建仓库的过程这里就不讲了,不懂的自行google。官网地址:https://www.docker.com/ 在写这篇文章之前我已经注册好docker账户并新建了一个仓库名为leeyis/ubuntu,使用tag指令为刚新建的镜像取个别名,使用push指令推送镜像至远程仓库,在推送之前要使用login指令登录,不过笔头君之前使用push指令推送了好多次都没成功,最后发现只有将别名改为远程仓库的名字才能推送成功,至于原因嘛,我也不知道,知道的朋友麻烦留言告知,先行谢过了。

$ sudo docker tag c3541cf26a74 leeyis/ubuntu
$ sudo docker login -u username -p password
$ sudo docker push leeyis/ubuntu
The push refers to a repository [docker.io/leeyis/ubuntu]
cb0e181778ea: Pushed 
4fcb79d431cc: Pushed 
4375cecd293e: Pushed 
738d3f35b582: Pushed 
53edc9780c07: Pushed 
bc224b1b676d: Pushed 
latest: digest: sha256:16f9762906f2fd2ecf0964870e28b02ff3d2caa67f0852329d727171c2d13176 size: 1572

最后附上上传成功后的截图 Docker笔记(3)-关于镜像的一些操作

删除本地镜像

先查看本地镜像

$ sudo docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
leeyis/ubuntu        latest              c3541cf26a74        21 hours ago        396.8 MB
ubuntu_python_v1.0   latest              c3541cf26a74        21 hours ago        396.8 MB
eason/ubuntu14.04    v2.0                c3541cf26a74        21 hours ago        396.8 MB
eason/ubuntu14.04    v1.0                ecd7ef582302        2 days ago          188 MB
ubuntu               14.04               3f755ca42730        3 weeks ago         188 MB
hello-world          latest              c54a2cc56cbb        6 months ago        1.848 kB

假如我要删除ID为ecd7ef582302的镜像,docker中删除镜像的命令是docker rmi,但有时候执行此命令并不能删除images,例如:

$ sudo docker rmi ecd7ef582302
Error response from daemon: conflict: unable to delete ecd7ef582302 (must be forced) - image is being used by stopped container 89b96cf88213

查看docker的帮助发现有两个与删除有关的命令rm和rmi

rm Remove one or more containers rmi Remove one or more images

这里有两个不同的单词,images和container。其中images很好理解,跟平常使用的虚拟机的镜像一个意思,相当于一个模版,而container则是images运行时的的状态。docker对于运行过的image都保留一个状态(container),可以使用命令docker ps来查看正在运行的container,对于已经退出的container,则可以使用docker ps -a来查看。回到之前的问题,由于image被某个container引用(拿来运行),如果不将这个引用的container销毁(删除),那image肯定是不能被删除。 知道原因之后,我们按照上面给出的错误提示,先停掉ID为89b96cf88213的container,接着删除该container,最后删除ID为ecd7ef582302的image试试:

$ sudo docker stop 89b96cf88213#停止容器
89b96cf88213
$ sudo docker rm 89b96cf88213#删除容器
89b96cf88213
$ sudo docker rmi ecd7ef582302#删除镜像
Untagged: eason/ubuntu14.04:v1.0
Deleted: sha256:ecd7ef582302e0b1906ce258fa96381589ac3587fe8a42f205cd8a3bde7682e3
Deleted: sha256:adddda1151a8e64207ad07cbdeb550a53f527b2318ff4e207333bc030ce719b2
$ sudo docker images#查看本地镜像
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
eason/ubuntu14.04    v2.0                c3541cf26a74        22 hours ago        396.8 MB
leeyis/ubuntu        latest              c3541cf26a74        22 hours ago        396.8 MB
ubuntu_python_v1.0   latest              c3541cf26a74        22 hours ago        396.8 MB
ubuntu               14.04               3f755ca42730        3 weeks ago         188 MB
hello-world          latest              c54a2cc56cbb        6 months ago        1.848 kB

发现ID为ecd7ef582302的镜像已经被成功删除,Done!

导出和载入镜像

导出镜像

如果要导出镜像到本地文件,可以使用docker save命令。 先查看本地镜像文件

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              14.04               7c09e61e9035        13 days ago         188 MB
hello-world         latest              48b5124b2768        8 weeks ago         1.84 kB

导出镜像文件到路径/home/eason/下保存为ubuntu_14.04.tar

$ sudo docker save -o /home/eason/ubuntu_14.04.tar ubuntu:14.04

载入镜像

可以使用docker load从导出的本地文件中再导入到本地镜像库,例如

$ sudo docker load --input /home/eason/ubuntu_14.04.tar

实现原理

Docker笔记(3)-关于镜像的一些操作 从上图我们看到了多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker内部的实现细节,并且能够在主机(运行Docker的机器)的文件系统上访问到。统一文件系统(union file system)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。


金笔头博客, 版权所有丨如未注明 , 均为原创, 转载请注明Docker笔记(3)-关于镜像的一些操作
喜欢 (1)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址