Docker实战:定制镜像、配置Yum源与容器内服务部署

🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度

这次我们来看 Docker 容器技术中几个非常核心的实战操作:如何定制一个简单的镜像、如何在容器内部配置 Yum 软件仓库,以及如何在容器内完成服务的安装与部署。对于需要在容器化环境中进行应用开发、测试或运维的工程师来说,掌握这些技能是摆脱“只会跑现成镜像”的关键一步。

本文的重点不是讲解 Docker 的复杂概念,而是提供一套可立即上手、能解决实际问题的操作流程。无论你是想将本地应用打包成镜像,还是在隔离的容器环境中模拟 CentOS 系统配置并部署服务(如 Nginx、MySQL),这篇文章都能提供清晰的指引。我们将从最基础的 Dockerfile 编写开始,到解决容器内无网络环境下的软件安装难题,最后完成一个服务的完整部署验证。

下面,我们将分步拆解这三个核心任务,并提供详细的命令和配置示例,确保你在自己的开发机上也能复现整个过程。

1. 核心能力速览

在深入细节之前,我们先通过一个表格快速了解本文涵盖的三个核心操作及其价值:

能力项 说明与目标
定制简单镜像 掌握使用 Dockerfile 将自定义应用或脚本打包成可重复部署的镜像。这是容器化自有应用的基础。
容器内配置 Yum 仓库 解决从官方基础镜像(如 centos:7 )启动的容器内无法直接使用 yum 安装软件的问题。重点在于配置本地或可用的 Yum 源。
容器内安装部署服务 在配置好环境的容器内,完成特定服务(如 Web 服务器、数据库)的安装、配置、启动和验证。这是模拟生产部署的闭环。
核心依赖 需要宿主机已安装 Docker Engine 或 Docker Desktop,并具备基本的 Linux 命令行操作知识。
资源占用 极低。主要占用磁盘空间(基础镜像和层缓存)和少量运行时内存,普通开发机即可完成。
产出物 自定义的 Docker 镜像、一个配置好软件源并可安装服务的容器环境、一套可复用的 Dockerfile 和配置脚本。
适合场景 本地开发环境搭建、CI/CD 流水线中的镜像构建、服务部署前的环境验证、学习 Docker 镜像构建原理。

2. 适用场景与使用边界

掌握定制镜像和在容器内配置环境的能力,主要适用于以下几类场景:

  1. 应用容器化 :你有一个用 Python、Node.js 或 Go 编写的应用程序,希望将其与运行环境一起打包,确保在任何装有 Docker 的机器上都能以相同的方式运行。
  2. 环境标准化与隔离 :需要快速创建一个干净的、特定版本(如 CentOS 7.9)的 Linux 环境来编译软件、测试安装脚本或复现问题,而不污染宿主机。
  3. 离线或内网环境部署 :在生产环境中,服务器可能无法访问互联网。你需要提前构建好包含所有依赖的镜像,或学会在容器内配置内部私有的 Yum 仓库。
  4. 学习与实验 :这是理解 Docker 镜像分层、构建上下文以及容器内部系统管理的最佳实践途径。

使用边界与注意事项:

  • 并非替代虚拟机 :对于需要完整操作系统特性、特殊内核模块或高性能持久化存储的场景,容器可能不是最佳选择。
  • 数据持久化 :容器内安装的服务,其数据(如数据库文件、日志)默认随容器删除而丢失。务必通过 -v 挂载卷或 Docker Volume 实现数据持久化。
  • 安全合规 :自定义镜像可能包含软件漏洞。建议基于官方最小化镜像(如 alpine centos:7 )构建,并定期更新基础镜像和软件包。从不可信的来源获取 Yum 仓库配置存在安全风险。
  • 镜像大小 :在 Dockerfile 中执行过多的 yum install 操作会导致镜像层臃肿。应合理安排命令顺序,并清理缓存(如 yum clean all )以优化最终镜像大小。

3. 环境准备与前置条件

开始操作前,请确保你的实验环境满足以下要求:

  1. 操作系统 :支持 Docker 的 Linux 发行版(如 Ubuntu、CentOS)、macOS 或 Windows 10/11。
  2. Docker 环境
    • Linux :已安装 Docker Engine。可通过 sudo docker --version 验证。
    • macOS/Windows :已安装 Docker Desktop 并处于运行状态。
  3. 网络连接 :首次拉取基础镜像和后续在容器内配置网络 Yum 源时需要互联网访问。对于离线配置部分,需提前下载好 RPM 包或仓库数据。
  4. 磁盘空间 :建议至少有 2GB 的可用磁盘空间,用于存储基础镜像和构建过程中的临时层。
  5. 权限 :在 Linux 上,非 root 用户需要加入 docker 用户组,或使用 sudo 来执行 Docker 命令。

