写在前面
这是我 Docker 学习之路的第二篇文章。前一篇《从虚拟机到容器:Docker 解决了什么问题》讲了概念,这篇来点硬核的——真实环境下的部署实战。
从网络配置到镜像拉取,从 Dockerfile 编写到 Docker Compose 编排,我把这几天的踩坑经历全部记录下来,希望能帮到同样在折腾 Docker 的你。
一、环境准备
我的实验环境:
•宿主机:Windows 10
•虚拟机:VMware 上的 CentOS 7
•Docker 版本:最终升级到 Docker CE 26.1.4
目标:在 CentOS 7 上完整部署 Docker,并成功运行 nginx + mysql 多容器应用。
二、第一个坑:网卡没有启动
装完虚拟机后,我发现网络不通。执行ping 8.8.8.8提示网络不可达。
问题排查
// bash
[root@localhost ~]# ping -c 3 8.8.8.8
connect: 网络不可达
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP> ...
inet 127.0.0.1/8 scope host lo
2: ens33: <BROADCAST,MULTICAST> ...
# 注意:这里没有 inet 地址,状态也不是 UP
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> ...
inet 172.17.0.1/16 scope global docker0
关键发现:ens33网卡状态是DOWN,没有分配到 IP 地址。
解决方案
// bash
# 启动网卡
ip link set ens33 up
# 通过 DHCP 获取 IP
dhclient ens33
# 验证
ip addr show ens33
# 现在可以看到:inet 192.168.120.131/24
# 测试网络
ping -c 3 8.8.8.8
# 64 bytes from 8.8.8.8: icmp_seq=1 ttl=128 time=201 ms ✓
教训:CentOS 7 最小化安装后,网卡默认可能没有设置为开机自启。
三、第二个坑:DNS 配置缺失
网络通了,但 Docker 还是拉不到镜像。报错:
Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:46940->[::1]:53: read: connection refused
问题分析
// bash
[root@localhost ~]# cat /etc/resolv.conf
# Generated by NetworkManager
# 空的!没有 nameserver
根本原因:DNS 配置为空,无法解析域名。
解决方案
// bash
# 配置公共 DNS
echo "nameserver 114.114.114.114" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
# 验证
cat /etc/resolv.conf
# nameserver 114.114.114.114
# nameserver 8.8.8.8
# 测试解析
ping -c 3 registry-1.docker.io
注意:如果/etc/resolv.conf被 NetworkManager 覆盖,需要修改 NetworkManager 配置或手动固定 DNS。
四、第三个坑:Docker 镜像拉取失败
DNS 修好了,但拉取镜像还是超时:
Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection
原因分析
国内网络访问 Docker Hub 不稳定,需要配置镜像加速器。
解决方案一:配置阿里云镜像加速
1.登录阿里云容器镜像服务
2.点击「镜像加速器」获取你的专属加速地址
3.配置到 Docker:
// bash
cat > /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": ["https://你的专属地址.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
解决方案二:安装 Docker CE(推荐)
CentOS 7 自带的 Docker 版本太老(1.13),对镜像加速支持不完善。升级到 Docker CE:
// bash
# 卸载旧版本
yum remove -y docker docker-common docker-client
# 添加阿里云 Docker CE 仓库
yum install -y yum-utils
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装 Docker CE
yum install -y docker-ce docker-ce-cli containerd.io
# 启动并设置开机自启
systemctl start docker
systemctl enable docker
# 验证版本
docker --version
# Docker version 26.1.4, build 5650f9b
关键收获:CentOS 7 自带的docker包和 Docker 官方的docker-ce是两个不同的东西,后者功能更完整、更新更及时。
五、Dockerfile 实战:构建自定义镜像
基础概念掌握了,来动手写个 Dockerfile。
目标
构建一个包含自定义首页的 nginx 镜像,不依赖外部 volume 挂载。
实现步骤
// bash
# 创建项目目录
mkdir ~/my-nginx && cd ~/my-nginx
# 创建 Dockerfile
cat > Dockerfile << 'EOF'
FROM nginx:latest
COPY index.html /usr/share/nginx/html/index.html
EOF
# 创建自定义首页
echo "<h1>这是我的第一个 Dockerfile 构建的镜像</h1>" > index.html
# 构建镜像
docker build -t my-nginx:v1 .
# 查看镜像
docker images | grep my-nginx
# my-nginx v1 b13e6ca12d9a 2 minutes ago 161MB
# 运行容器
docker run -d -p 8082:80 --name my-nginx-test my-nginx:v1
访问http://192.168.120.131:8082,成功看到自定义页面!
Dockerfile 要点:
•FROM:指定基础镜像
•COPY:将本地文件复制到镜像
•docker build -t 镜像名:标签 .:注意最后的.表示当前目录
六、Docker Compose:多容器编排
单个容器搞定了,接下来挑战多容器应用。
目标
用 docker-compose 同时启动 nginx + mysql,并实现数据持久化。
实现步骤
// bash
# 创建项目目录
mkdir ~/docker-compose-demo && cd ~/docker-compose-demo
# 创建 docker-compose.yml
cat > docker-compose.yml << 'EOF'
version: '3'
services:
nginx:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: testdb
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:
EOF
# 创建自定义页面
mkdir html
echo "<h1>Docker Compose 测试成功</h1>" > html/index.html
# 启动所有服务
docker compose up -d # 注意:新版是 docker compose,不是 docker-compose
# 查看状态
docker compose ps
# 查看日志
docker compose logs
踩坑提醒:
•旧版命令是docker-compose,需要单独安装
•新版(Docker 20+)内置了docker compose(空格分隔)
•如果你的系统报docker-compose: 未找到命令,试试docker compose
七、核心概念总结
1. Volume 数据持久化
// bash
# 绑定挂载(Bind Mount)
-v ~/nginx-data/html:/usr/share/nginx/html
# 命名卷(Named Volume)
-v mysql-data:/var/lib/mysql
区别:
•绑定挂载:直接映射宿主机目录,适合开发环境
•命名卷:由 Docker 管理,适合生产环境,更易迁移
2. 端口映射
// bash
-p 8080:80 # 宿主机 8080 → 容器 80
3. 网络模式
•bridge(默认):容器有独立 IP,通过端口映射访问
•host:容器直接使用宿主机网络
•none:无网络连接
八、踩坑清单
问题 | 现象 | 解决方案 |
网卡未启动 | ping 不通外网 | ip link set ens33 up && dhclient ens33 |
DNS 配置缺失 | 域名解析失败 | 配置/etc/resolv.conf添加 nameserver |
镜像拉取超时 | Docker pull 失败 | 配置镜像加速器或升级 Docker CE |
Docker 版本过旧 | 功能不完整 | 卸载旧版,安装 Docker CE |
docker-compose 未安装 | 命令找不到 | 使用docker compose或单独安装 |
参考资料
•Docker 官方文档
•阿里云 Docker CE 镜像
•Docker Compose 官方文档
写在最后
从零开始在 CentOS 7 上部署 Docker,看似简单的任务,实际操作中遇到了不少坑。但每一个坑都是一次学习的机会:
•网络问题让我理解了 Linux 网络配置
•镜像拉取失败让我学会了配置加速器
•Dockerfile 编写让我掌握了镜像构建原理
•Docker Compose 让我体验到了多容器编排的便利
如果你也在学 Docker,我的建议是:
1.不要只看教程,一定要动手实操
2.遇到问题先查日志,90% 的问题都能自己解决
3.把踩过的坑记录下来,这就是你最好的学习笔记
下一篇,我将记录如何用 Docker Compose 部署完整的 Web 应用,敬请期待!
系列文章:
•从虚拟机到容器:Docker 解决了什么问题
•从零开始在 CentOS 7 上部署 Docker:我的实战踩坑记录(本文)