创建你自己的 docker 镜像


Docker镜像就是一个最基础的容器, 每次当你使用` docker run` 命令,你就是告诉 docker 你要使用哪个镜像.
像平常我们刚接触 docker 的时候都会拿 Ubuntu 来做例子, 其他哪个镜像就是已经存在弄好的. 当然你还可以从` docker host`也就是你本地的宿主上发现其他的镜像.  如果它不存在的话, 那么它就会从某一个注册的 hub里下载.

下面来看看如何创建一个镜像. 包括:

- 管理和操作本地 docker 宿主的镜像
- 创建镜像
- 上传镜像

### 获取本地镜像列表

通过` docker images` 就可以得到当前 docker host 里的所有的镜像

```
$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              14.04               1d073211c498        3 days ago          187.9 MB
busybox             latest              2c5ac3f849df        5 days ago          1.113 MB
training/webapp     latest              54bb4e8718e8        5 months ago        348.7 MB
``` 
可以看到当前 host 里已经有这么几个 image 了.

- 第一列告诉我们来自哪个仓库
- image tag
- image 的 id

一个仓库往往包含多哥版本的镜像, 例如` ubuntu` 的镜像, 你可以看到他有多个版本, 10.04, 12.04, 一直到14.04 任何一个版本都是被定义为一个 tag. 你可以通过这样的方式来识别一个版本:

```

ubuntu:14.04

```

接下来当你想要跑一个 image 的时候就这样:

```

docker run -t -i ubuntu:12.04 /bin/bash

```

想要换个版本就是简单替换版本:

```

docker run -t -i ubuntu:14.04 /bin/bash

```

如果忘记指定版本,docker 就默认给最新的 tag: `ubuntu:latest`

###获取一个新的镜像

怎么获取一个镜像, 你可以不去想到底本地有没有, docker 会负责给你下载如果没有的话, 不过你可以事先自己先下载好想要的镜像, 通过` docker pull` 命令, 例如你要下载` centos` 就直接:


```
docker pull centos
```

然后

```
docker run -t -i centos /bin/bash

```

### 查找某个镜像

docker 这里已经有很多人创建了不同的镜像了. 并且上传到了` docker hub`里. 通过这里你可以搜索到很多有趣有用的镜像.

