.## 1. 介绍
- 1 2. Dockerfile 的基本结构
- 2 3. 实践:创建基于 Ubuntu 的 Dockerfile
- 3 4. 构建并验证 Docker 镜像
- 4 5. 高级:构建 Python 环境
- 5 6. 常见问题与故障排除
- 6 7. 总结
- 7 8. 常见问题解答(FAQ)
- 7.1 Q1. 在 Dockerfile 中应选择哪个 Ubuntu 版本?
- 7.2 Q2. 为什么 apt-get install 报告 “package not found”?
- 7.3 Q3. How do I set environment variables in a Dockerfile?
- 7.4 Q3. 如何在 Dockerfile 中设置环境变量?
- 7.5 Q4. What is the difference between CMD and ENTRYPOINT?
- 7.6 Q4. CMD 与 ENTRYPOINT 有何区别?
- 7.7 Q5. Why are my Dockerfile changes not reflected?
- 7.8 Q5. 为什么我的 Dockerfile 更改没有生效?
什么是 Docker 和 Dockerfile?
近年来,Docker 以其高效的方式快速流行起来,能够简化开发环境和应用部署。Docker 将应用及其依赖打包成一个称为“容器”的单元,使其能够在不同环境中保持一致运行。
要构建这些 Docker 容器,需要一个称为 Dockerfile 的蓝图。Dockerfile 是一个文本文件,定义了基础操作系统镜像、已安装的软件、环境变量以及其他配置细节。开发者可以使用它自动化构建自定义环境。
为什么使用 Ubuntu 作为基础镜像?
在创建 Dockerfile 时,第一步是选择基础操作系统镜像。在众多可选项中,Ubuntu 是最受欢迎的之一。Ubuntu 是基于 Debian 的 Linux 发行版,以易用性和灵活的环境设置著称,并拥有庞大的软件包生态系统支持。
基于 Ubuntu 的 Dockerfile 具有以下优势:
- 丰富的官方和社区文档,学习曲线低
- 使用 APT 轻松安装软件包和工具
- 官方提供的轻量级、最小化镜像(如
ubuntu:20.04和ubuntu: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。
| Instruction | Description |
|---|---|
FROM | Specifies the base Docker image (e.g., FROM ubuntu:24.04) |
RUN | Executes shell commands, typically for installing packages |
COPY | Copies local files into the image |
ADD | Similar to COPY, but also supports URLs and archive extraction |
WORKDIR | Sets the working directory |
ENV | Defines environment variables |
CMD | Defines the default command executed at container startup (can be overridden) |
ENTRYPOINT | Defines 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 为基础镜像,安装 curl 和 vim 实用工具,并在容器启动时运行 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:用于下载文件和测试 APIvim:轻量级文本编辑器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 时,创建
virtualenv或venv虚拟环境有助于避免依赖冲突。 - 使用
--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 .
容器立即退出或启动命令未运行
原因:
CMD或ENTRYPOINT中指定的命令存在错误- 在非交互模式下使用
CMD ["/bin/bash"]会导致容器立即退出
解决方案:
- 以调试模式启动容器:
docker run -it my-image /bin/bash
- 了解
CMD与ENTRYPOINT的区别并适当使用它们
通过遇到并解决这些问题,您的 Dockerfile 设计技能将稳步提升。出现错误时,请仔细阅读错误信息并确定是哪条指令和哪一层导致了问题。
7. 总结
创建基于 Ubuntu 的 Dockerfile 的关键要点
本文提供了关于如何 使用 Dockerfile 构建 Ubuntu 环境 的逐步说明,涵盖了基础和高级主题。让我们回顾关键要点:
- 了解 Dockerfile 基础 是第一步。
FROM、RUN、CMD、ENV等指令实现了环境的自动化创建。 - Ubuntu 是一个稳定且灵活的基础镜像。其庞大的软件包生态、广泛的用户群体以及 LTS 发行版使其非常适合开发环境。
- 实用的软件包管理 允许安装所需的工具和库。正确使用
apt-get、缓存清理以及非交互式安装至关重要。 - 构建实用环境(如 Python) 完全由 Dockerfile 支持。
pyenv、pip、requirements.txt等工具确保可复现的设置。 - 故障排除技能直接影响系统的稳定运行。了解权限、网络以及构建缓存行为可显著提升生产力。
Dockerfile 学习的下一步
当您熟练使用 Dockerfile 后,可以将技能扩展到测试和生产部署。考虑探索以下主题:
- 使用 Docker Compose 管理多容器部署
- 将 CI/CD 工具(如 GitHub Actions 和 GitLab CI)集成进来
- 使用 Kubernetes 等容器编排平台
官方文档和参考链接
8. 常见问题解答(FAQ)
Q1. 在 Dockerfile 中应选择哪个 Ubuntu 版本?
A1. 在大多数情况下,推荐选择 LTS(长期支持) 发行版以获得稳定性和长期维护。诸如 ubuntu:22.04 和 ubuntu: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. CMD 与 ENTRYPOINT 有何区别?
A4. 两者都指定容器启动时执行的命令,但行为不同。
| Item | CMD | ENTRYPOINT |
|---|---|---|
| Overridable | Can be overridden by docker run | Generally not overridden (treated as fixed command) |
| Use Case | Define a default command | Define 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 .
这会强制完整重建,确保所有更改都被应用。



