如何制作高质量的docker镜像
2015-08-06 14:09
645 查看
今天我们讨论下,Docker 的用户们关心的问题,如何制作高质量的镜像。首先我们对高质量镜像标准进行定义。
镜像兼容性好
镜像执行效率高
镜像体积小
镜像可以被继承
对一个正在运行的contianer,使用docker commit 创建镜像。
基于dockkerfile,使用
Docker commit提供了一种灵活的制作镜像的方式,但是它的主要作用时对当前docker 容器内容备份。如果你准备做基础镜像,我们是不推荐这种方式。
Docker commit 会记录docker run时提供的部分参数。
没有Dockerfile作为描述文件,不易于镜像管理维护。
不容易控制docker镜像的层次
提供完整的
CMD指令的官方解释是:The main purpose of a CMD is to provide defaults for an executing container
ENTRYPOINT指令的官方解释是: An ENTRYPOINT allows you to configure a container that will run as an executable.
CMD,ENTRYPOINT 及Docker run 时指定的命令,参数关系如下:[/code]
很多镜像使用wrapper scripts 启动应用程序。 如果你有这样的脚本,应该使用exec来执行它。 否则,docker 发出的信号不会被你的程序截获。举个例子:
我使用start.sh 来启动自己的应用。如果 写成 CMD /start.sh 或者 CMD ["/bin/bash/" "/start.sh"], CTRL+C 命令并不能中止我们的程序,正确的写法是 CMD /start.sh
使用shell exec来执行你的wrapper scripts。
很多镜像使用wrapper scripts, 这样可以在启动应用程序之前做一些配置操作。如果你有这样的脚本,请不要忘记 使用 exec 来调用你的应用。 有的时候,docker 发出的信号可能会被wrapper scripts截获。使用exec可以使你的应用进程pid=0.
yum install mysql;yum clean all
积累重构
随着时间的推移,可能镜像的层级越来越多,当镜像个头比较大时,可以通过从基础镜像重构来降低容量。
镜像兼容性好
镜像执行效率高
镜像体积小
镜像可以被继承
尽量使用Dockerfile制作镜像
有两种方法可以制作docker镜像对一个正在运行的contianer,使用docker commit 创建镜像。
基于dockkerfile,使用
docker build创建镜像
Docker commit提供了一种灵活的制作镜像的方式,但是它的主要作用时对当前docker 容器内容备份。如果你准备做基础镜像,我们是不推荐这种方式。
Docker commit 会记录docker run时提供的部分参数。
没有Dockerfile作为描述文件,不易于镜像管理维护。
不容易控制docker镜像的层次
使用Dockerfile做镜像的好习惯:
提供完整的 MAINTAINER
信息
MAINTAINER指令用与设置 image的作者信息,如果用户出现问题,可以很容易的联系到原始作者。
除非设计目的时把容器当作系统应用程序使用,否则不要使用ENTRYPOINT
有很多关于CMD和[code]ENTRYPOINT 指令如何工作的讨论,下面我们简单复习CMD和ENTRYPOINT的在docker run 时如何工作。
CMD指令的官方解释是:The main purpose of a CMD is to provide defaults for an executing container
ENTRYPOINT指令的官方解释是: An ENTRYPOINT allows you to configure a container that will run as an executable.
CMD,ENTRYPOINT 及Docker run 时指定的命令,参数关系如下:[/code]
Dockerfile 只设定了[code]CMD。 如果docker run 没有指定命令和参数,那么CMD设定的命令作为第一个程序被执行。如果docker run设定了命令和参数,CMD指令将不会被调用, docker run 指定的命令将会作为第一个程序被执行。[/code]
Dockerfile 设定了 [code]ENTRYPOINT, 那么ENTRYPOINT指定的命令作为第一个程序被执行。如果docker run 设定了命令和参数,该命令和参数将最为ENTRYPOINT指定命令的参数;如果docker run 没有设定参数,CMD的指令将作为ENTRYPOINT指定命令的参数[/code]
所以要小心使用 [code]ENTRYPOINT,除非你的容器时当作命令来设计的,否则不要使用ENTRYPOINT[/code]
使用ARRAY 而不是STRING 来运行程序
你可能已经注意到 CMD和ENTRYPOINT中ARRAY 和STRING的区别, ARRAY中的命令会被直接执行,即我们所说的exec; 而STRING会被/bin/sh调用执行。
很多镜像使用wrapper scripts 启动应用程序。 如果你有这样的脚本,应该使用exec来执行它。 否则,docker 发出的信号不会被你的程序截获。举个例子:
我使用start.sh 来启动自己的应用。如果 写成 CMD /start.sh 或者 CMD ["/bin/bash/" "/start.sh"], CTRL+C 命令并不能中止我们的程序,正确的写法是 CMD /start.sh
使用shell exec来执行你的wrapper scripts。
很多镜像使用wrapper scripts, 这样可以在启动应用程序之前做一些配置操作。如果你有这样的脚本,请不要忘记 使用 exec 来调用你的应用。 有的时候,docker 发出的信号可能会被wrapper scripts截获。使用exec可以使你的应用进程pid=0.在Dockerfile中,EXPOSE 重要的端口
EXPOSE指令会使得端口对主机及containers可见。 在Dockerfile中使用
EXPOSE端口,可以被docker ps/inspect 命令显示,对用户了解如何镜像很用帮助。
应该避免 Volumes的使用
VOLUME指令和
docker run 的 -v选项会使用外部的文件系统来代替容器内的文件系统。Volumes 具有容器共享,持久保存数据的优点。但是volume和外部系统关联密切,除非特殊需要,应避免在Dockerfile中设置VOLUME指令。合理的做法是,在容器内部预留目录,用户使用docker run -v 参数挂载。
尽量不要使用 root用户
Dcoker 的系统资源隔离并不彻底,Docker实现了对 进程,网络,挂载,机器名,和共享内存的隔离,但是还存在未被隔离的资源,如:/dev/mem, /dev/sd* file system devices,Kernel Modules。 所以如非特殊需求,请使用non-root运行容器。要注意Dockerfile的层级关系
Dockerfile中的每条指令都会为镜像增加新的一层。制作基础镜像,合理的设置指令的先后顺序,能够后续image 生成的时间。在遵循Dockerfile规则的前提下,应该把变化较少的指令放在前面,变化较多的放在后面。
要清除指令产生的临时文件
Docker build过程中,临时文件也会被添加到新的一层中,所以应及时清理临时文件,这样才能保证做出来的镜像个头比较小。 如: 下面命令,中每次安装后清楚缓存就是正确的做法,yum install mysql;yum clean all
要减少对系统的依赖
一个好的image应该在任何系统上都可以执行,如Linux,Solaris,Windows。这就要求我们的基础镜像,应该尽量及于可控的系统,如centos或者ubuntu. 在基础镜像中完成对系统的配置,如yum 安装,apt安装等。轻量级更新模式
大量的包安装应该发声在基础镜像阶段,后续软件变更,要抛弃包安装模式,采取轻量的更新方式。最后只更改程序变化的部分。积累重构
随着时间的推移,可能镜像的层级越来越多,当镜像个头比较大时,可以通过从基础镜像重构来降低容量。
相关文章推荐
- 如何用Docker编排容器
- 基于Docker的PHP开发环境
- 《Docker入门实战》笔记(一)
- rest service + spring boot + docker - (a != b) ? b : a - ITeye技术网站
- docker下基于flannel的overlay网络分析
- Docker点滴
- Ubuntu 15.04 下 Docker 1.7.1 中DOCKER_OPTS配置不生效的解决
- Docker搭建Java web环境
- rest service + spring boot + docker
- Flocker浅析与Docker插件(2)
- Docker源码分析(七):Docker Container网络 (上)
- Docker容器的跨主机访问
- Docker源码分析(六):DOCKER DAEMON网络
- Docker源码分析(五):Docker Server的创建
- Docker源码分析(四):Docker Daemon之NewDaemon实现
- Docker 容器日志的那些事儿
- docker exec 与容器日志
- docker logs 实现剖析
- [转]通过Mesos、Docker和Go,使用300行代码创建一个分布式系统
- 一图看尽Docker容器文件系统