![Kobito.YMXD7t.png](https://qiita-image-store.s3.amazonaws.com/0/56713/b1e9e8d2-af9d-9857-f7f6-e433814886b1.png "Kobito.YMXD7t.png")

当然你还可以通过命令行的形式来所搜. `docker search`. 例如当前你想要一个`ruby+sinatra` 的开发环境, 你就可以通过` docker search` 来搜索下有没有合适的镜像包含了` sinatra`

```
$ docker search sinatra
NAME                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
training/sinatra                       Sinatra training image                          0                    [OK]
marceldegraaf/sinatra                  Sinatra test app                                0
mattwarren/docker-sinatra-demo                                                         0                    [OK]
luisbebop/docker-sinatra-hello-world                                                   0                    [OK]
bmorearty/handson-sinatra              handson-ruby + Sinatra for Hands on with D...   0
subwiz/sinatra                                                                         0
bmorearty/sinatra                                                                      0
. . .
  
```


通过这个结果可以看到镜像名称, 已经描述,几颗星等. 到这里会发现有大致2种镜像,一种就是类似` ubuntu` 的这个, 他们直接去大名, 很好辨识. 往这样 的就是来自于 docker 官方,验证过的.另外一种就是类似` training/sinatra` 这样的往往就是来自民间. 我们选择这个` traning/sinatra`

####下载镜像

```
docker pull training/sinatra
```

然后

```
docker run -t -i training/sinatra  /bin/bash

```

###创建自己的镜像

虽然我们可以用这个` traning/sinatra` 镜像,但是总有不尽人意的, 那我们就自己 build 一个镜像. 有2种方式我们可以更新或者创建镜像

- 可以更新现有的已经存在的镜像
- 通过` Dockfile` 来创建一个全新的镜像

####创建提交一个镜像

首选我们先让自己你要更新的镜像跑起来,

```

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

```

然后我们就可以修改这个镜像了, 如:

```
root@0b2616b0e5a8:/# apt-get install -y ruby2.0-dev
root@0b2616b0e5a8:/# gem2.0 install json
```

`exit` 退出这个镜像, 然后我们通过`docker commit` 来提交我们的修改.

```
docker commit -m 'addjson gem' -a "xiang" \
90909090909 ouruser/sinatra:v2

234234324234234234343242654ygfddggdgdsgsg

```

注意这个命令,

- -m 参数是指定提交信息
- -a 指定一个作者


然后是一个镜像的 ID, 还有这个新的镜像的作者,` ouruser` 保留原本镜像的名称` sinatra`, 给一个新的 tag名称

```
ouruser/siantra:v2
```

现在我们通过` docker images` 命令就可以获取到一个新的镜像


```
$ docker images

REPOSITORY          TAG     IMAGE ID       CREATED       SIZE
training/sinatra    latest  5bc342fa0b91   10 hours ago  446.7 MB
ouruser/sinatra     v2      3c59e02ddd1a   10 hours ago  446.7 MB
ouruser/sinatra     latest  5db5f8471261   10 hours ago  446.7 MB
To use our new image to create a container you can then:

```


进入:

```

$ docker run -t -i ouruser/sinatra:v2 /bin/bash

root@78e82f680994:/#
```


### 如果 Dockerfile 来创建镜像

通过` docker commit` 很容易基于现有的镜像创建新的扩展. 我们还可以通过` docker build` 来从零开始创建一个镜像. 我们就是通过` Dockerfike` 来告诉 docker 如何构建这个镜像.

```
mkdir sinatra
cd sinatra
touch Dockerfile
```


然后编辑这个` Dockerfile`


```
# This is a comment
FROM ubuntu:14.04
MAINTAINER Kate Smith <ksmith@example.com>
RUN apt-get update && apt-get install -y ruby ruby-dev
RUN gem install sinatra

```

让我们来看看这个内容到底什么意思:

- `From`告诉 docker 我们的镜像是基于那个镜像的
- `MAINTAINER` 告诉谁维护这个镜像
- `RUN` 告诉镜像要跑什么命令, 这里我们就是要先更新 apt, 然后安装 ruby, 还有 sinatra


接下来我们通过` docker build` 来初始化这个镜像:


``` 
docker build -t ouruser/sinatra:v2

...
...

Installing RDoc documentation for tilt-1.4.1...
Installing RDoc documentation for rack-protection-1.5.3...
Installing RDoc documentation for sinatra-1.4.5...
 ---> 97feabe5d2ed
Removing intermediate container 6b81cb6313e5
Successfully built 97feabe5d2ed


```


[如何书写 `Dockerfile`] (https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/)

#### 设置 tag


拿到镜像的 id 然后


```
 docker tag 5db5f8471261 ouruser/sinatra:devel
```

查看所有:


```

docker images ouruser/sinatra

REPOSITORY          TAG     IMAGE ID      CREATED        SIZE
ouruser/sinatra     latest  5db5f8471261  11 hours ago   446.7 MB
ouruser/sinatra     devel   5db5f8471261  11 hours ago   446.7 MB
ouruser/sinatra     v2      5db5f8471261  11 hours ago   446.7 MB


```


我们拿到镜像的签名, 

```
$ docker images --digests | head

REPOSITORY        TAG      DIGEST                                                                     IMAGE ID      CREATED       SIZE
ouruser/sinatra   latest   sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf    5db5f8471261  11 hours ago  446.7 MB


```

然后` push` 镜像

```
docker push ouruser/sinatra

The push refers to a repository [ouruser/sinatra] (len: 1)
Sending image list
Pushing repository ouruser/sinatra (3 tags)
. . .

```


移除镜像

```

 docker rmi training/sinatra

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


```