📖 知识点简介
容器化是运维绕不开的关键技术。Docker 将应用及其依赖打包成轻量、可移植的容器,实现"一次构建,到处运行"。掌握 Docker 基础操作,是现代化运维的必备技能------从镜像拉取、容器生命周期管理,到 Dockerfile 构建和 Compose 编排,构成了运维容器化的知识骨架。
前八篇我们从系统命令、网络、服务管理走到了 Shell 脚本,今天是容器世界的起点。
🛠 核心命令整理
1. 镜像管理
| 命令 | 说明 |
|---|---|
docker pull <image>:<tag> |
拉取镜像(tag 默认 latest) |
docker images |
列出本地镜像 |
docker rmi <image> |
删除镜像 |
docker image prune |
清理未被使用的镜像(悬空镜像) |
docker tag <image> <new_tag> |
给镜像打标签 |
docker search <keyword> |
搜索 Docker Hub 上的镜像 |
docker save -o <file.tar> <image> |
导出镜像为 tar 文件 |
docker load -i <file.tar> |
从 tar 文件导入镜像 |
docker history <image> |
查看镜像构建历史 |
2. 容器生命周期
| 命令 | 说明 |
|---|---|
docker run <image> |
创建并启动容器 |
docker start/stop <container> |
启动/停止已存在的容器 |
docker restart <container> |
重启容器 |
docker pause/unpause <container> |
暂停/恢复容器进程 |
docker rm <container> |
删除容器(需先 stop) |
docker container prune |
清理所有已停止的容器 |
docker run 常用参数
| 参数 | 说明 |
|---|---|
-d |
后台运行(detach) |
--name |
指定容器名 |
-p 8080:80 |
端口映射(宿主机:容器) |
-v /host:/container |
挂载卷(持久化数据) |
-e KEY=VALUE |
传递环境变量 |
--restart=always |
容器退出自动重启 |
--rm |
容器停止后自动删除(临时测试用) |
--network |
指定网络模式 |
--link |
旧版容器互联(不推荐,建议用 network) |
3. 容器操作与监控
| 命令 | 说明 |
|---|---|
docker ps |
列出运行中的容器 |
docker ps -a |
列出所有容器(含已停止) |
docker logs <container> |
查看容器日志 |
docker logs -f <container> |
实时追踪日志 |
docker logs --tail 100 <container> |
只看最后 100 行 |
docker exec -it <container> bash |
进入容器终端(交互式) |
docker inspect <container> |
查看容器详细元数据(JSON) |
docker stats |
实时查看容器资源占用(类似 top) |
docker top <container> |
查看容器内进程 |
docker port <container> |
查看容器端口映射 |
docker diff <container> |
查看容器文件系统的变更 |
4. Dockerfile 基础指令
dockerfile
FROM nginx:alpine # 基础镜像(alpine 版更小)
LABEL maintainer="ops" # 元数据
WORKDIR /app # 工作目录
COPY . /app # 复制文件到镜像
ADD app.tar.gz /app # 复制并自动解压
RUN apt update && ... # 构建时执行命令
ENV NODE_ENV=production # 环境变量
EXPOSE 80 # 暴露端口(声明用)
CMD ["nginx", "-g", "daemon off;"] # 启动命令
ENTRYPOINT ["/start.sh"] # 入口点(更灵活)
5. Docker Compose 编排(docker-compose.yml)
yaml
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- api
api:
build: ./api
environment:
- DB_HOST=db
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
bash
docker-compose up -d # 启动所有服务(后台)
docker-compose down # 停止并删除所有服务
docker-compose logs -f # 查看所有服务的日志
docker-compose ps # 查看服务状态
docker-compose exec web sh # 进入某个服务容器
docker-compose restart web # 重启某个服务
💻 实操示例
示例 1:部署 Nginx 静态站点(从零开始)
bash
# ① 拉取镜像
docker pull nginx:alpine
# ② 先试运行(前台,测试用)
docker run --rm -p 8080:80 nginx:alpine
# 访问 http://localhost:8080 看到 Nginx 欢迎页
# ③ 挂载自定义页面并后台运行
mkdir -p ~/web/html
echo "<h1>Hello from Docker!</h1>" > ~/web/html/index.html
docker run -d \
--name my-nginx \
-p 8080:80 \
-v ~/web/html:/usr/share/nginx/html:ro \
--restart=always \
nginx:alpine
# ④ 验证
curl -s http://localhost:8080
docker ps
docker logs my-nginx
示例 2:容器内排错(经典场景:服务 502)
bash
# 场景:后端 API 容器启动失败
docker logs api-container | tail -30
# 输出: Error: Cannot connect to database
# 进入容器检查网络连通性
docker exec -it api-container sh
# 容器内执行
ping -c 2 db
# 如果 DNS 不通,检查 docker-compose 的 depends_on 和 network
# 查看容器进程
docker top api-container
# 查看容器资源占用
docker stats --no-stream api-container
示例 3:Dockerfile 构建 Node.js 应用
dockerfile
# Dockerfile --- 多阶段构建(减少镜像体积)
# 第一阶段:构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# 第二阶段:运行(镜像仅 150MB 左右)
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app ./
EXPOSE 3000
USER node
CMD ["node", "server.js"]
bash
# 构建并运行
docker build -t myapp:1.0 .
docker run -d --name myapp -p 3000:3000 myapp:1.0
示例 4:日常容器运维组合拳
bash
# 查找所有占用磁盘大的容器日志
find /var/lib/docker/containers/ -name "*-json.log" -exec ls -lh {} ;
# 限制单容器日志大小(推荐,在 docker run 时指定)
docker run -d \
--log-opt max-size=10m \
--log-opt max-file=3 \
--name app nginx:alpine
# 清理 Docker 磁盘空间(定期执行)
docker system df # 查看占用
docker system prune -a --volumes # 清理所有未使用的资源(慎用!)
⚠️ 常见坑点 / 注意事项
-
docker run --rm别忘了 --- 测试时加--rm,容器退出自动删除,避免积攒一堆死容器。生产环境当然不用。 -
容器内 PID 1 问题 --- 容器中第一个进程(PID 1)有特殊义务:处理 SIGTERM 信号。如果用 shell 做 CMD(如
CMD while true; do ...),shell 不会转发信号给子进程,docker stop可能超时。解决办法:用exec启动或使用 dumb-init/tini。 -
docker stop不是瞬间 kill --- 它会先发 SIGTERM(默认等待 10s),超时后才 SIGKILL。如果你的应用优雅退出慢,用docker stop -t 30 <container>延长等待时间。 -
镜像体积------Alpine 是标配 --- 相同功能的镜像,Alpine 版通常只有标准版的 1/5 ~ 1/10。生产环境优先选
-alpine标签的镜像。 -
挂载卷权限问题 --- 宿主机挂载目录的 UID/GID 与容器内进程的 UID 不一致时,容器可能没权限写入。检查容器内用户的 UID(如 nginx 是 101),宿主机
chown 101:101 ./data。 -
容器日志不轮转会撑爆磁盘 --- Docker 默认不限制日志文件大小,长期运行的容器日志可能几十 GB。务必加
--log-opt max-size=10m --log-opt max-file=3,或者在/etc/docker/daemon.json中全局配置:json{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } -
docker system prune -a会删所有未用镜像 --- 包括你可能需要的。定期清理前先docker system df看下占用量,确认没有重要镜像再用。 -
容器时间与宿主机不一致 --- 默认容器用 UTC 时区。生产环境挂载
/etc/localtime:bashdocker run -v /etc/localtime:/etc/localtime:ro ...
📌 一句话总结:
docker pull拿镜像 →docker run跑容器 →docker exec进排错 →docker-compose up -d整站启动。容器化让部署变得一致、可复现、易迁移,是现代运维的必备武器。