UP | HOME

镜像

Table of Contents

获取

Docker 运行容器前需要本地存在对应的镜像,如果镜像不存在本地,需要从镜像仓库下载

使用 docker pull 命令来从仓库获取所需要的镜像(默认是 Docker Hub 公共注册服务器中的仓库)

$ sudo docker pull ubuntu:12.04

指定镜像仓库下载

$ sudo docker pull dl.dockerpool.com:5000/ubuntu:12.04

运行

使用 docker run命令从一个镜像文件启动容器

$ sudo docker run -t -i ubuntu:latest /bin/bash

列出

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

$ sudo docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              latest              08881219da4a        4 days ago          129 MB

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

  • 来自于哪个仓库,比如 ubuntu
  • 镜像的标记,比如latest,标记来自同一个仓库的不同镜像,如果不指定默认是latest
  • 它的 ID 号(唯一),标识了镜像
  • 创建时间
  • 镜像大小

创建

创建镜像有很多方法,用户可以从 Docker Hub 获取已有镜像并更新,也可以利用本地文件系统创建一个

修改已有镜像

启动下载的镜像

$ sudo docker run -t -i training/sinatra /bin/bash

root@77ab4a6c9919:/#

在容器中添加 json 和 gem 两个应用

root@77ab4a6c9919:/#  gem install json

提交修改

$ sudo docker commit -m "Added json gem" -a "Docker Newbee" aeef5cb06dfeds ouruser/sinatra:v2

976e334f05f71d7093df9fb0d337786c832c125e8d947d4cdb1b6aeef5cb06da

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

$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
ouruser/sinatra     latest              976e334f05f7        About a minute ago   447 MB
ubuntu              latest              08881219da4a        4 days ago           129 MB
training/sinatra    latest              f0f4ab557f95        2.534651 years ago   447 MB

使用新的镜像来启动容器

$ sudo docker run -t -i ouruser/sinatra /bin/bash

root@a666dd918d6e:/#

使用 docker commit 来扩展一个镜像比较简单,但是不方便在一个团队中分享

利用 Dockerfile 来创建镜像

新建一个目录和一个 Dockerfile

$ mkdir klose
$ cd klose
$ touch Dockerfile

编写Dockerfile,其中的每一条指令都是创建镜像的一层

  • 使用#来注释
  • FROM 指令告诉 Docker 使用哪个镜像作为基础
  • 接着是维护者的信息
  • RUN开头的指令会在创建中运行,比如安装一个软件包
# This is a comment
FROM ubuntu:latest
MAINTAINER Docker Klose <klose911@gmail.com>
RUN apt-get -qq update
RUN apt-get -qqy install ruby ruby-dev
RUN gem install sinatra

使用 docker build 来生成镜像

可以看到 build 进程要做的第一件事情就是上传这个 Dockerfile 内容,因为所有的操作都要依据 Dockerfile 来进行。 然后,Dockfile 中的指令被一条一条的执行。每一步都创建了一个新的容器,在容器中执行指令并提交修改(就跟之前介绍过的 docker commit 一样)。当所有的指令都执行完毕之后,返回了最终的镜像 id。所有的中间步骤所产生的容器都被删除和清理了

  $ sudo docker build -t="ouruser/klose:v2" .

Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu
 ---> 08881219da4a
Step 1 : MAINTAINER Docker Newbee <klose911@gmail.com>
 ---> Running in 800e3d022e21
 ---> d402138ffe49
Removing intermediate container 800e3d022e21
Step 2 : RUN apt-get -qq update
 ---> Running in 56f49baef39c
  • ADD 命令复制本地文件到镜像
  • EXPOSE 命令来向外部开放端口
  • CMD 命令来描述容器启动后运行的程序等
    # put my local web site in myApp folder to /var/www
    ADD myApp /var/www
    # expose httpd port
    EXPOSE 80
    # the command to run
    CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]
    

从本地文件系统导入

本地文件系统导入一个镜像,可以使用 openvz(容器虚拟化的先锋技术)的模板来创建

先下载了一个 ubuntu-14.04 的镜像,然后用命令导入

$ sudo cat ubuntu-14.04-x86_64-minimal.tar.gz  |docker import - ubuntu:14.04

上传镜像

通过 docker push 命令,把自己创建的镜像上传到仓库中来共享

$ sudo docker push ouruser/klose

修改tag

用 docker tag 命令来修改镜像的标签

$ sudo docker images 

REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
ouruser/sinatra     latest              976e334f05f7        About an hour ago    447 MB
ubuntu              latest              08881219da4a        4 days ago           129 MB
training/sinatra    latest              f0f4ab557f95        2.534800 years ago   447 MB

$ sudo docker tag 976e334f05f7 ouruser/sinatra:devel 

$ sudo docker images 

REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
ouruser/sinatra     latest              976e334f05f7        About an hour ago    447 MB
ouruser/sinatra     devel               976e334f05f7        About an hour ago    447 MB
ubuntu              latest              08881219da4a        4 days ago           129 MB
training/sinatra    latest              f0f4ab557f95        2.534802 years ago   447 MB

导出和载入

导出镜像文件

使用 docker save 命令把镜像导出到本地文件

$ sudo docker save -o ubuntu_latest.tar ubuntu:latest

载入导出的文件

使用 docker load 从导出的本地文件中再导入到本地镜像库

$ sudo docker load --input ubuntu_latest.tar

移除

使用 docker rmi 命令移除镜像,注意: docker rm是移除容器

$ sudo docker rmi training/sinatra

Error response from daemon: Conflict, cannot delete f0f4ab557f95 because the container a666dd918d6e is using it, use -f to force
FATA[0000] Error: failed to remove one or more images

$ sudo docker rm a666dd918d6e

a666dd918d6e

$ sudo docker rmi training/sinatra

Untagged: training/sinatra:latest
Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d
Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f
Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0

实现原理

每个镜像都由很多层次构成,Docker 使用 Union FS 将这些不同的层结合到一个镜像中去

通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk 挂到同一个目录下, 另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起,Live CD 正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。 Docker 在 AUFS 上构建的容器也是利用了类似的原理

Next:容器

Previous:安装

Home:目录