🚀 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. 适用场景与使用边界
掌握定制镜像和在容器内配置环境的能力,主要适用于以下几类场景:
- 应用容器化 :你有一个用 Python、Node.js 或 Go 编写的应用程序,希望将其与运行环境一起打包,确保在任何装有 Docker 的机器上都能以相同的方式运行。
- 环境标准化与隔离 :需要快速创建一个干净的、特定版本(如 CentOS 7.9)的 Linux 环境来编译软件、测试安装脚本或复现问题,而不污染宿主机。
- 离线或内网环境部署 :在生产环境中,服务器可能无法访问互联网。你需要提前构建好包含所有依赖的镜像,或学会在容器内配置内部私有的 Yum 仓库。
- 学习与实验 :这是理解 Docker 镜像分层、构建上下文以及容器内部系统管理的最佳实践途径。
使用边界与注意事项:
- 并非替代虚拟机 :对于需要完整操作系统特性、特殊内核模块或高性能持久化存储的场景,容器可能不是最佳选择。
- 数据持久化 :容器内安装的服务,其数据(如数据库文件、日志)默认随容器删除而丢失。务必通过
-v挂载卷或 Docker Volume 实现数据持久化。 - 安全合规 :自定义镜像可能包含软件漏洞。建议基于官方最小化镜像(如
alpine、centos:7)构建,并定期更新基础镜像和软件包。从不可信的来源获取 Yum 仓库配置存在安全风险。 - 镜像大小 :在 Dockerfile 中执行过多的
yum install操作会导致镜像层臃肿。应合理安排命令顺序,并清理缓存(如yum clean all)以优化最终镜像大小。
3. 环境准备与前置条件
开始操作前,请确保你的实验环境满足以下要求:
- 操作系统 :支持 Docker 的 Linux 发行版(如 Ubuntu、CentOS)、macOS 或 Windows 10/11。
- Docker 环境 :
- Linux :已安装 Docker Engine。可通过
sudo docker --version验证。 - macOS/Windows :已安装 Docker Desktop 并处于运行状态。
- Linux :已安装 Docker Engine。可通过
- 网络连接 :首次拉取基础镜像和后续在容器内配置网络 Yum 源时需要互联网访问。对于离线配置部分,需提前下载好 RPM 包或仓库数据。
- 磁盘空间 :建议至少有 2GB 的可用磁盘空间,用于存储基础镜像和构建过程中的临时层。
- 权限 :在 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 中直接添加。
方法一:启动时挂载本地仓库文件(适用于快速测试)
- 在宿主机上创建一个 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 - 启动一个新的容器,并将该仓库文件挂载到容器内的
/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 - 在容器内再次尝试安装软件。
此时安装应该能够成功。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 验证服务是否正常运行
- 检查容器状态 :
应看到容器状态为 “Up”。docker ps | grep my-nginx - 查看容器日志 :
通常无错误信息。docker logs my-nginx - 访问服务 :
- 在宿主机浏览器中访问
http://localhost:8080。 - 或使用
curl命令:curl http://localhost:8080
- 在宿主机浏览器中访问
6.5 进入容器进行管理 你可以进入正在运行的容器内部,查看进程、修改配置(测试用)等。
docker exec -it my-nginx /bin/bash
# 进入容器后
ps aux | grep nginx
cat /etc/nginx/nginx.conf
退出容器使用 exit 。
7. 接口 API 与批量任务
虽然本文示例是一个 Web 服务器,但 Docker 容器化部署的模式适用于任何服务,包括提供 API 的后端应用。核心思路是一致的:
- 编写 Dockerfile :定义基础环境、安装依赖(如 Python pip, Node.js npm)、复制代码、设置启动命令(如
python app.py,node server.js)。 - 暴露端口 :在 Dockerfile 中使用
EXPOSE指令声明应用监听的端口(如EXPOSE 5000)。 - 运行容器 :使用
-p参数将容器端口映射到宿主机(如-p 5000:5000)。 - 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 -
性能建议 :
- 选择小巧的基础镜像 :如
alpine、-slim版本,可以显著减少镜像大小和启动时间。 - 优化 Dockerfile :合并相关的
RUN指令,清理不必要的缓存(如apt-get clean,yum clean all,rm -rf /var/cache/apk/*),可以减小最终镜像层。 - 使用
.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. 最佳实践与使用建议
- 从最小化镜像开始 :优先选择
alpine、-slim、-buster-slim等小型官方镜像作为基础,以提升安全性和效率。 - 利用构建缓存 :Dockerfile 的每条指令都会产生一个层。将不经常变化的指令(如安装系统包)放在前面,将经常变化的指令(如复制应用代码)放在后面,可以充分利用缓存加速构建。
- 一个容器一个进程 :虽然可以在一个容器内运行多个进程(使用 supervisord),但最佳实践是每个容器只运行一个主进程。这便于管理、监控和横向扩展。
- 使用环境变量配置 :将应用配置(如数据库地址、API密钥)通过环境变量(
ENV指令或-e参数)传入容器,而不是写死在镜像里,提高镜像的通用性。 - 做好数据管理 :
- 使用
VOLUME指令声明匿名卷。 - 使用
-v或--mount进行显式绑定挂载或命名卷挂载。 - 避免在容器内存储重要数据。
- 使用
- 编写清晰的 Dockerfile :
- 使用注释说明复杂步骤。
- 为镜像打上有意义的标签(如
myapp:1.0,myapp:latest)。 - 保持 Dockerfile 和构建上下文整洁。
- 安全扫描 :对构建的镜像进行安全漏洞扫描(可使用
docker scan命令或集成到 CI/CD 中),及时更新基础镜像。
通过定制镜像、配置容器内部环境到部署完整服务这一套流程的实践,你不仅掌握了 Docker 的基本操作,更理解了容器化应用从构建到运行的完整生命周期。接下来,你可以尝试将更复杂的应用(如带数据库的 Web 应用)拆分为多个容器,并使用 Docker Compose 来定义和运行多容器应用,这将是你迈向容器化编排的下一步。
🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度

347

被折叠的 条评论
为什么被折叠?