验证 Docker 环境: 打开终端或命令提示符,执行以下命令,确认 Docker 可正常使用。

# 检查 Docker 版本和运行状态
docker --version
docker info

# 尝试运行一个测试容器
docker run --rm hello-world

如果最后一条命令能成功输出 “Hello from Docker!” 等欢迎信息,说明环境就绪。

4. 任务一:使用 Dockerfile 定制简单镜像

我们的第一个目标是创建一个自定义镜像。假设我们有一个简单的 Python 应用,它打印当前时间和主机名。

4.1 创建项目目录与文件 首先,在宿主机上创建一个工作目录,并编写应用脚本和 Dockerfile。

mkdir my-docker-app && cd my-docker-app

创建应用文件 app.py

#!/usr/bin/env python3
import socket
import datetime

if __name__ == "__main__":
    hostname = socket.gethostname()
    current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"[{current_time}] Hello from Docker container running on host: {hostname}")

创建 Dockerfile (注意没有后缀名):

# 使用官方 Python 3.9 运行时作为父镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 将当前目录下的文件复制到容器的 /app 目录下
COPY app.py .

# 定义容器启动时执行的命令
CMD ["python", "./app.py"]

4.2 构建自定义镜像 my-docker-app 目录下,执行构建命令。 -t 参数用于给镜像打标签。

docker build -t my-python-app:1.0 .

命令最后的 . 表示构建上下文是当前目录。Docker Daemon 会读取该目录下的 Dockerfile 并执行其中的指令。

4.3 运行并验证镜像 构建成功后,运行这个自定义镜像创建的容器。

docker run --rm my-python-app:1.0

你应该能看到类似 [2023-10-27 14:30:00] Hello from Docker container running on host: xxxxx 的输出。 --rm 参数表示容器停止后自动删除,便于清理。

至此,你已经完成了从编写应用、编写 Dockerfile 到构建和运行自定义镜像的完整流程。这是容器化任何应用的基础模式。

5. 任务二:为 CentOS 容器配置 Yum 仓库

许多官方基础镜像为了保持精简,移除了默认的 Yum 仓库配置或使用了不可用的仓库地址。这导致在容器内直接运行 yum install 会失败。我们将解决这个问题。

5.1 启动一个干净的 CentOS 7 容器 首先,我们进入一个交互式的容器内部查看问题。

docker run -it --rm --name centos-test centos:7 /bin/bash

执行上述命令后,终端会切换到容器内部。

5.2 诊断 Yum 问题 在容器内尝试安装一个软件,如 vim

yum install -y vim

你很可能会遇到错误,提示 “Cannot find a valid baseurl for repo: base/7/x86_64” 或类似信息,这表示容器无法连接到默认的镜像仓库。

5.3 配置可用的 Yum 源 退出容器(输入 exit )。我们将在宿主机上准备一个 Yum 源配置文件,然后在启动容器时将其挂载进去,或者在 Dockerfile 中直接添加。

方法一:启动时挂载本地仓库文件(适用于快速测试)

  1. 在宿主机上创建一个 Yum 源配置文件,例如使用阿里云的 CentOS 7 镜像源。
    # 在宿主机上执行
    cat > /tmp/centos7-aliyun.repo << 'EOF'
    [base]
    name=CentOS-$releasever - Base - mirrors.aliyun.com
    baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
    gpgcheck=1
    gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
    
    [updates]
    name=CentOS-$releasever - Updates - mirrors.aliyun.com
    baseurl=http://mirrors.aliyun.com/centos/$releasever/updates/$basearch/
    gpgcheck=1
    gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
    
    [extras]
    name=CentOS-$releasever - Extras - mirrors.aliyun.com
    baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/
    gpgcheck=1
    gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
    EOF
    
  2. 启动一个新的容器,并将该仓库文件挂载到容器内的 /etc/yum.repos.d/ 目录,覆盖原有配置。
    docker run -it --rm \
      -v /tmp/centos7-aliyun.repo:/etc/yum.repos.d/centos7-aliyun.repo \
      --name centos-with-repo \
      centos:7 /bin/bash
    
  3. 在容器内再次尝试安装软件。
    yum clean all        # 清理旧缓存
    yum makecache fast   # 创建新缓存
    yum install -y vim wget net-tools
    
    此时安装应该能够成功。

