如何制作高质量的docker镜像

本文详细阐述了如何创建高效、兼容性好、体积小且易于维护的Docker镜像,包括使用Dockerfile的技巧、CMD与ENTRYPOINT的正确使用、避免不当使用Volumes和root用户、优化Dockerfile层级关系以及清理临时文件的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天我们讨论下,Docker 的用户们关心的问题,如何制作高质量的镜像。首先我们对高质量镜像标准进行定义。

  • 镜像兼容性好
  • 镜像执行效率高
  • 镜像体积小
  • 镜像可以被继承

尽量使用Dockerfile制作镜像

有两种方法可以制作docker镜像

  • 对一个正在运行的contianer,使用docker commit 创建镜像。
  • 基于dockkerfile,使用docker build创建镜像

Docker commit提供了一种灵活的制作镜像的方式,但是它的主要作用时对当前docker 容器内容备份。如果你准备做基础镜像,我们是不推荐这种方式。

  • Docker commit 会记录docker run时提供的部分参数。
  • 没有Dockerfile作为描述文件,不易于镜像管理维护。
  • 不容易控制docker镜像的层次

使用Dockerfile做镜像的好习惯

提供完整的 MAINTAINER信息

MAINTAINER 指令用与设置 image的作者信息,如果用户出现问题,可以很容易的联系到原始作者。

除非设计目的时把容器当作系统应用程序使用,否则不要使用ENTRYPOINT

有很多关于CMD和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 时指定的命令,参数关系如下:
  • Dockerfile 只设定了CMD。 如果docker run 没有指定命令和参数,那么CMD设定的命令作为第一个程序被执行。如果docker run设定了命令和参数,CMD指令将不会被调用, docker run 指定的命令将会作为第一个程序被执行。
  • Dockerfile 设定了 ENTRYPOINT, 那么ENTRYPOINT指定的命令作为第一个程序被执行。如果docker run 设定了命令和参数,该命令和参数将最为ENTRYPOINT指定命令的参数;如果docker run 没有设定参数,CMD的指令将作为ENTRYPOINT指定命令的参数
所以要小心使用 ENTRYPOINT,除非你的容器时当作命令来设计的,否则不要使用ENTRYPOINT

使用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安装等。

轻量级更新模式

大量的包安装应该发声在基础镜像阶段,后续软件变更,要抛弃包安装模式,采取轻量的更新方式。最后只更改程序变化的部分。

积累重构

随着时间的推移,可能镜像的层级越来越多,当镜像个头比较大时,可以通过从基础镜像重构来降低容量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值