使用 Ubuntu 的 Dockerfile:从入门到进阶的完整 Docker 镜像构建指南

.## 1. 介绍

目次

什么是 Docker 和 Dockerfile?

近年来,Docker 以其高效的方式快速流行起来,能够简化开发环境和应用部署。Docker 将应用及其依赖打包成一个称为“容器”的单元,使其能够在不同环境中保持一致运行。

要构建这些 Docker 容器,需要一个称为 Dockerfile 的蓝图。Dockerfile 是一个文本文件,定义了基础操作系统镜像、已安装的软件、环境变量以及其他配置细节。开发者可以使用它自动化构建自定义环境。

为什么使用 Ubuntu 作为基础镜像?

在创建 Dockerfile 时,第一步是选择基础操作系统镜像。在众多可选项中,Ubuntu 是最受欢迎的之一。Ubuntu 是基于 Debian 的 Linux 发行版,以易用性和灵活的环境设置著称,并拥有庞大的软件包生态系统支持。

基于 Ubuntu 的 Dockerfile 具有以下优势:

  • 丰富的官方和社区文档,学习曲线低
  • 使用 APT 轻松安装软件包和工具
  • 官方提供的轻量级、最小化镜像(如 ubuntu:20.04ubuntu:24.04

本文目的及目标读者

本文围绕关键词 “Dockerfile Ubuntu”,旨在以易于初学者理解的方式讲解如何创建基于 Ubuntu 的 Dockerfile。

内容涵盖从 Dockerfile 的基本结构到构建 Ubuntu 环境的逐步指令、如 Python 等应用环境的搭建示例,以及常见错误及其解决方案。

推荐阅读对象包括:

  • 第一次使用 Dockerfile 构建环境的用户
  • 想在 Ubuntu 上创建可复现开发环境的开发者
  • 希望深化理解、包括故障排查技巧的任何人

2. Dockerfile 的基本结构

Dockerfile 是什么以及它的作用是什么?

Dockerfile 类似于创建 Docker 镜像的配方。它定义了要使用的基础操作系统、要安装的软件以及如何配置环境。

通过基于该文件运行 docker build 命令,您可以轻松创建高度可复现的开发和运行时环境。

使用 Dockerfile 的好处:

  • 自动化环境搭建(无需手动重复)
  • 消除团队开发中的环境不一致
  • 易于集成到 CI/CD 流水线中

常用的 Dockerfile 指令

Dockerfile 由多条指令(指令集)组成。以下是最常用的一些指令。通过恰当组合它们,您可以构建基于 Ubuntu 的 Dockerfile。

InstructionDescription
FROMSpecifies the base Docker image (e.g., FROM ubuntu:24.04)
RUNExecutes shell commands, typically for installing packages
COPYCopies local files into the image
ADDSimilar to COPY, but also supports URLs and archive extraction
WORKDIRSets the working directory
ENVDefines environment variables
CMDDefines the default command executed at container startup (can be overridden)
ENTRYPOINTDefines a command that is always executed at container startup

最小化的基于 Ubuntu 的 Dockerfile 示例

下面是一个使用 Ubuntu 作为基础镜像的极简 Dockerfile 示例。

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y \
    curl \
    vim

CMD ["/bin/bash"]

该 Dockerfile 以 Ubuntu 24.04 为基础镜像,安装 curlvim 实用工具,并在容器启动时运行 Bash shell。

选择合适的 Ubuntu Tag

Ubuntu Docker 镜像发布在官方 Docker Hub 仓库中。虽然指定 ubuntu:latest 会使用最新版本,但强烈建议显式锁定版本

例如:

  • ubuntu:22.04(LTS:长期支持,侧重稳定性)
  • ubuntu:24.04(最新 LTS,侧重新特性)

根据您更看重稳定性还是新特性来选择相应的版本。

3. 实践:创建基于 Ubuntu 的 Dockerfile

在 Ubuntu 环境中安装所需软件包

.

当使用 Dockerfile 构建 Ubuntu 环境时,通常需要安装 额外的软件包。例如,以下工具在搭建开发环境时经常会用到:

  • curl :用于下载文件和测试 API
  • vim :轻量级文本编辑器
  • git :版本控制系统
  • build-essential :构建 C/C++ 程序的必备工具

要在 Dockerfile 中安装这些软件包,请使用 RUN 指令。

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y \
    curl \
    vim \
    git \
    build-essential

先运行 apt-get update,可以确保在安装前获取最新的软件包列表。

配置非交互式安装

在 Ubuntu 上,apt-get install 有时会要求用户输入。但在 Docker 构建过程中无法进行交互操作。为避免此问题,建议设置环境变量并启用 非交互模式

ENV DEBIAN_FRONTEND=noninteractive

这样可以抑制诸如地区或时区选择等提示,使安装过程顺利进行。

通过删除不必要的缓存来减小镜像体积

使用 APT 时,下载的临时文件(缓存)可能会残留在镜像中,导致最终镜像体积增大。可以通过如下方式删除缓存来减小镜像体积:

RUN apt-get update && apt-get install -y \
    curl \
    vim \
    && rm -rf /var/lib/apt/lists/*

将多个命令合并到同一个 RUN 指令中,也有助于避免不必要的镜像层增加。

编写 Dockerfile 的最佳实践

在实际开发环境中,以下 Dockerfile 最佳实践 被广泛推荐:

  • 尽可能合并 RUN 指令,以减少层数
  • 使用 ENV 明确指定版本和设置
  • 使用注释清晰描述每一步的目的
  • 通过 rm--no-install-recommends 避免留下不必要的文件

示例:

RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    git \
    && rm -rf /var/lib/apt/lists/*

这种做法可以得到 更轻量且更易维护的 Dockerfile

4. 构建并验证 Docker 镜像

从 Dockerfile 构建 Docker 镜像

Dockerfile 准备好后,下一步是 构建 Docker 镜像。使用 docker build 命令即可。 在包含 Dockerfile 的目录下运行以下命令:

docker build -t my-ubuntu-image .
  • -t 选项为镜像指定一个名称(标签)。在本例中,镜像名为 my-ubuntu-image
  • 点号( . )指代当前包含 Dockerfile 的目录。

Docker 会按顺序读取 Dockerfile 中的指令并相应地构建镜像。

检查已构建的 Docker 镜像

镜像成功构建后,可使用以下命令进行验证:

docker images

该命令会列出本地存储的 Docker 镜像及以下信息:

  • REPOSITORY(镜像名称)
  • TAG
  • IMAGE ID(唯一标识符)
  • CREATED(创建日期)
  • SIZE

示例:

REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
my-ubuntu-image   latest    abcd1234abcd   5 minutes ago    189MB

这表明镜像已正确注册。

运行 Docker 容器进行验证

为了确认创建的镜像能够正常工作,使用以下命令启动一个 Docker 容器

docker run -it my-ubuntu-image
  • -it 选项启动交互式终端会话。
  • 若成功,Bash 提示符会出现,表示已进入 Ubuntu 容器。

在容器内部,可以通过以下命令验证已安装的工具:

curl --version
vim --version

如果这些命令正常工作,则您的 Dockerfile 已正确配置。

清理未使用的镜像和容器

重复的构建和实验可能会在系统上留下未使用的 Docker 镜像和容器。建议定期使用以下命令进行清理:

  • 删除已停止的容器:
    docker container prune
    
  • 删除未使用的镜像:
    docker image prune
    
  • 删除所有未使用的数据(请谨慎使用):
    docker system prune
    

这些操作有助于节省磁盘空间并防止潜在问题

5. 高级:构建 Python 环境

在基于 Ubuntu 的 Dockerfile 中启用 Python

在使用 Dockerfile 构建 Ubuntu 环境时,添加Python 运行时环境可以支持广泛的使用场景,包括开发、测试和机器学习。虽然 Ubuntu 默认可能已经安装了 Python,但通常会显式配置,以便更好地管理版本和依赖包。

使用 APT 安装 Python

最简单的方法是通过 APT 包安装 Python。下面是一个示例:

FROM ubuntu:24.04

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

此方法提供了一个稳定的系统 Python 版本(如 Python 3.10 或 3.12,取决于 Ubuntu 发行版)。您也可以使用 pip 命令安装额外的 Python 包。

使用 pyenv 管理 Python 版本

如果需要特定的 Python 版本或想在多个版本之间切换,强烈推荐使用 pyenv

以下示例展示了如何在 Dockerfile 中使用 pyenv 安装 Python 3.11.6:

FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
    git \
    curl \
    make \
    build-essential \
    libssl-dev \
    zlib1g-dev \
    libbz2-dev \
    libreadline-dev \
    libsqlite3-dev \
    wget \
    llvm \
    libncurses5-dev \
    libncursesw5-dev \
    xz-utils \
    tk-dev \
    libffi-dev \
    liblzma-dev \
    && rm -rf /var/lib/apt/lists/*

# Install pyenv
RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv

ENV PYENV_ROOT="$HOME/.pyenv"
ENV PATH="$PYENV_ROOT/bin:$PATH"

RUN echo 'eval "$(pyenv init --path)"' >> ~/.bashrc

# Install a specific Python version
RUN pyenv install 3.11.6 && pyenv global 3.11.6

此配置提供了灵活且可控的 Python 环境。

使用 requirements.txt 管理包

大多数实际项目都需要多个 Python 库。这些依赖通常通过 requirements.txt 文件进行管理。

首先,在项目根目录创建一个 requirements.txt 文件:

flask==2.3.2
requests>=2.25.1
pandas

然后在 Dockerfile 中引用它,如下所示:

COPY requirements.txt /app/requirements.txt
WORKDIR /app

RUN pip install --no-cache-dir -r requirements.txt

这样可以一次性安装所有必需的库,显著提升环境的可复现性。

最佳实践

  • 使用 Python 时,创建 virtualenvvenv 虚拟环境有助于避免依赖冲突。
  • 使用 --no-cache-dir 等缓存抑制选项可以减小 Docker 镜像体积。
  • 在安装包之前运行 pip install --upgrade pip 可以帮助避免安装错误。

6. 常见问题与故障排除

权限错误

示例:

Permission denied

此错误通常发生在复制的文件缺少执行权限,或文件所有者与执行用户配置不当时。

解决方案:

  • 使文件可执行:
    RUN chmod +x script.sh
    
  • 如有必要,修改文件所有者:
    RUN chown root:root /path/to/file
    

未找到包或安装失败

示例:

E: Unable to locate package xxx

produce final.此错误通常发生在未执行 apt-get update 或软件包名称不正确的情况下。

解决方案:

  • 在安装软件包之前始终运行 apt-get update
    RUN apt-get update && apt-get install -y curl
    
  • 验证软件包名称并检查拼写错误

与网络相关的错误

示例:

Temporary failure resolving 'deb.debian.org'

此错误表明在构建过程中出现 DNS 解析问题。

解决方案:

  • 重启 Docker 守护进程可能会解决此问题:
    sudo systemctl restart docker
    
  • 通过在 /etc/docker/daemon.json 中添加 DNS 服务器来检查 Docker DNS 设置:
    {
      "dns": ["8.8.8.8", "8.8.4.4"]
    }
    

使用过期缓存进行构建

Docker 使用 基于层的缓存 来加速构建。因此,对 Dockerfile 的更改可能不会立即生效。

解决方案:

  • 在不使用缓存的情况下重新构建:
    docker build --no-cache -t my-image .
    

容器立即退出或启动命令未运行

原因:

  • CMDENTRYPOINT 中指定的命令存在错误
  • 在非交互模式下使用 CMD ["/bin/bash"] 会导致容器立即退出

解决方案:

  • 以调试模式启动容器:
    docker run -it my-image /bin/bash
    
  • 了解 CMDENTRYPOINT 的区别并适当使用它们

通过遇到并解决这些问题,您的 Dockerfile 设计技能将稳步提升。出现错误时,请仔细阅读错误信息并确定是哪条指令和哪一层导致了问题。

7. 总结

创建基于 Ubuntu 的 Dockerfile 的关键要点

本文提供了关于如何 使用 Dockerfile 构建 Ubuntu 环境 的逐步说明,涵盖了基础和高级主题。让我们回顾关键要点:

  • 了解 Dockerfile 基础 是第一步。FROMRUNCMDENV 等指令实现了环境的自动化创建。
  • Ubuntu 是一个稳定且灵活的基础镜像。其庞大的软件包生态、广泛的用户群体以及 LTS 发行版使其非常适合开发环境。
  • 实用的软件包管理 允许安装所需的工具和库。正确使用 apt-get、缓存清理以及非交互式安装至关重要。
  • 构建实用环境(如 Python) 完全由 Dockerfile 支持。pyenvpiprequirements.txt 等工具确保可复现的设置。
  • 故障排除技能直接影响系统的稳定运行。了解权限、网络以及构建缓存行为可显著提升生产力。

Dockerfile 学习的下一步

当您熟练使用 Dockerfile 后,可以将技能扩展到测试和生产部署。考虑探索以下主题:

  • 使用 Docker Compose 管理多容器部署
  • CI/CD 工具(如 GitHub Actions 和 GitLab CI)集成进来
  • 使用 Kubernetes 等容器编排平台

官方文档和参考链接

8. 常见问题解答(FAQ)

Q1. 在 Dockerfile 中应选择哪个 Ubuntu 版本?

A1. 在大多数情况下,推荐选择 LTS(长期支持) 发行版以获得稳定性和长期维护。诸如 ubuntu:22.04ubuntu:20.04 等版本被广泛使用,并提供五年支持。

如果需要最新的软件包或语言版本,可以选择更新的发行版,如 ubuntu:24.04,但建议进行充分测试。

Q2. 为什么 apt-get install 报告 “package not found”?

.A2. 最常见的原因是事先未运行 apt-get update。如果不更新软件包列表,APT 将无法找到请求的包。

Correct example:

正确示例:

RUN apt-get update && apt-get install -y curl

同时确保软件包名称正确且未被弃用(例如,使用 python3 而不是 python)。

Q3. How do I set environment variables in a Dockerfile?

Q3. 如何在 Dockerfile 中设置环境变量?

A3. 使用 ENV 指令定义环境变量,这些变量在构建阶段和容器运行时均可用。

Example:

示例:

ENV DEBIAN_FRONTEND=noninteractive

这通常用于在 APT 安装期间抑制交互式提示。环境变量也对应用配置和 API 密钥等很有用。

Q4. What is the difference between CMD and ENTRYPOINT?

Q4. CMDENTRYPOINT 有何区别?

A4. 两者都指定容器启动时执行的命令,但行为不同。

ItemCMDENTRYPOINT
OverridableCan be overridden by docker runGenerally not overridden (treated as fixed command)
Use CaseDefine a default commandDefine a command that must always run

Example:

示例:

CMD ["python3", "app.py"]
# vs
ENTRYPOINT ["python3"]
CMD ["app.py"]

在后者的情况下,你可以使用 docker run my-image another_script.py 传递参数。

Q5. Why are my Dockerfile changes not reflected?

Q5. 为什么我的 Dockerfile 更改没有生效?

A5. Docker 使用构建缓存,即使编辑了 Dockerfile,也可能导致未更改的层被复用。

Solution:

解决方案:

docker build --no-cache -t my-image .

这会强制完整重建,确保所有更改都被应用。

年収訴求