微容器:更小的,更轻便的Docker容器

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文讲的是微容器:更小的,更轻便的Docker容器,【编者的话】本文介绍了微容器的概念和好处,并用一些例子介绍了如何构建微镜像,从scratch到Alpine Linux,并推荐了一些已有的基础微镜像,方便为几乎所有主流语言的应用构建微镜像。
本文讲的是微容器:更小的,更轻便的Docker容器 【编者的话】本文介绍了微容器的概念和好处,并用一些例子介绍了如何构建微镜像,从scratch到Alpine Linux,并推荐了一些已有的基础微镜像,方便为几乎所有主流语言的应用构建微镜像。本文也指出了构建微镜像的基本原理:将构建时依赖和运行时依赖分开,构建时所用的镜像包含所有构建所用的工具,它可以比较大,但运行时的基础镜像应该仅包含运行时依赖。使用微容器, no going back!
microwhale-vs-bigwhale.png

Docker  使你能把你的应用和应用的依赖打包到一个良好的自包含镜像中。然后你可以用该那个镜像来在容器中运行你的应用。问题是,你通常也打包了一些你可能不需要比你需要的更多的东西,最终座椅最重你得到了一个巨大的镜像和巨大的容器。大多数开始使用Docker的人会使用Docker的 官方仓库 作为他们的语言的选择,但是不幸的是,如果你使用官方镜像,你会得到一个巨大的镜像,而本来你可以得到一个小镜像的。你并不需要和这些官方镜像中一起的许多复杂的东西。例如,如果你使用 官方的Node镜像 构建一个你的应用的Node的镜像,它至少有643MB大,因为这是 官方Node镜像的大小

我构建了一个简单的 Hello World Node 应用 ,在官方Node镜像上构建,它的大小是644MB。
tnf.jpg

这太大了!我的应用加上依赖也不超过1MB,Node.js的运行时大概20MB,那是什么占据了剩下的620MB?我们应该能做得更好。

什么是微容器?

一个微容器仅包含OS库和运行应用所需要的语言依赖以及应用本身。其他都不需要。

与其包含所有,不如仅包含最基本的,在需要的时候添加依赖。

以上面的Node应用为例,使用一个小的基础镜像,然后安装核心的部分,即Node.js和它的依赖,它只有29MB,小了22倍(见下图)!
tnl.jpg

pasted_image_at_2016_01_22_11_20_am.png

如果你想,现在试试运行这两个镜像, docker run –rm -p 8080:8080 treeder/tiny-node:fat  然后  docker run –rm -p 8080:8080 treeder/tiny-node:latest 。完全一样的应用,而大小大不相同。

为什么微容器很棒?

有许多使用微容器的好处:
  • 大小 —— 微容器很小。像上面展示的,没有改变任何代码,镜像大小减少了22倍。
  • 快速/简单的发布 —— 因为镜像非常小,可以更快地从 Docker registry(例如 Docker Hub)下载镜像,因而可以更快地发布到不同的机器。
  • 提高安全性 —— 更少的代码和程序在容器中意味着更小的攻击面。基础OS就更安全(详见下文)。

这些好处和 Unikernels 的好处类似,没有任何缺点。

如何构建微容器

所有Docker镜像的基础镜像是 scratch 镜像。它本质上什么都没有。听起来它好像没什么无用,但是你可以用它 创建你的应用的最小可能镜像 ,如果你把你的应用编译为一个没有依赖的静态二进制文件,像Go或C那样。例如,我的 treeder/static-go 镜像  包含了一个Go的Web应用,则整个镜像(包括我的应用)是5MB。
sgl.jpg

这是关于如何得到尽可能小的镜像:scratch镜像+你的应用的二进制文件。

然而并不是所有人都是用Go,所以你可能有更多的依赖,并且你需要比scratch镜像要多一些的东西。关于 Alpine Linux ,我不会枯燥地告诉你关于它的细节,但是他们的广告语说出了全部:“Alpine Linux是一个面向安全的,轻量的Linux发行版,基于musl libc和busybox。” 你可以在 这里 得到详细说明,但是我们这篇文章最关心的是“轻量”的部分。基础的Alpine镜像只有5MB。
apl.jpg

现在我们有一个非常好的OS作为一个基础镜像,它有一个 很好的包管理系统 来添加我们的依赖。对于我们的简单的Node应用而言,我们只需要Node自己,所以我们可以只添加Node包。我们的Dockerfile看起来像这样:
FROM alpine
RUN apk update && apk upgrade
RUN apk add nodejs

简单而整洁。现在我们只在镜像中有Node和Node的依赖。
现在为了添加我们的代码到镜像中,只需要在我们的Dockerfile中添加几行:
FROM alpine
RUN apk update && apk upgrade
RUN apk add nodejs
WORKDIR /app
ADD . /app
ENTRYPOINT [ "node", "server.js" ]

你可以获得示例代码并且在 这里 查看完整的构建指导。

同样的规则适用于所有其他的语言。

适用于所有语言的基础镜像

幸运的是,我们已经构建了一个适用所有主要语言的基础镜像,你可以在这里找到它们: https://github.com/iron-io/dockers

它们有一些优化来使它们尽可能的小,并且我们会定期更新,使用基础镜像使得它们比起你自己来更好。通过使用Iron.io的基础镜像,上面Node应用的Dockerfile变成这样:
FROM iron/node
WORKDIR /app
ADD . /app
ENTRYPOINT [ "node", "server.js" ]

另外,对于每一种其他语言,我们构建了两个版本的这种镜像,一个用于构建,另一个用于运行。用于构建的镜像有所有的构建工具在其中,所以可能比运行时要更大。

