专栏首页CU技术社区如何 10 步 Docker 化一个应用?

如何 10 步 Docker 化一个应用?

本文将讲解如何将应用 Docker 化的一些很实用的技巧和准则,推荐一读。

一、选择基础镜像

每种对应技术几乎都有自己的基础镜像,例如:

  • https://hub.docker.com/_/java/
  • https://hub.docker.com/_/python/
  • https://hub.docker.com/_/nginx/

如果不能直接使用这些镜像,我们就需要从基础操作系统镜像开始安装所有的依赖。

网上大多数教程使用的都是以 Ubuntu(例如:Ubuntu:16.04 )作为基础镜像,这并不是一个问题,但是我建议优先考虑 Alpine 镜像:

  • https://hub.docker.com/_/alpine/

Alpine 是一个非常小的基础镜像(它的容量大约只有 5MB)。

注:在基于 Alpine 的镜像中你无法使用 apt-get 命令。不过你不必担心,因为 Alpine 系统有自己的软件包仓库和包管理工具 apk。关于 apk 的具体使用你可以详细参考:「Alpine Linux配置使用技巧」一文。

二、安装必要软件包

这个步骤通常比较琐碎,有一些容易忽略的细节:

  • apt-get updateapt-get install 命令应该写在一行(如果使用 Alpine 则对应的是 apk 命令)。这不是一个常见的做法,但是在 Dockerfile 中应该要这么做。否则 apt-get update 命令产出的临时层可能会被缓存,导致构建时没有更新包信息。(具体可参见此文)。
  • 确认是否只安装了实际需要的软件(特别是在生产环境中运行这个容器)。

注:我见过有人在他们的镜像中安装了 vim 和其他开发工具。如果这是必要的,应该针对构建、调试和开发环境创建不同的 Dockerfile。这不仅仅关系到镜像大小,还涉及到安全性、可维护性等等。

三、添加自定义文件

一些优化 Dockerfile 的小提示:

  • 理解 COPY 和 ADD 指令的区别,具体可参考此文。
  • 尽可能遵照文件系统惯例来存放文件。例如:针对解释型应用程序(如:Python),使用 /usr/src 目录。
  • 检查添加文件的属性。如果需要可执行权限,没有必要在镜像上新建一个层( 通过 RUN chmod +x … 指令来增加权限)。你只需要在代码仓库的源文件上修正这些属性即可,即使开发平台是 Windows,也可以参照此文给文件增加可执行权限。

四、定义容器运行时的用户权限

  • 容器中的进程默认情况下是以 root 权限运行的。
  • 如果容器中的应用程序需要使用特定的用户或组(/etc/passwd 或 /etc/group)来运行时,可以在容器启动时使用 docker run 命令的--user 参数来指定其固定的 UID 或 GID。
  • 尽可能避免容器中的进程以 root 权限运行。

注:现在不少热门应用程序镜像都需要用特定的用户 ID 来运行(例如:Elastic Search 需要 uid:gid = 1000:1000),请尽量不要在写出这样的镜像。更多关于容器内运行应用程序的权限说明可参考此文。

五、定义暴露的端口

不要为了暴露特权端口(例如:80)而将容器以 root 权限运行。如果有这样的需求,可以让容器暴露一个非特权端口(例如:8080),然后在启动时进行端口映射。

注:低于 1024 的 TCP / IP 端口号就是特权端口,因为不允许普通用户在这些端口上运行服务。

六、定义入口点(entrypoint)

  • 普通方式:直接运行可执行文件。
  • 更好的方式:创建一个 docker-entrypoint.sh 脚本,这样可以通过环境变量来配置容器的入口点。这也是一个非常普遍的做法,可参考下面这些例子:elasticsearch 的 docker-entrypoint.sh 文件 和 postgres 的 docker-entrypoint.sh 文件。

七、定义一种配置方式

每个应用程序都需要参数化,你基本上可以遵循以下两个原则:

  • 使用应用程序特定的配置文件:该方式需要通过文档来说明配置文件的格式、字段、放置位置等等(当运行环境比较复杂,例如:应用程序跨越不同的技术,则不太合适)。
  • 使用操作系统环境变量:简单而有效。这也是 12-factors 推荐的方式。

注:使用环境变量方式并不意味着您需要丢弃配置文件并重构应用程序的配置机制,你只需要通过 envsubst 命令来替换配置文件模板中的值就可以了(这个流程一般需要在 docker-entrypoint.sh 文件中完成,因为这需要在容器进程运行前完成)。例如:在 Nginx 配置中使用环境变量,具体方法可参考此文。

