从零定制Docker镜像:基于CentOS 7.9配置Yum源并部署Nginx

发布时间:2026/7/28 19:02:38

从零定制Docker镜像:基于CentOS 7.9配置Yum源并部署Nginx 在实际容器化开发和运维工作中我们经常遇到一个核心需求如何将一个标准的操作系统镜像快速定制成一个包含特定软件和配置的、可直接部署服务的应用镜像。很多初学者会直接进入容器内部通过yum install安装软件但这种方式创建的容器状态是临时的无法复用。Docker 的核心优势在于通过 Dockerfile 实现构建过程的自动化与版本化从而生成可重复、可移植的镜像。本文将以一个典型的 Linux 服务部署场景为例手把手带你完成从零定制一个简单 Docker 镜像的全过程。我们将以 CentOS 7.9 为基础镜像目标是在镜像内配置一个可用的 Yum 软件仓库并成功安装并部署一个常用服务例如 Nginx。通过这个实践你将清晰理解 Dockerfile 的编写逻辑、镜像构建的步骤以及如何验证容器内的服务状态。无论你是刚开始接触 Docker还是希望巩固镜像定制的基本功这篇文章都将提供一条可复现的路径。1. 理解 Docker 镜像定制从容器临时操作到 Dockerfile 固化在深入操作之前必须厘清一个关键概念我们最终要交付的是一个“镜像”Image而不是一个手动配置好的“容器”Container。容器是镜像的运行实例你可以进入一个运行中的容器随意安装软件、修改配置但这些改动只存在于当前这个容器实例的生命周期内。一旦容器被删除所有改动都会丢失。Dockerfile 是解决这个问题的核心。它是一个文本文件包含了一系列的指令Instruction每一条指令都会在镜像构建过程中创建一个新的“层”Layer。这些指令层叠起来最终形成一个完整的、只读的镜像。当你运行docker build命令时Docker 引擎会逐行执行 Dockerfile 中的指令并缓存每一层的结果。这种分层机制使得镜像构建高效且可复用。对于我们的目标——在 CentOS 镜像中配置 Yum 源并安装服务如果只在容器内操作步骤大致是启动一个基础 CentOS 容器。进入容器备份旧的 Yum 源配置文件。下载并替换为国内镜像源如阿里云、清华源以加速下载。执行yum install -y nginx安装服务。配置服务并启动。而使用 Dockerfile我们需要将这些手动步骤翻译成 Dockerfile 指令例如RUN、COPY、WORKDIR等从而实现自动化构建。最终我们通过docker build -t my-nginx:1.0 .这样的命令就能生成一个名为my-nginx、标签为1.0的镜像。任何人拿到这个 Dockerfile 和构建命令都能生成一模一样的镜像这就是“基础设施即代码”思想在容器领域的体现。2. 环境准备与项目初始化在开始编写 Dockerfile 之前需要确保你的开发环境已经就绪。我们将在一个干净的目录中完成所有工作。2.1 宿主机环境要求与验证首先你需要一台安装了 Docker 的 Linux 或 macOS 机器Windows 用户可以使用 WSL2 或 Docker Desktop。通过以下命令验证 Docker 是否已正确安装并运行# 检查 Docker 客户端和服务端版本 docker --version docker-compose --version # 如果用到 Compose # 更详细地查看 Docker 系统信息确认服务状态 docker info # 运行一个测试容器验证 Docker 引擎功能是否正常 docker run hello-world如果hello-world容器能成功运行并输出欢迎信息说明 Docker 环境基本正常。接下来为我们的镜像定制项目创建一个独立的工作目录这有助于管理构建上下文Build Context。# 创建一个项目目录并进入 mkdir -p ~/projects/custom-centos-nginx cd ~/projects/custom-centos-nginx2.2 规划镜像内容与 Dockerfile 结构在动手写 Dockerfile 之前先明确我们要构建的镜像包含哪些内容基础镜像选择centos:7.9.2009。选择特定版本而非centos:latest是生产环境的最佳实践可以避免因基础镜像版本自动升级带来的不可预测行为。Yum 仓库配置将 CentOS 默认的国外源替换为国内镜像源如阿里云以大幅提升软件包下载速度。目标服务安装并配置 Nginx这是一个轻量级 Web 服务器非常适合作为演示。容器行为定义当容器启动时自动运行 Nginx。对应的 Dockerfile 指令规划如下表步骤手动操作Dockerfile 指令目的与说明1选择基础系统FROM centos:7.9.2009指定构建的起点2配置 Yum 源RUN(执行命令备份和替换源文件)加速后续软件安装3安装 NginxRUN yum install -y nginx安装主服务软件包4暴露端口EXPOSE 80声明容器运行时监听的网络端口5启动命令CMD [nginx, -g, daemon off;]定义容器启动时执行的默认命令3. 编写 Dockerfile 定制镜像现在我们在项目目录中创建 Dockerfile 并逐步实现上述规划。3.1 创建 Dockerfile 并指定基础镜像使用文本编辑器如 Vim、Nano 或 VS Code创建名为Dockerfile的文件注意没有后缀名。# Dockerfile # 使用官方 CentOS 7.9 特定版本作为基础镜像确保环境一致性 FROM centos:7.9.2009 # 设置镜像的作者信息元数据非必需 LABEL maintaineryour-emailexample.comFROM指令必须是 Dockerfile 的第一条有效指令除了ARG。它定义了构建过程的基础层。3.2 配置国内 Yum 镜像源CentOS 7 默认的 Yum 源速度可能较慢。我们将使用阿里云的镜像源进行替换。这一步需要在容器内执行 shell 命令因此使用RUN指令。# 配置 Yum 仓库为阿里云镜像加速软件安装 RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup \ curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo \ sed -i -e /mirrors.cloud.aliyuncs.com/d -e /mirrors.aliyuncs.com/d /etc/yum.repos.d/CentOS-Base.repo \ yum clean all \ yum makecache指令详解RUN在构建过程中于当前镜像层之上执行命令并提交结果。每一条RUN都会创建一个新的镜像层。将多个命令串联在一个RUN指令中。这是一个重要的最佳实践。Docker 镜像的每一层都是只读的减少RUN指令的数量可以有效减少镜像的层数从而缩小最终镜像的体积。如果分多条RUN写每条都会增加一层。yum clean all yum makecache清理旧的缓存并生成新的元数据缓存确保后续安装使用新的镜像源。注意网络搜索材料中提到了检查内核版本和下载 Yum 源但那是在宿主机上安装 Docker 引擎的步骤与我们在容器内配置 Yum 仓库是两件不同的事情切勿混淆。本文的RUN指令是在构建镜像时在未来的容器内部环境中执行的。3.3 安装并初步配置 Nginx配置好高速源后安装 Nginx 就非常简单了。# 安装 Nginx RUN yum install -y nginx # 可选创建一个简单的自定义首页替换 Nginx 默认页面 RUN echo h1Hello, Docker! This is a custom CentOS with Nginx./h1 /usr/share/nginx/html/index.html第一个RUN使用yum install -y nginx安装软件包。-y参数表示自动确认安装避免构建过程因等待用户输入而挂起。 第二个RUN创建了一个简单的 HTML 文件覆盖 Nginx 的默认欢迎页这样当我们访问容器时能立刻看到定制化的内容便于验证。3.4 定义容器运行时行为安装完成后我们需要告诉 Docker 这个镜像运行时应该做什么。# 声明容器运行时对外暴露的端口号 EXPOSE 80 # 设置容器启动时执行的默认命令 CMD [nginx, -g, daemon off;]指令详解EXPOSE 80这是一个元数据指令用于声明容器内的应用程序将监听 80 端口。它并不会自动在宿主机上打开端口映射实际的端口映射需要在docker run时通过-p参数指定。CMD [nginx, -g, daemon off;]指定容器启动时的默认执行命令。这里以“前台进程”模式启动 Nginxdaemon off;。这是关键点Docker 容器需要有一个前台进程持续运行如果进程退出容器就会停止。Nginx 默认以守护进程daemon模式启动会立即在后台运行并退出启动进程这会导致 Docker 容器启动后立刻退出。使用-g daemon off;让 Nginx 保持在前台运行。至此一个完整的 Dockerfile 就编写完成了。完整内容如下# 定制 CentOS 7.9 并部署 Nginx 的 Dockerfile FROM centos:7.9.2009 LABEL maintainerdevexample.com # 1. 配置国内 Yum 源 (阿里云) RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup \ curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo \ sed -i -e /mirrors.cloud.aliyuncs.com/d -e /mirrors.aliyuncs.com/d /etc/yum.repos.d/CentOS-Base.repo \ yum clean all \ yum makecache # 2. 安装 Nginx 并创建自定义首页 RUN yum install -y nginx \ echo h1Hello, Docker! This is a custom CentOS with Nginx./h1 /usr/share/nginx/html/index.html # 3. 声明暴露端口和定义启动命令 EXPOSE 80 CMD [nginx, -g, daemon off;]4. 构建镜像与运行验证有了 Dockerfile我们就可以将其构建成真正的 Docker 镜像并运行容器进行验证。4.1 执行镜像构建命令在包含 Dockerfile 的项目目录 (~/projects/custom-centos-nginx) 下执行构建命令# 构建镜像-t 参数用于给镜像打标签格式为 name:tag # 最后的 . 表示构建上下文为当前目录Docker 引擎会将该目录下的所有文件发送给守护进程因此不要放无关大文件 docker build -t my-centos-nginx:v1.0 .命令执行后Docker 守护进程会逐行解析 Dockerfile下载基础镜像如果本地没有并执行每一层指令。你会看到类似下面的输出Sending build context to Docker daemon 2.048kB Step 1/5 : FROM centos:7.9.2009 7.9.2009: Pulling from library/centos Digest: sha256:... Status: Downloaded newer image for centos:7.9.2009 --- a6d4c6c1a6ec Step 2/5 : LABEL maintainerdevexample.com --- Running in abcd1234 --- bcde2345 Step 3/5 : RUN mv /etc/yum.repos.d/CentOS-Base.repo ... yum makecache --- Running in cdef3456 ... Complete! --- 7890abcd Step 4/5 : RUN yum install -y nginx ... --- Running in defg4567 ... Installed: nginx.x86_64 1:1.20.1-9.el7 Complete! --- 8901bcde Step 5/5 : CMD [nginx, -g, daemon off;] --- Running in efgh5678 --- 9012cdef Successfully built 9012cdef Successfully tagged my-centos-nginx:v1.0构建成功后使用docker images查看本地镜像列表应该能看到新构建的my-centos-nginx镜像。docker images | grep my-centos-nginx4.2 运行容器并验证服务现在从我们自定义的镜像启动一个容器。# 运行容器 # -d: 后台运行 # -p 8080:80: 将宿主机的 8080 端口映射到容器的 80 端口 # --name my-web: 给容器起一个名字便于管理 docker run -d -p 8080:80 --name my-web my-centos-nginx:v1.0运行后可以通过以下命令检查容器状态# 查看正在运行的容器 docker ps # 应该能看到 my-web 容器状态为 Up # 查看容器日志确认 Nginx 启动无报错 docker logs my-web最关键的一步是验证服务是否可达。Nginx 正在容器内的 80 端口监听我们通过宿主机的 8080 端口访问。# 方法1使用 curl 命令如果宿主机有 curl http://localhost:8080 # 方法2直接在浏览器中访问 http://宿主机IP:8080如果一切正常curl命令会返回我们之前写入的 HTML 内容h1Hello, Docker! This is a custom CentOS with Nginx./h1。浏览器访问也会显示这个标题。4.3 进入容器内部检查为了更深入地验证我们的构建结果可以进入运行中的容器内部检查 Yum 源和已安装的软件。# 使用 exec 命令在运行中的容器内启动一个交互式 shell docker exec -it my-web /bin/bash进入容器后执行以下检查命令# 检查 Yum 源是否已替换为阿里云 cat /etc/yum.repos.d/CentOS-Base.repo | grep -i aliyun # 检查 Nginx 是否已安装且版本正确 nginx -v # 检查 Nginx 服务进程 ps aux | grep nginx # 检查我们创建的自定义首页 cat /usr/share/nginx/html/index.html完成检查后输入exit退出容器。5. 常见问题排查与优化实践在构建和运行自定义镜像的过程中你可能会遇到一些问题。下面列出一些典型场景及其解决方法。5.1 构建阶段常见问题问题现象可能原因检查与解决方式docker build失败提示Unable to find image ‘centos:7.9.2009’ locallyDocker 无法从配置的仓库拉取基础镜像。1. 检查网络连接。2. 运行docker pull centos:7.9.2009手动拉取看是否有更详细的错误信息。3. 检查 Docker 守护进程是否运行 (systemctl status docker)。docker build在RUN yum install步骤卡住或极慢。1. 容器内 Yum 源仍是国外源网络慢。2. Dockerfile 中配置国内源的命令执行失败。1. 进入构建临时容器检查在RUN指令前加RUN cat /etc/yum.repos.d/CentOS-Base.repo查看源文件内容。2. 确保配置源的curl命令能成功下载.repo文件网络搜索材料中提供的阿里云源地址是有效的。构建成功但镜像体积异常巨大。1. 每个RUN指令都产生一层且未清理缓存。2. 构建上下文 (.) 包含了大量不必要的文件。1.合并 RUN 指令将相关的yum install、yum clean all等命令用连接在一个RUN中。2.清理缓存在安装命令最后加上 yum clean all。3.使用.dockerignore文件在项目根目录创建该文件排除node_modules,.git, 日志等不参与构建的文件。COPY或ADD指令失败本文未使用但常见。要复制的文件在构建上下文中不存在。确保docker build命令最后的路径构建上下文包含了你要复制的文件。5.2 运行阶段常见问题问题现象可能原因检查与解决方式容器启动后立即退出 (docker ps看不到)。最常见原因容器内没有前台进程。例如Nginx 以默认的守护进程模式启动后主进程退出。1.docker logs my-web查看日志通常无报错。2. 确保 Dockerfile 的CMD是以前台模式启动应用如 Nginx 使用nginx -g “daemon off;”。docker run时报错port is already allocated。宿主机上 8080 端口已被其他程序占用。1. 更改映射端口例如-p 8081:80。2. 在宿主机使用 netstat -tlnp访问http://localhost:8080连接被拒绝。1. 容器没有正常运行。2. 端口映射错误。3. 容器内防火墙或 SELinux 阻止CentOS 镜像默认可能开启。1.docker ps确认容器状态为Up。2.docker port my-web查看容器的端口映射情况。3. 在 Dockerfile 中安装服务后可以尝试关闭防火墙RUN yum install -y nginx systemctl disable firewalld(仅用于学习环境生产环境需谨慎)。进入容器后无法使用systemctl命令。Docker 容器不是完整的操作系统通常不运行 Systemd 这类初始化系统。在容器内直接使用服务的二进制命令启动如nginx。这正是我们在CMD中直接调用nginx命令的原因。5.3 镜像优化与生产环境建议我们构建的镜像是一个可用的起点但为了用于开发测试甚至生产环境还需要考虑以下优化点使用更小的基础镜像centos:7.9.2009体积较大约 200MB。可以考虑使用alpine仅 5MB或debian:bullseye-slim等更精简的镜像作为基础能显著减少镜像拉取时间和磁盘占用。但需要注意软件包管理命令apkvsapt和库的差异。多阶段构建Multi-stage Build如果你的应用需要编译如 Golang、Java可以在一个大的“构建镜像”中完成编译然后将编译好的二进制文件复制到一个干净的“运行镜像”中。这可以避免将编译工具、源代码等冗余文件打包进最终镜像。非 root 用户运行默认情况下容器内的进程以 root 用户运行存在安全风险。应在 Dockerfile 中创建并切换到一个非 root 用户来运行应用。RUN groupadd -r nginx-group useradd -r -g nginx-group nginx-user USER nginx-user健康检查HEALTHCHECK添加HEALTHCHECK指令让 Docker 引擎能够判断容器内应用的健康状态这对于编排工具如 Kubernetes非常重要。HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost/ || exit 1环境变量与配置外置不要将配置文件硬编码在镜像里。使用ENV指令定义环境变量或通过docker run -e传入。对于配置文件可以使用VOLUME指令挂载宿主机目录或配置卷实现配置与镜像分离。通过以上步骤你不仅完成了一个从定制 Yum 源到安装服务的完整 Docker 镜像构建流程还掌握了排查常见问题的方法和面向生产环境的优化思路。下次当你需要为一个简单的应用制作 Docker 镜像时就可以遵循这个模式明确需求、编写 Dockerfile、构建测试、优化调整。

相关新闻