当前位置:Java -> 使用 Ubuntu Docker 镜像

使用 Ubuntu Docker 镜像

Ubuntu的官方Docker镜像是Docker Hub上下载量最高的镜像。Ubuntu已经证明自己是一个受欢迎且可靠的基础镜像,可以用来构建你自己的定制的Docker镜像,下载量已经达到了超过10亿次。

在本文中,我将向你展示如何在构建自己的Docker镜像时充分利用Ubuntu基础镜像。

一个Dockerfile示例

这里有一个包括了本文讨论的微调的示例Dockerfile。我将逐个解释每一个设置,解释它们的作用:

FROM ubuntu:22.04
RUN echo 'APT::Install-Suggests "0";' >> /etc/apt/apt.conf.d/00-docker
RUN echo 'APT::Install-Recommends "0";' >> /etc/apt/apt.conf.d/00-docker
RUN DEBIAN_FRONTEND=noninteractive \
  apt-get update \
  && apt-get install -y python3 \
  && rm -rf /var/lib/apt/lists/*
RUN useradd -ms /bin/bash apprunner
USER apprunner


使用以下命令构建镜像:

docker build . -t myubuntu


现在,你已经学会了如何从Ubuntu基础镜像构建自定义镜像,让我们来逐个了解为什么要添加这些设置。

选择基础镜像

为所有版本的Ubuntu提供了Docker镜像,包括长期支持(LTS)版本20.04和22.04,以及正常版本如19.04、19.10、21.04和21.10。

LTS版本支持5年,这段时间内由Canonical维护相关的Docker镜像,详情参见Ubuntu发行周期页面

这些镜像也会被频繁更新,发布更新的安全镜像,因此你需要自动使用最新的镜像以确保用户得到一致的安全保障。

创建Docker镜像用于托管生产软件时,最好是将你的镜像基于最新的LTS版本。这可以让DevOps团队在最新的LTS基础镜像上重建他们的自定义镜像,自动包括所有更新,并且不太可能包括在主要操作系统版本之间引入的破坏性变化。

我使用了Ubuntu 22.04 LTS Docker镜像作为此镜像的基础:

FROM ubuntu:22.04


不安装建议或推荐的依赖项

某些软件包有一系列不是必需但却默认安装的建议或推荐的依赖项。这些额外的依赖会不必要地增加最终Docker镜像的大小,正如Ubuntu在他们的关于减小Docker镜像大小的博文中所述

为了对所有调用apt-get的可选依赖项的安装进行禁用,需要在/etc/apt/apt.conf.d/00-docker文件中创建以下设置:

RUN echo 'APT::Install-Suggests "0";' >> /etc/apt/apt.conf.d/00-docker
RUN echo 'APT::Install-Recommends "0";' >> /etc/apt/apt.conf.d/00-docker


安装额外的软件包

大多数基于Ubuntu的自定义镜像需要你安装额外的软件包。例如,要运行用Python、PHP、Java、Node.js或DotNET编写的自定义应用程序,你的自定义镜像必须安装这些语言关联的软件包。

在典型的工作站或服务器上,可以通过简单的命令来安装软件包:

apt-get install python3


在Docker镜像中安装新软件的过程是非交互式的,这意味着你没有机会回应提示。这意味着你必须添加-y参数,自动回答提示继续进行软件包安装:

RUN apt-get install -y python3


防止软件包安装过程中的提示错误

安装某些软件包会尝试打开额外的提示以进一步定制安装选项。在非交互式环境中,比如在构建Docker镜像时,尝试打开这些对话框会导致错误,比如:

unable to initialize frontend: Dialog


这些错误可以忽略,因为它们并不会阻止软件包的安装。但是错误可以通过将DEBIAN_FRONTEND环境变量设置为noninteractive来防止:

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python3


Docker网站提供了关于使用DEBIAN_FRONTEND环境变量的官方指南。他们认为这是一种表面上的变化,并且不建议永久设置这个环境变量。上面的命令设置了环境变量来影响单个apt-get命令的持续时间,意味着任何随后对apt-get的调用将不会定义DEBIAN_FRONTEND

清理软件包列表

在安装任何软件包之前,需要调用以下命令来更新软件包列表:

RUN apt-get update


然而,在安装所需的软件包之后,软件包列表的价值不大。最佳实践是从Docker镜像中清除任何不必要的文件,以确保最终镜像尽可能小。为了在安装所需的软件包后清理软件包列表,在单个命令中更新软件包列表,安装所需软件包,并清理软件包列表,每一行都以反斜杠结尾:

RUN DEBIAN_FRONTEND=noninteractive \
  apt-get update \
  && apt-get install -y python3 \
  && rm -rf /var/lib/apt/lists/*


以非根用户身份运行

默认情况下,Docker容器中运行root用户。通常情况下,root用户拥有比运行自定义应用程序时所需的权限更多,因此创建一个没有root特权的新用户可以提供更好的安全性。

useradd命令提供了一种非交互式的创建新用户的方式。这不要与adduser命令混淆,后者是useradd的一个高级封装。

在编辑所有配置文件并安装所有软件包之后,您可以创建一个名为apprunner的新用户:

RUN useradd -ms /bin/bash apprunner


然后将该用户设置为任何后续操作的默认用户:

USER apprunner


结论

可以使用基本的Ubuntu Docker镜像,除了安装所需的附加软件包外,几乎不需要自定义。但是,通过一些调整来限制安装可选软件包,在安装软件包后清理软件包列表,并创建具有有限权限来运行自定义应用程序的新用户,可以为您的自定义应用程序创建更小、更安全的镜像。

了解如何使用其他流行的容器镜像:

资源

祝您部署愉快!

推荐阅读: 10. let、const、var的区别

本文链接: 使用 Ubuntu Docker 镜像