例如,为了构建Node的依赖,你要像这样使用 iron/node:dev
docker run --rm -v "$PWD":/app -w /app iron/node:dev npm install

然后在你的Dockerfile中使用 iron/node 然后运行它:
docker run --rm -it -p 8080:8080 -v "$PWD":/app -w /app iron/node node server.js

上述方法同样适用于其他语言,但是你需要使用它们自己的 build/vendor/run 的指令。

如果你想要一个语言的不同版本,你可以改变tag,例如你可以使用iron/node:4.1或者iron/node:0.12。你可以在Docker Hub上找到每个语言的所有的版本tag。例如Node的tag在这里: https://hub.docker.com/r/iron/node/tags/ 。你可以在 iron-io/dockers 的项目里找到所有其他Docker Hub tags的链接。

如何为所有的语言构建和打包

这可能没那么幸运了,但是我们有一些例子可以让大多数主流语言使用上面的基础镜像: https://github.com/iron-io/dockerworker

你可以看看那个项目中的每个语言的README,它会指引你如何构建你的依赖,测试你的代码,构建一个小的Docker镜像和测试镜像。

没有回头

读完本文之后,你应该可以为你的应用创建只包含运行应用所需要的东西的Docker镜像。容器本质是一个镜像的实例,所以一旦你开始用你的镜像来运行容器,你就进入了微容器的世界。没有(理由)回头。

刚使用了你的“小镜像”技术在我的一个golang项目上,很棒!感谢这篇伟大的文章。竟然令人震惊地减小到5mb。 —— Harlow Ward @ Clearbit
原文链接:Microcontainers – Tiny, Portable Docker Containers (翻译:陈光 审校:高婧雅)

原文发布时间为:2016-02-20
本文作者:Casgy 
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:微容器:更小的,更轻便的Docker容器
目录
相关文章
|
11天前
|
数据库 Docker 容器
docker容器为啥会开机自启动
通过配置适当的重启策略,Docker容器可以在主机系统重启后自动启动。这对于保持关键服务的高可用性和自动恢复能力非常有用。选择适合的重启策略(如 `always`或 `unless-stopped`),可以确保应用程序在各种情况下保持运行。理解并配置这些策略是确保Docker容器化应用可靠性的关键。
158 93
|
1月前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
264 77
|
13天前
|
Ubuntu NoSQL Linux
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
86 6
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
|
25天前
|
搜索推荐 安全 数据安全/隐私保护
7 个最能提高生产力的 Docker 容器
7 个最能提高生产力的 Docker 容器
112 35
|
1月前
|
监控 Docker 容器
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序
|
12天前
|
数据库 Docker 容器
docker容器为啥会开机自启动
通过配置适当的重启策略,Docker容器可以在主机系统重启后自动启动。这对于保持关键服务的高可用性和自动恢复能力非常有用。选择适合的重启策略(如 `always`或 `unless-stopped`),可以确保应用程序在各种情况下保持运行。理解并配置这些策略是确保Docker容器化应用可靠性的关键。
40 17
|
24天前
|
Ubuntu Linux 开发工具
docker 是什么?docker初认识之如何部署docker-优雅草后续将会把产品发布部署至docker容器中-因此会出相关系列文章-优雅草央千澈
Docker 是一个开源的容器化平台,允许开发者将应用程序及其依赖项打包成标准化单元(容器),确保在任何支持 Docker 的操作系统上一致运行。容器共享主机内核,提供轻量级、高效的执行环境。本文介绍如何在 Ubuntu 上安装 Docker,并通过简单步骤验证安装成功。后续文章将探讨使用 Docker 部署开源项目。优雅草央千澈 源、安装 Docker 包、验证安装 - 适用场景:开发、测试、生产环境 通过以上步骤,您可以在 Ubuntu 系统上成功安装并运行 Docker,为后续的应用部署打下基础。
docker 是什么?docker初认识之如何部署docker-优雅草后续将会把产品发布部署至docker容器中-因此会出相关系列文章-优雅草央千澈
|
12天前
|
运维 Java 虚拟化
《docker基础篇:1.Docker简介》,包括Docker是什么、容器与虚拟机比较、能干嘛、去哪下
《docker基础篇:1.Docker简介》,包括Docker是什么、容器与虚拟机比较、能干嘛、去哪下
76 12
|
13天前
|
Kubernetes Linux 虚拟化
入门级容器技术解析:Docker和K8s的区别与关系
本文介绍了容器技术的发展历程及其重要组成部分Docker和Kubernetes。从传统物理机到虚拟机,再到容器化,每一步都旨在更高效地利用服务器资源并简化应用部署。容器技术通过隔离环境、减少依赖冲突和提高可移植性,解决了传统部署方式中的诸多问题。Docker作为容器化平台,专注于创建和管理容器;而Kubernetes则是一个强大的容器编排系统,用于自动化部署、扩展和管理容器化应用。两者相辅相成,共同推动了现代云原生应用的快速发展。
77 11
|
30天前
|
存储 Kubernetes 开发者
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
Docker 是一种开源的应用容器引擎,允许开发者将应用程序及其依赖打包成可移植的镜像,并在任何支持 Docker 的平台上运行。其核心概念包括镜像、容器和仓库。镜像是只读的文件系统,容器是镜像的运行实例,仓库用于存储和分发镜像。Kubernetes(k8s)则是容器集群管理系统,提供自动化部署、扩展和维护等功能,支持服务发现、负载均衡、自动伸缩等特性。两者结合使用,可以实现高效的容器化应用管理和运维。Docker 主要用于单主机上的容器管理,而 Kubernetes 则专注于跨多主机的容器编排与调度。尽管 k8s 逐渐减少了对 Docker 作为容器运行时的支持,但 Doc
140 5
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档