docker 没有镜像_从安全到镜像流水线,Docker 最佳实践与反模式一览

本文探讨了Docker的最佳实践和反模式,强调了正确使用标签、避免在同一容器中运行多个服务、避免构建环境特定的镜像以及使用非Root容器的重要性。通过合理的标签管理,确保Docker镜像的版本控制和可追踪性,同时,保持每个服务的独立性以简化扩展和安全管理。使用非Root用户运行容器可以增强安全性,但可能需要处理权限问题。
摘要由CSDN通过智能技术生成
338eaf3205b30a9993cd0d3d2fdcc8e7.png

作者 | Timothy Mugayi

译者 | 弯月,责编 | 夕颜

封图 | CSDN付费下载自视觉中国

出品 | CSDN(ID:CSDNnews)

在使用Docker的大部分时间里,我们并不关心其内部的工作原理。仅凭启动一个Docker容器并且让应用程序运行良好,并不能说明你已经实现了一个良好的解决方案。有时,由于时间限制,我们只能复制粘贴Docker镜像,却没能真正理解实现细节以及如何构建Docker镜像的细微差别。

在本文中,我们将探讨Docker的最佳实践和反模式。反模式是人们对于反复出现的问题的一般解决方案,这些方案没有效率,甚至会完全抵消Docker技术栈带来的好处。

下面我们来看看我们的哪些做法不可取。

7af9dc697223f7a5bfdd9d2e904e529d.png

我们需要的标签

标签是必不可少的,我们需要通过标签传达有关Docker镜像的信息。你可以将标签视为Docker镜像ID的别称。Git标签负责标记特定的提交,而Docker标签与之类似,可以给不同时间点上的Docker镜像添加版本。忘记打标签是小事,但会带来一些弊端,具体来讲,如果未指定标记,则默认镜像将被标记为latest。

FROM your_image_name:latest

如果你频繁执行该操作,那么很有可能镜像不是最新的,可能指向的是旧版本。因此,请使用适当的标签并遵守某个版本控制标准,例如语义版本控制。这样,Docker镜像使用者才能确保Docker镜像的兼容性并时刻保持最新,还可以有计划地使用正确的版本。

还有一个情况应该避免。你可以利用最新的默认标签(如FROM python3:latest),从Docker镜像仓库中提取最新的镜像。乍一看,这种做法似乎是个好主意,但却有一些意想不到的副作用:每个最新的请求可能都会派生出与以前的构建完全不同的Docker镜像。弄明白Docker镜像损坏的原因将会变得很困难,因为镜像本应该是不可变的。因此,我强力建议使用特定的标签来标记镜像(例如:python3:1.0.1)。这种方法可以确保你的Dockerfile保持不变。

0dcc1c91cd01e9116f186330af13b825.png

在同一个容器中运行多个服务

虽然你可以在同一个容器中运行多个服务,但我并不建议你这么做,原因有两个。在使用Docker服务时,我们应该努力维持责任单一性。最佳做法是,组成应用程序的每个服务都应在各自的容器中运行,请务必将每项独立的功能都打包到单独的独立容器镜像中。

将多个服务添加到一个Docker镜像的做法似乎很诱人,但是你不应该将容器镜像视为虚拟机。一个容器包含多个服务,可能会导致你的应用程序很难水平扩展。Docker容器核心概念是,它们都是瞬态的,专为分发而设计,这对于现代Web应用程序来说很理想,因为它的瞬态特性、扩展和并发会非常容易。添加多个服务会增加管理分发的难度。

另外,单个容器上的多个服务还会加大管理安全性的难度。庞大的镜像可能会降低CI/CD的速度,你需要小心。

345a531ed60c60590066084d922acd1a.png

使用LABEL对镜像进行分类

这并不能说是反模式,但我认为值得一提。我在处理各种Docker镜像时注意到了一件事:有时这些镜像的创建者没有使用LABEL maintainer标签。这个标签可在事件中设置镜像的Author字段,当出现问题或需要澄清时,这个标签可以方便大家了解该与何人内部联系;如果镜像是公开共享的,也可以知道该与哪个外部的人联系。

这绝不是唯一可以使用的标签。你可以根据需要定义各种标签,来对镜像进行分类,定义许可信息,也可以定义标签来帮助自动化。

除了maintainer,还可以使用多行标签:

# Set one or more individual labelsLABEL com.example.version="0.0.1-beta"LABEL vendor1="RBTSB Incorporated"LABEL vendor2=TIPTAPCODE IncorporatedLABEL com.example.release-date="202-04-02"LABEL com.example.version.production="0.0.1"

Docker 1.10之前的单行标签会创建新的docker层,如果你使用的是最新版的Docker,则不必担心创建额外的层。

LABEL vendor=ACME Incorporated com.example.is-beta= com.example.is-production="" com.example.version="0.0.1-beta" com.example.release-date="2015-02-12"

我们应该将尽可能多的元数据添加到不可变的Docker镜像,以方便追踪,提高可见性和可维护性。

1f5d9e78f86d4242be5452e9dbc0c1be.png

避免构建依赖特定环境的镜像

在构建Docker镜像时,我们应始终牢记不变性。最好不要使用带有dev、test、staging和production的镜像,因为这会破坏单一来源的原则。另一个问题是,如果在不同环境上验证或调试,则这种做法无法保证镜像的相似。

6c5bdf2339ef61f2d136289b399ff9f1.png

为什么要使用非Root容器?

在默认情况下,Docker容器以root身份运行。以root用户身份运行的Docker容器可以完全控制主机系统。然而,出于安全考虑,我并不推荐这种做法。使用非root运行的Docker容器镜像可以多一层保护,在生产环境中通常建议使用非root容器。但是,由于这些容器由非root用户运行,因此无法执行需要特殊权限的任务。如果需要利用USER指令指定非root用户(如以下示例所示),则需要进行一些上下文切换。

FROM python:3.6-slim-busterLABEL maintainer="Timothy Mugayi "RUN apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/*# Dumb initRUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64RUN chmod +x /usr/local/bin/dumb-initRUN pip install --upgrade pipWORKDIR /usr/src/appCOPY requirements.txt .RUN pip install -r requirements.txtCOPY helloworld.py .USER 1001ENTRYPOINT ["/usr/local/bin/dumb-init
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值