前言

概念懂了,开始动手装 Docker。目标:装好、跑起第一个容器、掌握镜像与容器的日常操作。

一、安装与加速

# 1. 卸载旧版本
dnf remove -y docker docker-client docker-common

# 2. 配置国内 yum 源(阿里云)
dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 3. 安装
dnf install -y docker-ce docker-ce-cli containerd.io

# 4. 配置镜像加速器(国内拉 Docker Hub 很慢)
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<'EOF'
{
  "registry-mirrors": ["https://docker.m.daocloud.io"],
  "log-driver": "json-file",
  "log-opts": {"max-size": "50m", "max-file": "3"}
}
EOF

# 5. 启动
systemctl enable --now docker
docker version          # Client + Server 都有输出即成功

daemon.json 里顺手配了日志上限——容器 stdout 日志不加限制,迟早把磁盘写爆(血泪教训)。

二、第一个容器

# 跑个 Nginx(本地没有镜像会自动 pull)
docker run -d --name web -p 8080:80 nginx:alpine

# 参数拆解:
#   -d          后台运行
#   --name web  容器命名
#   -p 8080:80  端口映射: 宿主机8080 -> 容器80
#   nginx:alpine 精简版镜像

curl -I http://127.0.0.1:8080    # 200 OK 🎉

数据持久化——数据卷挂载:

docker run -d --name web \
  -p 8080:80 \
  -v /opt/www:/usr/share/nginx/html:ro \
  nginx:alpine

# -v 宿主机路径:容器路径[:ro]
# 容器删了, /opt/www 的文件还在 —— 数据不进容器是黄金法则

三、镜像操作

docker pull python:3.11-slim        # 拉取(不写 tag 默认 latest, 生产禁用)
docker images                       # 本地镜像列表
docker rmi python:3.11-slim         # 删除镜像
docker tag nginx:alpine reg.local/mynginx:v1   # 打标签
docker push reg.local/mynginx:v1    # 推到私有仓库
docker save -o nginx.tar nginx:alpine        # 导出离线包
docker load -i nginx.tar                     # 导入
docker history nginx:alpine         # 看镜像分层
docker inspect nginx:alpine         # 镜像详情(JSON)

镜像分层:镜像是只读层的堆叠(每条 Dockerfile 指令一层),多个镜像共享基础层,省空间、拉取快。

四、容器生命周期

docker ps                       # 运行中的容器
docker ps -a                    # 包括已停止的
docker stop web && docker start web
docker restart web
docker rm web                   # 删除(停止的)容器
docker rm -f web                 # 强删(运行中的)
docker container prune           # 清理所有停止的容器

# 进入容器排查(比 attach 安全, 退出不带走容器)
docker exec -it web sh

# 看日志
docker logs -f --tail 100 web

# 拷文件(双向)
docker cp web:/etc/nginx/nginx.conf ./
docker cp ./app.conf web:/etc/app/

# 查看资源占用
docker stats --no-stream
docker top web                  # 容器内进程

五、容器 ↔ 进程的对应关系

# 容器本质是宿主机上的进程
docker inspect -f '{{.State.Pid}}' web     # 拿到容器主进程 PID, 假设 9876
ps -p 9876                                 # 宿主机上能看到
ls /proc/9876/ns/                          # namespace 隔离证据

六、动手练习:跑一个 Python 应用

mkdir -p /opt/pyapp && cd /opt/pyapp
cat > app.py <<'EOF'
from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
    return "hello from container\n"

app.run(host="0.0.0.0", port=5000)
EOF

docker run -d --name pyapp \
  -v /opt/pyapp:/app -w /app \
  -p 5000:5000 \
  python:3.11-slim \
  sh -c "pip install -q flask -i https://mirrors.aliyun.com/pypi/simple/ && python app.py"

curl http://127.0.0.1:5000

这个例子把代码挂载、工作目录、端口映射、启动命令四个高频点全串起来了。

七、常见坑速查

现象 原因与解法
拉镜像超时 没配 registry-mirrors,或镜像源挂了换一个
端口映射后外部不通 云安全组没放行;或容器内服务只监听 127.0.0.1
容器一启动就退出 前台没有常驻进程;看 docker logs
磁盘被吃满 /var/lib/docker 膨胀,docker system prune + 日志限额
exec 进不去 精简镜像(alpine/scratch)没有 bash,用 sh
# 大扫除(谨慎: 会删掉未使用的镜像/容器/网络)
docker system df               # 先看占用
docker system prune -a

小结

操作 命令
跑容器 docker run -d --name x -p 宿:容器 -v 宿:容器 镜像
进容器 docker exec -it x sh
看日志 docker logs -f x
清理 docker rm / docker rmi / system prune

牢记两条黄金法则:数据不进容器(用 -v)、生产不用 latest(锁版本)。下一篇写 Dockerfile,把"怎么做出自己的镜像"补上。


本文是「云原生」系列第 2 篇。