这种方式可以将应用程序的配置文件封装在容器内部。

八、外部化数据

关于数据存储有一条黄金法则:绝对不要将任何持久化数据保存到容器内。

容器的文件系统本身是被设计成临时和短暂的。因此任何由应用程序生成的内容、数据文件和处理结果都应该保存到挂载的卷或者操作系统绑定挂载点上(既:将宿主机操作系统的目录挂载到容器中)。

如果将数据保存到绑定挂载点,对于要绑定到容器的宿主机上的目录,你需要注意以下几点:

  • 在宿主机操作系统上创建非特权用户和组。
  • 所有需要绑定目录的所有者都是该用户。
  • 根据使用场景给授权(仅针对这个特定的用户和组,其他用户无权访问)。
  • 容器也以该用户运行。
  • 容器可以完全控制这些目录。

九、确保处理好日志

如果这是一个新的应用程序,并且希望它能够坚持 Docker 约定,就不应该将日志写入任何文件。应用程序应该使用标准输出和标准错误输出日志,这和之前推荐使用环境变量传递参数一样,这也是 12-factors 之一,具体可以参见这里。

Docker 会自动捕捉应用程序的标准输出,并可以通过 docker logs 命令查看。有关于 docker logs 的具体使用你可以参考这里。

但是在一些实际场景下你可能会遇到问题,例如:运行一个简单的 Nginx 容器,至少会有两种不同的日志文件:

  • HTTP 访问日志(Access Logs)
  • 错误日志(Error Logs)

对于这种按照特定结构输出日志的应用,就不太适合将它们的日志输出到标准输出。这种情况下,你需要按持久化的方式处理这些日志,并确保这些日志文件的能正常的轮转。

十、轮转日志

如果应用程序将日志写到文件,或者会无限追加内容到文件,就需要关注这些文件的轮转(rotation),这对于防止服务器空间耗尽非常有用的。

如果使用绑定挂载,我们可以依靠宿主机的一些工具来实现文件轮转功能。例如:logrotate,关于 logrotate 的使用你可以参考示例一、示例二。

注:本文在 「如何 Docker 化任意一个应用」的基础上整理和修改,原文地址:http://t.cn/ReT0AyJ 。

本文分享自微信公众号 - CU技术社区(ChinaUnix2013)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 10分钟看懂Docker和K8S

    2010年,几个搞IT的年轻人,在美国旧金山成立了一家名叫“dotCloud”的公司。

    用户6543014
  • Docker 入门,看这篇就够了

    关于Docker的发展史,本文就不做介绍,有兴趣的小伙伴们可以查看这篇文章,挺有意思的。http://www.oschina.net/news/57838/do...

    用户6543014
  • 简单几步搭建一个基于 Docker 的 Tomcat 运行环境!

    Docker 旨在提供一种应用程序的自动化部署解决方案,在 Linux 系统上迅速创建一个容器 (轻量级虚拟机) 并部署和运行应用程序,并通过配置文件可以轻松实...

    用户6543014
  • Docker入门教程 Part 3 Services

    本篇笔记是官方Get Started入门教程的Part3 Services,主要演示如何使用 docker-compose.yml 来定义应用服务,docker...

    twowinter
  • 史上最简单的SpringCloud教程 | 第十一篇: docker部署spring cloud项目

    一、docker简介 Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地...

    方志朋
  • 5 种 Docker 日志最佳实践

    微服务和容器很好地结合了,但是它们的结合让日志记录也变成了一个难题。作者在本文描述了一些因素,在设置监控的时候是需要考虑的。

    胡文翠
  • docker容器技术系列一:基本概念

    前言:从去年下半年开始,我们就尝试在使用docker部署生产应用,至现在已经有十多个项目使用了docker容器部署,docker为我们节约 了大量的服务器资源,...

    小小科
  • Linux 系统代理魔法对 Docker 无效?

    Linux所谓的系统代理是针对系统使用者,通过SHELL转化用户请求为系统可识别,完成网络出口的系统转发。Docker基于C/S架构运行,Server端由Sys...

    运维部落
  • 公司125相关工具搭建备忘录

    详见:https://blog.52itstyle.vip/archives/3135/

    小柒2012
  • Docker镜像竟然也是容器?!Docker 到底为什么这么快!?

    Docker虚拟化技术是基于容器化,容器化技术的本质其实是基于内核资源调度的再分配! 并不是什么新技术,只是近年Linux内核更加成熟,在资源调度隔离更成熟,所...

    运维部落

扫码关注云+社区

领取腾讯云代金券