Docker 容器

容器(Container)是镜像跑起来的实例——一个真实运行着的进程,有自己的文件系统、网络、PID 空间。这一章把容器管理的常用命令一网打尽,学完你就能熟练地启动、查看、进入、停止、监控任何容器。

1. docker run:启动容器

docker run用得最多的命令,选项组合出无穷变化。先把高频参数记牢:

# docker run:从镜像启动一个新容器(最核心的命令)

# 基本形态:docker run [选项] 镜像 [命令]
docker run nginx                       # 前台跑,关终端就退出
docker run -d nginx                    # -d 后台运行
docker run --name web nginx            # --name 起名字,方便管理
docker run --rm nginx echo hi          # --rm 跑完自动删除容器

# 端口映射:主机端口:容器端口
docker run -p 8080:80 nginx            # 单个端口
docker run -p 8080:80 -p 8443:443 nginx  # 多个端口
docker run -p 127.0.0.1:8080:80 nginx  # 只绑定本机,不对外暴露
docker run -P nginx                    # -P 大写,自动分配主机端口(随机)

# 环境变量
docker run -e TOKEN=abc123 nginx
docker run -e PORT=8080 -e DEBUG=true nginx
docker run --env-file .env nginx       # 从文件批量读

# 挂载目录(下一章数据卷详解)
docker run -v /host/data:/container/data nginx
docker run -v $(pwd)/logs:/var/log/nginx nginx

# 工作目录、用户、重启策略
docker run -w /app -u node node:20 sh
docker run --restart unless-stopped nginx   # 崩溃自动重启

一个口诀记忆常用参数:"d 名 p v e"——-d 后台、--name 命名、-p 端口、-v 挂载、-e 环境变量。--restart unless-stopped 在生产很重要:服务器重启后容器会自动起来。

2. docker ps:查看容器

# 查看容器列表

docker ps                       # 只看运行中的容器
docker ps -a                    # -a 包含所有(已停止的也显示)
docker ps -aq                   # 只列容器 ID(常配合 xargs 删全部)

# CONTAINER ID  IMAGE   COMMAND   CREATED        STATUS        NAMES
# a1b2c3d4...   nginx   "ngin.."  5 minutes ago  Up 5 minutes   web

# 自定义输出列
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# 按状态过滤
docker ps -f status=running
docker ps -f status=exited
docker ps -f name=web                  # 按名字过滤

# 看最后启动的几个
docker ps -n 5                         # 最近 5 个(含已停止)

新手常踩的坑:docker ps 默认只看运行中的,以为容器没了其实只是停了。养成用 docker ps -a 的习惯,看到所有容器(包括已退出的)。-q 只输出 ID,在批量操作脚本里非常好用,如 docker rm $(docker ps -aq) 一键清空所有容器。

3. 生命周期:start / stop / restart / rm

# 容器生命周期:start / stop / restart / rm

# 启动已停止的容器(不会重新跑启动命令,而是从上次状态继续)
docker start web
docker start -i web                    # -i 附加交互模式

# 优雅停止(发 SIGTERM,超时 10 秒后 SIGKILL)
docker stop web
docker stop -t 30 web                  # 给 30 秒优雅退出时间

# 强制停止(直接 SIGKILL,可能丢数据)
docker kill web

# 重启
docker restart web

# 删除容器(必须先停止)
docker rm web                          # 按名字
docker rm a1b2c3d4                     # 按 ID
docker rm -f web                       # 强制删(运行中也停掉删)
docker rm $(docker ps -aq)             # 删除所有容器(慎用)
docker container prune                 # 删除所有已停止的容器

注意 stopkill 的区别:stop 先发 SIGTERM 让进程优雅退出(默认 10 秒),超时才 SIGKILL;kill 直接 SIGKILL,可能丢数据。Web 服务用 stop,卡死的容器才用 kill。

另一个易混点:docker run 每次都新建一个容器,而 docker start启动已存在的停止容器。如果你的容器配置复杂不想每次重写一长串参数,就 stop / start 复用。

4. docker exec:进入容器

这是调试神器——像 SSH 进服务器一样进容器排查问题:

# 进入运行中的容器:exec vs attach

