Docker 镜像管理&仓库管理

创建容器时需要指定使用哪个镜像,新容器创建后,不依赖镜像就可以运行。使用docker images 可以查找到本机已有的所有镜像。

每个镜像也有唯一的标示ImageID,和容器的Container ID一样,默认128位,可以使用前16位的缩略形式。

镜像的分层

通过docker images 可以看到每个镜像的大小都很大,但是镜像所占的磁盘空间之和远远小于所有镜像之和。原因是镜像采用了分层机制,相同部分独立成层,只需要存储一份就可以了。大大节省了镜像空间。比如wordpress和mysql都是基于ubuntu系统构建的,那么就只需要一个ubuntu的镜像分层,再次基础上再根据wordpress 和mariadb各自不同1部分构建各自的独立分层。

Docker 的镜像通过联合文件系统将各层文件系统叠加在一起,在用户看来就像一个完整的文件系统。例如某个镜像有两层,第一层有三个文件夹,第二层有两个文件夹,使用联合文件系统叠加后,用户可以看到五个文件夹,感觉不到分层的存在。

通过docker history可以查询镜像分了多少层,每一层做了什么操作。

对于分层的Docker 镜像有两个特性,一个是已有的分层只能读不能修改,另一个是上层镜像的优先级高于底层镜像。

下面举一个例子:

镜像B和镜像C都是在镜像A的基础上搭建起来的,镜像A有一个文件a.txt.内容为“HELLO WORLD”,从用户的视角来看,镜像B和镜像C都可以看到文件a.txt,且内容都是“HELLO,WORLD”,这时镜像B想要修改a.txt的内容为“hello docker”如果我们允许直接对镜像A中的文件a.txt进行修改,那么C看到的内容也会发生改变,这对C来说,是不可接受的,所以已有的分层都是不能修改的,要修改的话,只能通过在镜像B的基础上新增加一个分层B’,存储修改后的a.txt,利用上层镜像的优先级高于底层镜像原则,新增加的分层B’中的a.txt会覆盖原有镜像A的a.txt,从用户的视角,就会看到修改后的a.txt的内容为HELLO docker, 而镜像C看到的还是hello world

Dockerfile

语法

每行都以一个关键字为行首,如果一行内容过长,它使用’\’把多行连接在一起。

第一行使用关键字FROM,表示新的镜像是从Ubuntu这个基础镜像开始构建的,MAINTAINER:指定该镜像的创建者 ENV:设置环境变量。

RUN:运行shell命令 多条命令用&&连接。

COPY 将编译机本地文件拷贝到镜像文件系统中。

EXPOSE:指定监听的端口

ENTRYPOINT: 欲执行命令,创建镜像时不执行,等到使用该镜像创建容器,容器启动后才执行的命令。

项目中的镜像分层

将两个项目gitlab和Redmine两个项目的所有镜像分层放一起来看,可以发现:

  • 每个镜像加一个可写层形成容器,多个容器组合在一起,对外提供某些特殊功能的服务。
  • 基于同一个镜像只需要增加一个可写层,就可以为不同项目创建各自需要的容器。

Docker 仓库管理

仓库主要用于镜像的存储,它是Docker镜像分发,部署的关键,实际应用中,由开发者或者运维制作好应用程序镜像,然后上传到镜像仓库,Docker 守护进程再从仓库拉取镜像,然后运行相应的镜像。

镜像公有仓库

登录DockerHub

1
2
3
4
$ docker login
Username:
Password:
Login Succeeded

基本操作

  • 上传镜像
1
$ docker push ubuntu1404-baseimage:1.0
  • 搜索镜像
1
$ docker search centos
  • 下载镜像
1
$ docker pull