Docker开发最佳实践

事实证明,以下开发模式对使用Docker构建应用程序的人们很有帮助。如果您发现了我们应该添加的内容,请告诉我们

如何缩小镜像

在启动容器或服务时更小的镜像能更快地在网络上传输,更快地加载到内存中。有一些经验法则可以使镜像有更小的尺寸:

  • 从适当的基础镜像开始。例如,如果您需要JDK,请考虑将您的镜像基于官方的openjdk镜像,而不是从通用的ubuntu镜像开始并将openjdk作为Dockerfile的一部分进行安装。

  • 使用多阶段构建。例如,您可以使用maven镜像来构建Java应用程序,然后重置到tomcat镜像并将Java构件复制到正确的位置以部署您的应用程序,所有这些都在同一Dockerfile中。这意味着您的最终镜像不包括构建所引入的所有库和依赖项,而仅包括运行它们所需的构件和环境。

    • 如果需要使用不包含多阶段构建的Docker版本,请尝试通过最小化Dockerfile中单独的RUN命令的数量来减少镜像中的层数。为此,您可以将多个命令合并到一条RUN行中,并使用Shell的机制将它们组合在一起。考虑以下两个片段。第一个在镜像中创建两层,而第二个仅创建一层。
    RUN apt-get -y update
    RUN apt-get install -y python
    
    RUN apt-get -y update && apt-get install -y python
    
  • 如果您有多个具有很多共同点的镜像,请考虑使用共享的组件创建您自己的基镜像,并在此基础上创建唯一的镜像。 Docker只需要加载一次公共层,然后将它们缓存。这意味着您的派生镜像将更有效地使用Docker主机上的内存,并更快地加载。

  • 为了使生产镜像保持精简并允许进行调试,请考虑将生产镜像用作调试镜像的基础镜像。可以在生产镜像的上层添加其他测试或调试工具。

  • 在构建镜像时,请始终使用有用的标签来标记镜像,这些标签可以包括版本信息,预期目标(例如,prodtest),稳定性或其他在不同环境中部署应用程序时有用的信息。不要依赖自动创建的latest标签。

在何处以及如何持久化应用程序数据

  • 避免使用存储驱动程序将应用程序数据存储在容器的可写层中。这会增加容器的大小,并且从I/O角度来看,效率不如使用卷或绑定挂载。
  • 使用存储数据。
  • 在开发过程中是一种适合使用绑定挂载的情景,当您可能想挂载源代码目录或刚构建到容器中的二进制文件时。对于生产环境,请改用卷,将其挂载到与开发期间挂载绑定到的相同位置。
  • 对于生产,请使用secrets存储服务使用的敏感应用程序数据,并使用configs存储非敏感数据(例如配置文件)。如果当前使用单独容器,请考虑迁移以使用单一副本服务,以便可以利用这些只有这些服务才有的功能。

使用CI/CD进行测试和部署

当您签入更改到源代码管理或创建拉取请求时,请使用Docker Hub或其他CI/CD管道自动构建并标记Docker镜像并对其进行测试。

在部署到生产中的镜像之前,通过要求您的开发,测试和安全团队对镜像进行签名,使用Docker Engine Enterprise进行进一步的处理。这样,您可以确定在将镜像部署到生产中之前,它已经由开发,质量和安全团队进行了测试和签名。

开发和生产环境的差异

开发环境 生产环境
使用绑定挂载使您的容器可以访问源代码。 使用卷来存储容器数据。
使用Docker Desktop for Mac 或 Docker Desktop for Windows 如果可能,请使用Docker Engine Enterprise,并通过用户映射来更好地将Docker进程与主机进程隔离。
不用担心时间偏差。 始终在Docker主机和每个容器进程中运行NTP客户端,并将它们全部同步到同一NTP服务器。 如果使用群集服务,还请确保每个Docker节点将其时钟同步到与容器相同的时间源。