V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiqingongzi
V2EX  ›  Docker

新手指南:如何将应用打包成为 Docker 镜像?

  •  
  •   xiqingongzi ·
    bestony · 2016-07-12 19:10:28 +08:00 · 25671 次点击
    这是一个创建于 3067 天前的主题,其中的信息可能已经有所发展或是发生改变。

    虽然 DockerHub 提供了大量的镜像,但是由于企业环境的多样性,并不是每个应用都能在 DockerHub 找到对应的镜像来使用。那就要求企业的运维人员掌握制作 Docker 镜像的技能。在开始打包应用前,你首先要明白这两件事: 第一件事是选择适合你的方式来生成镜像: 1. 通过 Dockerfile 来自动编译生成镜像,实现构建镜像的需求。 2.通过容器内操作,并进行 Commit 来实现打包生成镜像。第一种思路多用于用户交互较少的时刻,比如软件部署时无需输入任何命令的应用。第二种思路用于用户交互较多、安装过程中配置较多的应用。 第二件事是你需要注意,如何拆分现有的应用,来实现打包。Docker 容器化的应用应当是功能最小化的应用。这里的拆分并不是指将每个软件拆分成为一个容器,而是强调实现功能最小化。拿最常见的 LAMP 架构来讨论。最小化的结构应当是 Apache 和 PHP 在一个容器内, MySQL 在一个容器内。而不是将 Apache 、 PHP 、 MySQL 各自拆分一个容器。 Apache 和 PHP 的有机结合使结构内的应用完整的实现了 PHP 解析和 Web 页面的功能,而 MySQL 独自承担了数据存储的功能。而各自拆分一个容器会导致架构极为复杂,在进行容器扩容时也容易受到影响。一般来说,你可以将应用拆分成为 2-3 个容器, 2 个容器的情况下,是数据存储和应用程序各自一个容器。对于部分应用,可能还有缓存系统,同样也要单独放置在一个容器内。这样的结构下,在你需要扩容时,就比较容易,根据你的需要,可以随时扩容缓存系统或应用程序。

    明了了上面的两件事,接下来进入应用打包的环节。

    Dockerfile 打包

    首先,我们先看下 Docker 官方打包的 Tomcat 镜像的 Dockerfile.

    Dockerfile

    我们可以看到,里面大量执行了 Linux 命令,来安装,部署软件,并且对于需要确认的命令都加入-f 来强制执行。确保没有交互,因为在编译镜像的过程中,无法进行交互操作,如果碰到交互操作,卡住就会导致镜像编译的失败,故而 DockerFile 不支持需要输入命令的安装脚本等

    错误交互演示

    当然,对于 Dockerfile,我们同样也有一些最佳实践:

    • 通过 Dockerfile 构建的镜像应当尽可能精简。
    • 尽量不安装非必要的软件包。
    • 一个容器只运行一个单独的实例,将具有耦合度的应用分别安装到不同的容器里面。
    • 慎重引入新的数据层
    • 将准备安装的软件包按安装的字母顺序排列,这样可以避免重复安装软件包的情况,同时也有助于进行软件更新。通过添加 “\” 分割命令,增加代码的可读性
    • 尽量选择官方提供的镜像版本来作为基础镜像,减小镜像的体积。
    • 将多条 RUN 命令使用"/"连接起来,这样更易于理解,可以方便维护。
    • 为镜像定义一个比较通用的端口,比如提供 HTTP Web 服务的镜像,最好是暴露 80 端口。
    • Dockerfile 的开头几行的指令应当固定下来,不要每次都随意更改,这样可以利用缓存
    • 通过 – t 标记来构建镜像,有助于用户管理每个创建的镜像。
    • 不要在 Dockerfile 中映射公有端口。
    • 使用 CMD 和 ENTRYPOINT 时,一定要用数组语法,而且 CMD 和 ENTRYPOINT 结合使用更好
    • 不要开机初始化
    • 在 Push 之前,现在本地构建运行一下,确保本地构建的镜像可以在任何地方正常运行。
    • 不要在构建中升级版本,如果更新时试图修改 Init 或改变容器的内容,更新可能会失败,还可能产生不一致的镜像。
    • FROM 命令应该包含基础镜像的完整仓库名和标签
    • 使用指令组合,比如 apt-get update 应该和 apt-get install 结合。

    基础镜像 Commit 生成镜像

    除了通过 Dockerfile 来打包生成镜像外,也可以通过 Docker Commit 来生成镜像。通过 Commit 打包的镜像多是由于应用本身在部署时有大量的交互内容,无法通过命令来指定。 在通过 Commit 打包镜像时,我们需要如下操作: 1.启动一个基础镜像容器,并进入 console docker run -i – t centos:6.7 上面的命令创建了一个基于 CentOS 6.7 的容器,并进入到容器内

    进入容器

    2.执行配置环境的命令 登陆容器后,可以执行各种 Linux 下的命令。

    安装软件

    等配置完环境后,打开一个新的控制台 执行命令docker ps,可以看到正在运行的容器

    容器列表

    比如我的容器的 ID 就是 35f1c2ae1f7e 3.将容器打包成镜像 执行命令 docker commit 35f1c2ae1f7e mynewimage 就将容器35f1c2ae1f7e打包为新的镜像mynewimage

    打包镜像

    可以执行docker images查看镜像

    镜像列表

    另外,蜂巢的保存为镜像的功能,就是基于此功能制作的,通过云端容器 Console 的操作,并打包成为镜像,大大降低了上云的难度。无需在本地部署 Docker 环境,即可实现应用的容器化;同时云端打包镜像比本地打包速度也要更快些,大大提升了上云的速度。 保存镜像


    PS.其实官方推荐:单个镜像单个进程。这样的情况下,有利有弊利在于,单进程容器更加适合纵向扩展和复用。但是,在较大的产品框架下,可能容器之间的关联会非常复杂。创建一个应用可能会需要创建非常多的容器。所以,在我看来如何划分,还是应该看使用场景和技术路线,量身定制.

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1073 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:17 · PVG 03:17 · LAX 11:17 · JFK 14:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.