方法二:在 Dockerfile 中配置仓库(适用于构建固定环境的镜像) 如果你需要构建一个默认就配置好 Yum 源的镜像,可以在 Dockerfile 中操作。

FROM centos:7

# 备份原有的低效仓库文件
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

# 添加阿里云仓库配置文件
ADD centos7-aliyun.repo /etc/yum.repos.d/

# 清理并重建缓存,然后安装所需软件
RUN yum clean all && \
    yum makecache && \
    yum install -y vim wget net-tools

# 后续可以继续添加你的应用代码...

你需要将上面创建的 centos7-aliyun.repo 文件放在与 Dockerfile 相同的目录下。这种方法将仓库配置固化到了镜像层中。

6. 任务三:在容器内安装部署服务

现在,我们综合前两个任务,在一个配置好 Yum 源的 CentOS 容器中,完成一个服务(以 Nginx 为例)的安装、配置、启动和访问验证。

6.1 编写用于部署服务的 Dockerfile 我们将创建一个新的 Dockerfile,它基于 CentOS 7,配置 Yum 源,安装 Nginx,暴露端口,并设置启动命令。

# 文件名:Dockerfile.nginx
FROM centos:7

# 配置 Yum 仓库(使用内联方式,避免额外文件)
RUN 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

# 安装 Nginx
RUN yum install -y nginx

# 创建用于存放自定义配置的目录(可选)
RUN mkdir -p /etc/nginx/conf.d/custom

# 暴露 Nginx 默认的 HTTP 端口
EXPOSE 80

# 设置容器启动时运行 Nginx,并以前台模式运行
CMD ["nginx", "-g", "daemon off;"]

6.2 构建 Nginx 服务镜像

docker build -f Dockerfile.nginx -t my-nginx-centos:1.0 .

6.3 运行容器并验证服务 运行容器,并将容器的 80 端口映射到宿主机的 8080 端口。

docker run -d --name my-nginx -p 8080:80 my-nginx-centos:1.0
  • -d : 后台运行。
  • --name : 指定容器名称。
  • -p 8080:80 : 端口映射,宿主机 8080 -> 容器 80。

6.4 验证服务是否正常运行

  1. 检查容器状态
    docker ps | grep my-nginx
    
    应看到容器状态为 “Up”。
  2. 查看容器日志
    docker logs my-nginx
    
    通常无错误信息。
  3. 访问服务
    • 在宿主机浏览器中访问 http://localhost:8080
    • 或使用 curl 命令:
      curl http://localhost:8080
      
    如果看到 Nginx 的欢迎页面或相关的 HTML 输出,说明服务部署成功。

6.5 进入容器进行管理 你可以进入正在运行的容器内部,查看进程、修改配置(测试用)等。

docker exec -it my-nginx /bin/bash
# 进入容器后
ps aux | grep nginx
cat /etc/nginx/nginx.conf

退出容器使用 exit

7. 接口 API 与批量任务

虽然本文示例是一个 Web 服务器,但 Docker 容器化部署的模式适用于任何服务,包括提供 API 的后端应用。核心思路是一致的:

  1. 编写 Dockerfile :定义基础环境、安装依赖(如 Python pip, Node.js npm)、复制代码、设置启动命令(如 python app.py , node server.js )。
  2. 暴露端口 :在 Dockerfile 中使用 EXPOSE 指令声明应用监听的端口(如 EXPOSE 5000 )。
  3. 运行容器 :使用 -p 参数将容器端口映射到宿主机(如 -p 5000:5000 )。
  4. API 测试 :容器启动后,即可通过宿主机的映射端口访问 API。

对于 批量任务 (如定时数据处理脚本),通常不需要长期运行的服务。你可以:

  • 构建一个包含任务脚本和所有依赖的镜像。
  • 使用 docker run --rm <image-name> <command> 来一次性执行任务,任务完成后容器自动删除。
  • 结合宿主机 crontab 或 Kubernetes CronJob 实现定时调度。

8. 资源占用与性能观察

