当我第一次学习Docker时,我期望有一个配置文件,映像生成器,CLI以及用于挂载和网络的选项。就这些了。
我没想到将构建命令放入Dockerfile中。我以为docker可以包装/压缩/包含我所做的预建任务。为什么要在Docker中提供构建命令?
它肯定可以导入任务,从而使Jenkins / Bazel等与众不同且分开以制作图像/容器吗?
答案 0 :(得分:6)
我想我们正在处理一个误解。 Docker不是VMware / Xen / KVM / Parallels / FancyVirtualization的轻量级版本。
免责声明:为全面起见,以下内容被大大简化了。
一句话:Docker是一个在操作系统中尽可能将进程与其他进程隔离的系统,同时仍提供运行它们的所有方法。换句话说:
Docker是用于隔离进程的软件包管理器。
chroot和BSD监狱是其最亲密的祖先之一。这些工作的主要目的是隔离一部分OS资源(对于BSD,更多的是chroot),并使其独立于其余OS的完整环境运行- except 内核。
为了能够做到这一点,Docker镜像显然需要包含内核的所有除了。因此,您需要提供一个shell(如果您选择这样做),标准库(例如glibc),甚至资源(例如CA证书)。供参考:为了设置chroot监狱,您曾经一次手工完成所有这些工作,并在chroot环境中预安装了所需的每一个软件。 Docker基本上是从这里来的繁重工作。
提到的隔离甚至是已安装的(和可用的软件)听起来都很麻烦,但是作为开发人员,它给您带来了许多好处。由于除了(兼容)内核外,您基本上提供了所有其他内容,因此您可以在以后运行的相同环境中开发和测试代码。这不是一个近似的近似值,而是字面上相同的环境,一点一点地出现。关于Docker的一个相当著名的谚语是:
“在我的机器上运行”不再是借口。
另一个优势是可以将静态资源添加到您的Docker映像中,并通过非常普通的文件系统语义来访问它们。您当然也可以使用虚拟化映像来做到这一点,但是它们通常不带有用于配置的语言。 Docker可以-Dockerfile
:
FROM alpine
LABEL maintainer="you@example.com"
COPY file/in/host destination/on/image
如上所述,您需要提供应用程序具有的 all 个依赖项(以及传递性依赖项)。确保这一点的最简单方法是在Docker映像内构建应用程序:
FROM somebase
RUN yourpackagemanager install long list of dependencies && \
make yourapplication && \
make install
如果构建失败,则说明您缺少依赖项。现在,您可以调整和调整Dockerfile
,直到它编译并通过测试。因此,现在您的Docker映像已完成,您可以放心地分发它,因为您知道,只要docker守护进程在有人尝试在其上运行映像的机器上运行,您的映像就会运行。>
在Go生态系统中,您基本上可以确保go.mod
和go.sum
是最新的并且可以正常工作,并且可以重复工作。
(良好)泊坞窗映像仅运行其需要运行的映像。在绝大多数docker映像中,这仅意味着一个进程,例如您的Go程序。
侧面说明:在一个Docker映像中运行多个进程是很不明智的做法,比如说您的应用程序,数据库服务器,缓存和诸如此类的东西。这就是docker-compose的用途,或更笼统地说是容器编排。但这是一个太大的话题,无法在这里解释。
但是,虚拟化的OS需要运行内核,外壳,驱动程序,日志系统等等。
因此,解决问题的基本方法是您获得所有的好东西(隔离,可再现性,易于分发),而浪费的资源更少(运行相同操作系统的5个版本及其所有恶作剧)。
答案 1 :(得分:1)
因为我们希望拥有可复制构建的环境。我们不想依赖语言的版本,编译器的存在,libraires的版本等等。
答案 2 :(得分:1)
在Dockerfile中构建可让您独立于平台使用所需的所有工具和环境。从开发的角度来看,将所需的所有内容轻松放入容器中即可。
但是您必须考虑在Dockerfile中进行构建的目标,如果您的构建过程非常复杂且具有很多依赖项,则必须担心将所有工具都包含在其中,并且它会反映您最终的大小结果图像。因为生成人工制品的建筑物与生成最终容器的建筑物不是同一建筑物。
考虑这两个方面,您必须学习在Docker here中使用多阶段构建过程。主要想法更接近于您的问题,因为根据构建过程的不同,您可以根据需要拥有任意多个阶段,并使用不同的FROM
映像来确保您对每个阶段都有正确的要求和依赖性,从而最终生成具有最小依赖性和较小尺寸的图像。
答案 3 :(得分:0)
我将在上面的答案中添加:
是否在docker中进行构建是取决于您的目标的选择。就我而言,我对kubernetes的Docker容器更感兴趣,此外,我们已经拥有成熟的构建。
此链接显示如何执行预建任务并将其添加到图像中。该策略与添加库,环境等一起很好地利用了docker,表明docker确实是灵活的。 https://medium.com/@chemidy/create-the-smallest-and-secured-golang-docker-image-based-on-scratch-4752223b7324