# docker exec:在容器里新开一个进程(推荐)
docker exec -it web bash               # 进入容器开 bash
docker exec -it web sh                 # alpine 没有 bash,用 sh
docker exec web ls /app                # 不进入,直接执行命令
docker exec web cat /etc/nginx/nginx.conf

# docker attach:附加到容器主进程(容器 PID 1)
# 退出时按 Ctrl+P Ctrl+Q 才能让容器继续跑
# 直接 Ctrl+C 会把容器一起干掉,慎用
docker attach web

# 实战:在 nginx 容器里改个文件看效果
docker exec -it web sh
> echo "<h1>hi from docker</h1>" > /usr/share/nginx/html/index.html
> exit
# 刷新浏览器 http://localhost:8080 就能看到改动

记住优先用 exec,不要用 attachexec 是新开一个 shell,退出不影响容器;attach 是接到主进程,你 Ctrl+C 容器就跟着死。-it 两个参数:-i 保持输入流开,-t 分配伪终端,缺一个交互体验都会很怪。

5. docker logs:看日志

# 看容器日志

docker logs web                        # 全部日志
docker logs -f web                     # -f 跟随模式(类似 tail -f)
docker logs --tail 100 web             # 只看最后 100 行
docker logs --since 10m web            # 最近 10 分钟
docker logs --since 2024-01-01T00:00:00 web   # 指定时间起
docker logs -t web                     # 显示时间戳

# 组合:实时看最近 50 行
docker logs -f --tail 50 web

# 容器日志的来源:容器内进程写到 stdout / stderr 的内容
# Docker 自动收集并存到 /var/lib/docker/containers/<id>/<id>-json.log
# 日志默认无大小限制,久了会撑爆磁盘,生产要配 log-rotate

Docker 日志的关键认知:它只显示写到 stdout/stderr 的内容。如果应用把日志写到文件(如 /var/log/app.log),docker logs 是看不到的——要么改应用让日志输出到 stdout,要么用 docker exec 进去看文件。后面最佳实践章会讲为什么容器应用必须把日志写 stdout。

6. 监控与排错

# 监控容器资源

# 实时看 CPU、内存、网络 IO(类似 top)
docker stats
docker stats web                       # 只看指定容器
docker stats --no-stream               # 只输出一次,不滚动

# CONTAINER ID   NAME   CPU %   MEM USAGE / LIMIT   ...
# a1b2c3d4...    web    0.50%   25MiB / 8GiB        ...

# 看容器内进程树
docker top web

# 看容器详细配置(IP、挂载点、环境变量、启动命令)
docker inspect web
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web

# 查看文件改动(容器相对镜像改了哪些文件)
docker diff web

# 把容器的文件拷到主机(或反向)
docker cp web:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./app.conf web:/etc/nginx/conf.d/app.conf

docker stats 是实时的资源监控,排查"容器为什么卡/吃内存"很直观。docker inspect 信息最全,就是 JSON 太长,配合 -f 模板提取关键字段才好用。docker cp 在容器和主机之间拷文件,调试时拿日志、改配置都很方便。

实战:第一次完整使用

把上面学的串起来,完整跑一遍 Nginx 的"启动→查看→改文件→监控→清理"全流程:

# 第一个容器实战:跑一个 Nginx 并交互

# 1. 后台跑容器
docker run -d --name web -p 8080:80 nginx:1.25-alpine

# 2. 看是否在运行
docker ps

# 3. 看日志确认启动成功
docker logs web

# 4. 进容器改个文件
docker exec -it web sh
/ # echo "hello docker" > /usr/share/nginx/html/index.html
/ # exit

# 5. 浏览器访问 http://localhost:8080 看到 "hello docker"

# 6. 看 CPU/内存占用
docker stats --no-stream web

# 7. 清理
docker stop web && docker rm web

走完这一遍,你已经掌握容器日常使用的 80%。剩下 20% 是数据卷(下一章)和网络——它们让容器不再是"用完即扔"的临时存在。

容器退出码速查

docker ps -a 看到 STATUS 列的退出码,能快速定位问题:

← 上一篇 Docker 镜像

下一篇 Dockerfile 详解

✈️💬