写在前面

这是我 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:我的实战踩坑记录(本文)

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