当只有一个应用程序在里面运行时,容器的效果最佳。此应用程序应具有单个父进程。例如,不要在同一容器中运行PHP和MySQL:更难调试,Linux信号将无法正确处理,无法水平扩展PHP容器等原因。这使您可以将应用程序的生命周期和该容器绑定在一起。
上图中左边的容器遵循最佳实践,右边的容器没有。
Kubernetes和Docker将Linux信号发送到容器内的应用程序以停止它,使用进程标识符(PID)1将这些信号发送到指定进程。如果您希望应用程序在需要时正常停止,则需要正确地处理这些信号。
谷歌开发者提倡的Sandeep Dinesh的文章——《Kubernetes最佳实践:如何优雅终止kubernetes[1]》——解释了整个Kubernetes终止生命周期。
Docker可以缓存镜像层以加速以后的构建。这是一个非常有用的功能,但在编写Dockerfiles时,需要介绍一下我们需要考虑的一些行为。 例如,您应该在Dockerfile中尽可能晚地添加应用程序的源代码,以便基本镜像和应用程序的依赖项得到缓存,并且不会在每次构建时重建。
以下面这个Dockerfile为例:
dockerfile
FROM python:3.5
COPY my_code/ /src
RUN pip install my_requirements
你应该把最后两行交换一下:
dockerfile
FROM python:3.5
RUN pip install my_requirements
COPY my_code/ /src
在新版本中,pip命令的结果将被缓存,并且每次源代码更改时都不会重新运行。
删除不必要的工具
减少主机系统的攻击面总是一个好主意,而且使用容器比使用传统系统容易得多。从容器中删除应用程序不需要的所有内容。 或者更好的处理是,仅将您的应用程序包含在distroless或scratch镜像中。 如果可能,您还应该将容器的文件系统设置为只读。这样在您的绩效考核期间可以从安全团队获得一些出色的反馈。
谁喜欢下载数百兆的无用数据?大家都想获取最小的镜像。这样可以减少下载时间,冷启动时间和磁盘使用量。您可以使用多种策略来实现这一目标:从最小的基本镜像开始,利用镜像之间的公共层,并利用Docker的多阶段构建功能。
上图展示了Docker多阶段构建过程。
谷歌开发者提倡的Sandeep Dinesh的文章——《Kubernetes最佳实践:如何以及为何构建小型容器镜像[2]》——深入介绍了这一主题。
仔细考虑是否使用公共镜像
当你开始使用某个特定的软件时,使用公共镜像是个不错的选择。 但是,在生产中使用它们可能会带来一系列挑战,特别是在约束高的环境中。 例如,您可能需要控制其中的内容,或者您可能不想依赖外部存储库。 另一方面,为您使用的每个软件都构建自己的镜像并非易事,尤其是因为您需要跟上上游软件的安全更新。仔细权衡每种选择的优缺点,并做出明智的决定。
相关链接:
https://cloudplatform.googleblog.com/2018/05/Kubernetes-best-practices-terminating-with-grace.html
https://cloudplatform.googleblog.com/2018/04/Kubernetes-best-practices-how-and-why-to-build-small-container-images.html
原文链接:https://cloudplatform.googleblog.com/2018/07/7-best-practices-for-building-containers.html