Docker 镜像管理
认识Docker镜像
创建镜像时需要制定使用哪个镜像。它会先从本地查找有没有这个镜像,如果不存在,就去官方Docker Hub仓库查找并下载到本机然后基于该镜像创建容器。
每个镜像有一个唯一的ID,也可以使用镜像的名字和版本号两部分组合唯一表示。如果省略版本号,默认使用最新版本(latest)
docker images #查到本机已有的所有镜像
镜像分层
镜像所占的磁盘空间远远小于所有镜像之和,原因是Docker镜像采用分层机制,相同部分独立成层,只需要存储一份就可以了大大节省了镜像空间。Docker
的镜像通过联合文件系统,将各层叠加在一起,在用户看来就像一个完整的文件系统,感觉不到分层的存在。
docker history #docker history <image_name> #查询镜像分了多少层,每一层具体做了什么操作。
分层的镜像有两个特性:一是已有的分层只能读不能修改,另外一个是上层镜像的优先级高于底层镜像。
已有的分层不能修改,如果要修改,只能通过在镜像的基础上新增一个分层,存储修改后的文件,利用“上层镜像的优先级高于底层镜像”的原则,新增分层的文件会覆盖原有镜像。
从用户视角,就会看到修改后的文件内容,而原有的镜像内容没有变。
容器时在镜像的基础上创建的,从文件系统的角度来讲,它是在分层镜像的基础上增加一个新的空白分层,这个新分层是可读写的。新创建的容器启动后是可写的。所有的写
操作都会存储在最上面的可读写层。
docker commit #提交生成新镜像
镜像A修改文件a.txt,生成形象AA。步骤如下:
首先,基于镜像A创建一个新容器C.
其次,在容器C中修改文件a.txt的内容。
最后,通过docker commit 命令提交生成新的镜像AA。 但这种方式会让镜像的层越来越多,另外一种情况一旦基础镜像需要修改,基于他的上层应用镜像很多,如果每一个
上层镜像都通过这种容器方式生成新镜像,那么维护的工作量太大。
Dockerfile
使用GUN的make工具能够比较方便构建一个工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。Makefile文件中描述了整个工程所有文件的编
译顺序、编译规则。Makefile有自己的书写格式、关键字、函数。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建哪些库文件、如何最后产生我们想要的可执
行文件尽管看起来可能很复杂,但是为工程编写makefile的好处是一旦提供一个正确的Makefile,就能够使用一行命令来完成“自动化编译”。编译整个工程所要做的唯一的一件事
就是在shell提示符下输入make命令。整个工程完全自动编译,极大提高了效率。
Dokcer 提供了和Makefile完全一样的机制来管理镜像,这就是Dokcerfile。它是Docker镜像的描述文件,通过Dockerfile做出来的,包含操作系统基础文件和软件运行环境,
它使用分层的存储方式。
# base image,表示从centos这个基础镜像开始构建,centos是他的底层镜像
FROM centos
# MAINTAINER,指定该进行的创建者
MAINTAINER json_hc@163.com
# put nginx-1.12.2.tar.gz into /usr/local/src and unpack nginx
ADD nginx-1.12.2.tar.gz /usr/local/src
# running required command,运行shell命令,如果有多条命令可以用“&&”链接
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel
RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
RUN useradd -M -s /sbin/nologin nginx
# change dir to /usr/local/src/nginx-1.12.2
WORKDIR /usr/local/src/nginx-1.12.2
# execute command to compile nginx
RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module
--with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module
--with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module
--with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install
#设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH
#指定监听的端口
EXPOSE 80
#这个关键字和以上所有的关键字是有区别的,上面的关键字都是在构建镜像时执行,但这个关键字是预执行命令,在创建镜像时不执行,要等到使用该镜像时,容器启动后才执行
ENTRYPOINT ["nginx"]
CMD ["-g","daemon off;"]
从例子我们看到Dockerfile的语法规则:每行都以一个关键字为首行,如果一行内容过长,它使用“\”把多行连接到一起。
docker build -t image_name #编译Dokcerfile,通过“-t”选项给镜像起一个名字。
有了新镜像,就可以通过docker run命令创建和使用新容器了。
项目中的镜像分层
>>多个项目会共享基础镜像。
>>每个镜像加一个可写层形成容器,多个容器组合在一起,对外提供某些特殊功能的服务。
>>基于同一个镜像增加一个可写层,就可以为不同项目创建各自需要的容器。
对我们的启发是:当我们制作自己的应用镜像时,也尽量考虑使用相同的底层镜像,这样可以极大地降低后续的维护成本。