Docker 容器本身开销很小。资源占用主要取决于你运行的应用程序和基础镜像。

  • 观察容器资源使用

    # 查看所有容器的实时资源占用(CPU,内存,网络IO等)
    docker stats
    
    # 查看特定容器的详细信息,包括资源限制
    docker inspect my-nginx | grep -A 10 -B 5 \"HostConfig\"
    
  • 镜像与容器磁盘空间

    # 查看镜像大小
    docker images
    
    # 查看容器(包括停止的)占用的磁盘空间
    docker ps -a --size
    
  • 性能建议

    1. 选择小巧的基础镜像 :如 alpine -slim 版本,可以显著减少镜像大小和启动时间。
    2. 优化 Dockerfile :合并相关的 RUN 指令,清理不必要的缓存(如 apt-get clean , yum clean all , rm -rf /var/cache/apk/* ),可以减小最终镜像层。
    3. 使用 .dockerignore 文件 :在构建上下文中排除不必要的文件(如 __pycache__ , .git , node_modules ),加速构建过程。

9. 常见问题与排查方法

在实践过程中,你可能会遇到以下问题:

问题现象 可能原因 排查方式 解决方案
docker build 失败,提示找不到文件 Dockerfile 中的 COPY ADD 指令路径错误,或文件不在构建上下文中。 检查 Dockerfile 中的路径,确保要复制的文件位于 docker build 命令指定的上下文目录( . )或其子目录下。 调整文件位置或 Dockerfile 中的路径。使用 .dockerignore 排除无关文件。
docker run 失败,提示端口冲突 宿主机上映射的端口(如 8080 )已被其他进程占用。 在宿主机执行 netstat -tulnp | grep :8080 lsof -i :8080 查看占用进程。 更换宿主机端口(如 -p 8081:80 )或停止占用端口的进程。
容器启动后立即退出 容器内主进程(CMD 或 ENTRYPOINT 指定的命令)执行完毕或出错退出。 使用 docker logs <container-id> 查看容器日志输出。 确保启动命令是长期运行的前台进程(如 nginx -g ‘daemon off;‘ )。对于脚本,确保有循环或持久化逻辑。
容器内无法连接外网(如 yum 失败) 容器网络配置问题,或宿主机的 DNS 设置未正确传递。 在容器内执行 ping 8.8.8.8 测试网络连通性,执行 cat /etc/resolv.conf 查看 DNS。 检查宿主机的防火墙和 Docker 网络设置。运行容器时可尝试 --network host (主机网络模式)测试。或自定义 Docker 网络。
容器内修改文件后,重启容器丢失 对容器内可写层的修改默认是临时的,容器删除后即丢失。 理解 Docker 的存储层概念。 对需要持久化的数据(如数据库文件、配置文件、日志),使用 -v 参数将宿主机目录挂载到容器内。
yum install 速度慢或失败 容器内默认的 Yum 源地址不可达或速度慢。 进入容器检查 /etc/yum.repos.d/ 下的 .repo 文件内容。 如本文所述,配置国内镜像源(如阿里云、清华源)。
权限错误(Permission denied) 容器内进程默认以 root 用户运行,但挂载的宿主机目录权限不足。 检查宿主机目录对 Docker 守护进程用户(或当前用户)是否可读可写。 调整宿主机目录权限,或在 Dockerfile 中使用 USER 指令指定非 root 用户,并确保该用户有相应权限。

10. 最佳实践与使用建议

  1. 从最小化镜像开始 :优先选择 alpine -slim -buster-slim 等小型官方镜像作为基础,以提升安全性和效率。
  2. 利用构建缓存 :Dockerfile 的每条指令都会产生一个层。将不经常变化的指令(如安装系统包)放在前面,将经常变化的指令(如复制应用代码)放在后面,可以充分利用缓存加速构建。
  3. 一个容器一个进程 :虽然可以在一个容器内运行多个进程(使用 supervisord),但最佳实践是每个容器只运行一个主进程。这便于管理、监控和横向扩展。
  4. 使用环境变量配置 :将应用配置(如数据库地址、API密钥)通过环境变量( ENV 指令或 -e 参数)传入容器,而不是写死在镜像里,提高镜像的通用性。
  5. 做好数据管理
    • 使用 VOLUME 指令声明匿名卷。
    • 使用 -v --mount 进行显式绑定挂载或命名卷挂载。
    • 避免在容器内存储重要数据。
  6. 编写清晰的 Dockerfile
    • 使用注释说明复杂步骤。
    • 为镜像打上有意义的标签(如 myapp:1.0 , myapp:latest )。
    • 保持 Dockerfile 和构建上下文整洁。
  7. 安全扫描 :对构建的镜像进行安全漏洞扫描(可使用 docker scan 命令或集成到 CI/CD 中),及时更新基础镜像。

通过定制镜像、配置容器内部环境到部署完整服务这一套流程的实践,你不仅掌握了 Docker 的基本操作,更理解了容器化应用从构建到运行的完整生命周期。接下来,你可以尝试将更复杂的应用(如带数据库的 Web 应用)拆分为多个容器,并使用 Docker Compose 来定义和运行多容器应用,这将是你迈向容器化编排的下一步。

🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值