Dockerfile实战:从CentOS基础镜像到Nginx服务定制化部署

📅 2026/7/10 3:20:29
Dockerfile实战:从CentOS基础镜像到Nginx服务定制化部署
30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度在实际项目开发和测试环境搭建中我们经常需要基于一个基础镜像定制出符合特定业务需求的专属镜像。例如你可能需要一个预装了特定服务如 Nginx、MySQL和配置了内部 Yum 源的 CentOS 容器。直接进入容器安装软件虽然可行但无法固化成果容器销毁后一切都需要重来。通过 Dockerfile 定制镜像则能将环境构建过程代码化、版本化实现一次构建随处运行。本文将围绕一个典型的运维开发场景展开从拉取一个干净的 CentOS 7.9 基础镜像开始逐步编写 Dockerfile在构建镜像的过程中为其配置一个可用的本地 Yum 仓库并安装部署一个常用服务如 Nginx作为示例。通过这个过程你将掌握 Docker 镜像定制的核心流程理解 Dockerfile 指令的用法并学会处理容器内软件安装的依赖问题。最终你将得到一个包含 Nginx 服务和自定义 Yum 配置的、可随时启动的标准化镜像。1. 理解 Docker 镜像定制与容器内软件管理在深入操作之前需要厘清几个核心概念及其在本次实践中的角色。1.1 Docker 镜像不可变的构建模板Docker 镜像是一个轻量级、可执行的独立软件包它包含运行某个软件所需的所有内容代码、运行时、库、环境变量和配置文件。镜像是分层的、只读的。我们无法直接修改一个已存在的镜像而是通过在其基础上叠加新的层来创建新的镜像。本次实践的目标就是基于centos:7.9.2009这个官方镜像叠加我们自己的配置层Yum 仓库和应用层Nginx生成一个新的镜像。1.2 Dockerfile构建镜像的蓝图Dockerfile 是一个文本文件里面包含了一条条指令Instruction每一条指令构建一层。Docker 引擎通过读取 Dockerfile 中的指令来自动化构建镜像。它是实现环境标准化和持续集成的关键。我们将通过编写一个 Dockerfile 来定义所有构建步骤。1.3 容器内的 Yum 仓库解决离线与加速问题在容器内使用yum install命令安装软件默认会连接互联网上的公共仓库。但在某些隔离环境如内网、无外网访问权限的容器或为了追求更快的安装速度我们需要配置本地或内部的 Yum 仓库。这通常涉及将仓库的.repo文件放置到/etc/yum.repos.d/目录下。在 Dockerfile 构建过程中配置仓库可以确保基于此镜像创建的所有容器都拥有相同的软件源环境。1.4 容器与宿主机文件系统理解卷与拷贝容器拥有自己独立的文件系统命名空间。在 Dockerfile 构建阶段我们可以使用COPY指令将宿主机上的文件如本地 RPM 包、repo 文件复制到镜像中。在容器运行时如果需要持久化数据或与宿主机交换文件则需要使用 Docker 卷Volume或绑定挂载Bind Mount。本次构建主要使用COPY指令。2. 环境准备与项目结构规划在开始编写 Dockerfile 之前需要确保环境就绪并规划好清晰的目录结构这有助于管理构建上下文和资源文件。2.1 宿主机环境要求你需要一个安装了 Docker 引擎的 Linux 或 Windows/macOS使用 Docker Desktop系统。通过以下命令验证 Docker 是否可用docker --version docker info2.2 创建项目目录与资源准备为项目创建一个独立目录所有相关文件都放在这里。这个目录在构建时将成为 Docker 的“构建上下文”。mkdir -p ~/docker-custom-image cd ~/docker-custom-image在这个目录下我们需要准备以下资源Dockerfile构建脚本的核心文件。本地 Yum 仓库文件例如一个指向阿里云或企业内部镜像站的centos7.repo文件。如果处于完全离线环境则需要准备包含所有 RPM 包的本地仓库目录但本次以配置网络仓库为例。需要预装的软件可以通过 Yum 在线安装无需提前下载。创建目录结构如下~/docker-custom-image/ ├── Dockerfile # 镜像构建定义文件 └── resources/ # 存放需要拷贝到镜像中的资源 └── centos7.repo # 自定义的 Yum 仓库配置文件2.3 编写自定义 Yum 仓库文件在resources目录下创建centos7.repo文件。这里以配置阿里云 CentOS 7 镜像源为例它比官方源速度更快。文件内容如下# resources/centos7.repo [base] nameCentOS-$releasever - Base - mirrors.aliyun.com baseurlhttps://mirrors.aliyun.com/centos/$releasever/os/$basearch/ gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [updates] nameCentOS-$releasever - Updates - mirrors.aliyun.com baseurlhttps://mirrors.aliyun.com/centos/$releasever/updates/$basearch/ gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [extras] nameCentOS-$releasever - Extras - mirrors.aliyun.com baseurlhttps://mirrors.aliyun.com/centos/$releasever/extras/$basearch/ gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 [epel] nameExtra Packages for Enterprise Linux 7 - $basearch baseurlhttps://mirrors.aliyun.com/epel/7/$basearch gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/epel/RPM-GPG-KEY-EPEL-7注意如果你身处企业内部网络需要将baseurl替换为内部镜像服务器的地址。离线环境则需要搭建本地 HTTP 或文件系统仓库并相应修改baseurlfile:///path/to/local/repo。3. 编写 Dockerfile从基础镜像到服务部署Dockerfile 的每一行指令都会生成一个镜像层。合理的指令顺序可以充分利用 Docker 的构建缓存提升构建速度。我们将按逻辑顺序编写。3.1 指定基础镜像与维护者信息第一行必须是FROM指令指定构建的基石。我们选择体积相对较小的centos:7.9.2009作为基础镜像。LABEL指令用于添加元数据。# Dockerfile # 使用官方 CentOS 7.9 作为基础镜像指定版本以避免后续更新导致的不兼容 FROM centos:7.9.2009 # 设置镜像的维护者信息可选 LABEL maintaineryour-emailexample.com LABEL descriptionCustom CentOS 7.9 with internal yum repo and Nginx pre-installed.3.2 配置系统环境与 Yum 仓库在安装任何软件之前先配置好系统环境尤其是 Yum 仓库。我们做以下几件事清理可能存在的默认仓库配置文件避免冲突。将我们准备好的自定义仓库文件复制到容器内相应目录。更新 Yum 缓存使新仓库生效。安装一些常用的基础工具如vimnet-toolswget。# 设置工作目录后续的 RUN/COPY 指令若使用相对路径则基于此目录 WORKDIR /tmp # 1. 备份并移除默认的仓库文件谨慎操作仅用于实验环境 # 在实际生产镜像中可能更倾向于覆盖而非删除。 RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2/dev/null || true # 2. 复制自定义的仓库配置文件到容器内 COPY resources/centos7.repo /etc/yum.repos.d/ # 3. 清理旧缓存并生成新缓存验证仓库配置是否有效 RUN yum clean all yum makecache fast # 4. 安装基础工具包 RUN yum install -y vim-enhanced net-tools wget curl telnet tree注意RUN mv ... 2/dev/null || true这行命令的目的是如果文件不存在命令不会报错导致构建失败。这是一种防御性写法。3.3 安装并配置目标服务NginxYum 仓库配置成功后就可以安装我们需要的服务了。这里以 Nginx 为例。我们不仅安装软件还进行一些基本的初始配置。# 5. 安装 Nginx RUN yum install -y nginx # 6. 对 Nginx 进行基本配置可选 # 例如创建一个自定义的欢迎页面替换默认的 index.html RUN echo h1Hello from Custom Docker Image with Nginx!/h1pYum repo and Nginx are ready./p /usr/share/nginx/html/index.html # 7. 暴露 Nginx 默认的 HTTP 端口 EXPOSE 803.4 设置容器启动命令最后我们需要指定当基于这个镜像启动容器时默认执行什么命令。对于 Nginx 这类前台进程通常直接启动它。# 8. 设置容器启动时执行的命令 # 使用 nginx -g daemon off; 让 Nginx 在前台运行这是 Docker 容器的最佳实践 CMD [nginx, -g, daemon off;]完整的Dockerfile内容如下# Dockerfile FROM centos:7.9.2009 LABEL maintainerdevopsexample.com LABEL descriptionCentOS 7.9 with Aliyun Yum repo and Nginx. WORKDIR /tmp # 配置 Yum 仓库 RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2/dev/null || true COPY resources/centos7.repo /etc/yum.repos.d/ RUN yum clean all yum makecache fast # 安装基础工具和 Nginx RUN yum install -y vim net-tools wget nginx # 定制欢迎页 RUN echo h1Welcome to Custom Nginx Container/h1pBuilt from Dockerfile with custom Yum repo./p /usr/share/nginx/html/index.html EXPOSE 80 CMD [nginx, -g, daemon off;]4. 构建镜像与运行验证有了 Dockerfile 和资源文件就可以开始构建镜像并运行容器进行验证了。4.1 执行 Docker 构建命令在~/docker-custom-image目录下执行构建命令。-t参数用于给新镜像打上标签格式通常为名称:版本。最后的.表示使用当前目录作为构建上下文。docker build -t my-centos-nginx:1.0 .构建过程会逐条执行 Dockerfile 中的指令并在终端输出每一步的结果。如果网络通畅且仓库配置正确你会看到 Yum 成功缓存元数据并安装软件。4.2 验证镜像构建成功构建完成后使用docker images命令查看本地镜像列表应该能看到新构建的my-centos-nginx:1.0镜像。docker images | grep my-centos-nginx4.3 运行容器并测试服务现在基于新镜像启动一个容器。-d表示后台运行-p 8080:80将宿主机的 8080 端口映射到容器的 80 端口。docker run -d --name my-nginx-test -p 8080:80 my-centos-nginx:1.0使用docker ps查看容器是否正常运行docker ps4.4 验证服务与配置验证 Nginx 服务打开浏览器访问http://localhost:8080应该能看到我们在 Dockerfile 中定制的欢迎页面。验证 Yum 仓库配置进入容器内部检查仓库文件并测试 Yum 命令。# 进入容器 docker exec -it my-nginx-test /bin/bash # 查看 Yum 仓库配置 cat /etc/yum.repos.d/centos7.repo # 测试 Yum 命令例如搜索某个包 yum search iftop验证基础工具在容器内尝试使用vimifconfig来自 net-toolswget等命令确认它们已成功安装。4.5 清理测试容器测试完毕后停止并删除测试容器docker stop my-nginx-test docker rm my-nginx-test5. 关键指令详解与构建优化理解 Dockerfile 每条指令的细节和最佳实践能帮助你编写出更高效、更安全的镜像。5.1 指令深度解析指令作用与原理本次使用示例与说明FROM指定基础镜像必须是第一条非注释指令。所有后续操作都基于此镜像层。FROM centos:7.9.2009指定了明确的小版本避免了因latest标签变化带来的不确定性。COPY将宿主机构建上下文中的文件或目录复制到镜像内。COPY resources/centos7.repo /etc/yum.repos.d/。源路径是相对于构建上下文.的。RUN在镜像构建过程中执行命令并提交结果形成新层。常用于安装软件、配置环境。RUN yum install -y nginx。多个RUN指令应尽量合并以减少镜像层数。WORKDIR为后续的RUNCMDENTRYPOINTCOPYADD指令设置工作目录。WORKDIR /tmp。如果目录不存在会自动创建。EXPOSE声明容器运行时监听的网络端口。这是一个元数据实际映射需要在docker run时用-p指定。EXPOSE 80声明容器内 Nginx 监听 80 端口。CMD指定容器启动时的默认执行命令。一个 Dockerfile 只能有一个CMD。CMD [nginx, -g, daemon off;]使用exec格式推荐格式。5.2 构建缓存与层优化Docker 构建使用缓存。如果某一层及其之前的所有层没有变化Docker 会直接使用缓存极大加速构建。优化原则将变化频率低的指令放在前面如安装系统依赖。COPY resources/centos7.repo ...这类文件拷贝指令一旦centos7.repo文件内容变化其后的所有缓存都会失效。因此稳定的操作应前置。合并相关的RUN指令每一条RUN都会产生新层。可以用连接多个命令并用\换行保持可读性。# 优化前产生3层 RUN yum update -y RUN yum install -y package1 RUN yum install -y package2 package3 RUN yum clean all # 优化后产生1层且清理了缓存镜像更小 RUN yum update -y \ yum install -y package1 package2 package3 \ yum clean all \ rm -rf /var/cache/yum/*在我们的示例中安装基础工具和 Nginx 可以合并。5.3 生产环境镜像建议使用更小的基础镜像如alpine或针对特定语言的官方精简镜像如openjdk:11-jre-slim可以显著减少镜像体积和安全漏洞面。非 root 用户运行在 Dockerfile 中创建非 root 用户并使用USER指令切换以提升容器运行时的安全性。RUN groupadd -r nginx-group useradd -r -g nginx-group nginx-user USER nginx-user健康检查添加HEALTHCHECK指令让 Docker 引擎能够判断容器内应用的健康状态。HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost/ || exit 16. 常见问题排查与解决方案在构建和运行自定义镜像时你可能会遇到以下典型问题。6.1 构建阶段问题问题现象可能原因排查与解决Step X/XX : RUN yum install ...失败提示Could not resolve host或Cannot retrieve repository metadata。1. 容器构建时无法访问互联网。2. 自定义的.repo文件baseurl配置错误。3. 宿主机 DNS 配置问题。1. 检查宿主机网络确保构建环境可访问外网或内部镜像站。2. 进入resources/centos7.repo文件确认baseurl链接可访问用curl测试。3. 在 Dockerfile 中RUN命令前尝试添加RUN cat /etc/resolv.conf查看 DNS或使用--network参数指定构建网络。COPY failed: file not found in build contextCOPY指令指定的源文件在构建上下文中不存在。确认docker build命令最后的路径.是否正确以及COPY指令中的源路径是否相对于该上下文。确保resources/centos7.repo文件存在于构建上下文目录下。构建成功但镜像体积异常大。1. 每个RUN指令都产生新层且未清理缓存。2. 构建上下文中包含了不必要的文件如日志、git 历史。1. 合并RUN指令并在安装软件后执行清理缓存命令如yum clean all。2. 创建.dockerignore文件排除node_modules.git*.log等文件。6.2 运行阶段问题问题现象可能原因排查与解决容器启动后立即退出Exited。CMD或ENTRYPOINT指定的命令执行完毕或报错。对于 Nginx默认以守护进程启动会立即退出。确保CMD是让应用在前台运行的命令如nginx -g daemon off;。使用docker logs container_id查看容器日志获取错误信息。访问localhost:8080连接被拒绝。1. 容器没有成功启动。2. 端口映射错误-p参数宿主端口:容器端口。3. 容器内防火墙或 SELinux 阻止CentOS 镜像通常已禁用。1.docker ps确认容器状态是否为Up。2. 检查docker run的-p 8080:80是否正确并确认宿主机 8080 端口未被占用。3. 进入容器curl localhost:80测试内部是否可访问先排除容器内问题。容器内无法解析域名如ping baidu.com失败。容器使用的 DNS 配置有问题。检查宿主机的/etc/resolv.conf。运行容器时可指定 DNSdocker run --dns 8.8.8.8 ...。或在 Docker 守护进程配置中修改默认 DNS。6.3 Yum 特定问题GPG 密钥验证失败如果自定义仓库启用了gpgcheck1但gpgkey不可达会导致yum makecache或install失败。可以临时在 Dockerfile 中禁用 GPG 检查不推荐生产环境或确保gpgkey的 URL 可访问。仓库元数据缓存失败yum makecache fast失败。可以尝试先yum clean all再yum makecache。检查仓库配置文件语法确保baseurl中的变量如$releasever$basearch能被正确解析。7. 进阶实践与扩展方向掌握了基础镜像定制后你可以向以下几个方向深化实践。7.1 构建参数与多阶段构建使用ARG和ENVARG用于构建时传递变量如软件版本ENV设置容器运行时的环境变量。ARG NGINX_VERSION1.20.1 RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz ENV PATH/usr/local/nginx/sbin:$PATH多阶段构建适用于需要编译环境的场景。可以在一个阶段builder编译软件在另一个阶段只复制编译好的二进制文件得到更小的最终镜像。FROM golang:1.19 AS builder WORKDIR /app COPY . . RUN go build -o myapp . FROM alpine:latest COPY --frombuilder /app/myapp /usr/local/bin/myapp CMD [myapp]7.2 使用 Docker Compose 编排多容器服务当你的应用需要多个容器如 Web 服务器 数据库时使用 Docker Compose 可以一键管理。创建一个docker-compose.yml文件version: 3.8 services: web: build: . # 使用当前目录的 Dockerfile 构建镜像 ports: - 8080:80 volumes: - ./html:/usr/share/nginx/html # 挂载本地页面目录 depends_on: - db db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: example然后使用docker-compose up -d启动所有服务。7.3 推送镜像到仓库构建好的镜像可以推送到 Docker Hub、Harbor 等镜像仓库供其他环境拉取使用。# 1. 登录 Docker Hub docker login # 2. 为本地镜像打上符合仓库规范的标签 docker tag my-centos-nginx:1.0 yourusername/my-centos-nginx:1.0 # 3. 推送镜像 docker push yourusername/my-centos-nginx:1.07.4 为不同服务定制镜像你可以复用本文的流程定制不同服务的镜像。关键在于修改 Dockerfile 中的软件安装和配置部分。定制 Python 应用镜像基础镜像换为python:3.9-slim使用pip install -r requirements.txt安装依赖CMD启动gunicorn或python app.py。定制 Java 应用镜像基础镜像换为openjdk:11-jre-slimCOPY打包好的 JAR 文件CMD执行java -jar app.jar。定制数据库镜像通常直接使用官方镜像如mysql:5.7但可以通过 Dockerfile 初始化自定义的 SQL 脚本或配置文件。通过本次从配置 Yum 仓库到安装部署 Nginx 的完整实践你应该已经掌握了 Docker 镜像定制的核心方法。记住一个优秀的自定义镜像始于一个明确的需求、一个严谨的 Dockerfile 和一份对每一层构建目的的清晰认知。在后续的实践中多思考如何让镜像更小、更安全、更易于维护这将是你容器化技能提升的关键。 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度