📘 第02课:第一个容器

基础 动手创建和管理你的第一个Docker容器

🚀 docker run 深度解析

docker run是Docker最核心的命令,它完成了一连串操作:

docker run nginx 的完整流程: ① 检查本地镜像 ──→ 本地有?──→ 使用本地镜像 没有 ② 从Registry拉取 ──→ Docker Hub ──→ 下载到本地 ③ 创建容器 ──→ 分配文件系统 / 网络 / PID命名空间 ④ 启动容器 ──→ 执行ENTRYPOINT/CMD指令 ⑤ 容器运行中
# 基本语法
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 运行hello-world(测试Docker安装)✅
docker run hello-world

# 运行Nginx Web服务器 ✅
docker run nginx

# 后台运行,命名容器 ✅
docker run -d --name my-nginx nginx

# 前台交互运行Ubuntu ✅
docker run -it ubuntu bash

📋 docker run 常用选项

选项说明示例
-d后台运行(detached模式)docker run -d nginx
-it交互模式(i=stdin, t=TTY)docker run -it ubuntu bash
--name命名容器docker run --name web nginx
-p端口映射(宿主:容器)docker run -p 8080:80 nginx
-v挂载数据卷docker run -v /data:/app nginx
-e设置环境变量docker run -e FOO=bar nginx
--rm容器停止后自动删除docker run --rm nginx
--restart重启策略docker run --restart=always nginx
-w工作目录docker run -w /app ubuntu
-u用户(uid:gid)docker run -u 1000:1000 ubuntu
--hostname容器主机名docker run --hostname myhost ubuntu
--network指定网络docker run --network bridge nginx
--cpusCPU限制docker run --cpus=1.5 nginx
-m内存限制docker run -m 512m nginx

🐧 实战:交互式Ubuntu容器

# 运行Ubuntu容器并进入bash ✅
docker run -it --name my-ubuntu ubuntu:22.04 bash

# 现在你已经在容器内部了!
root@abc123:/# cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"

# 在容器内安装软件
apt-get update && apt-get install -y curl

# 查看容器内进程
ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 bash
   38 root      0:00 ps aux

# 退出容器
exit
💡 -it的本质-i保持STDIN打开,-t分配伪终端。没有-it,容器执行完命令会立即退出。只有需要交互时才用-it,服务类容器用-d

🌐 实战:Nginx Web服务器

# 后台运行Nginx,映射端口 ✅
docker run -d --name web-server -p 8080:80 nginx

a1b2c3d4e5f6... (容器ID)

# 查看容器状态 ✅
docker ps
CONTAINER ID   IMAGE   STATUS         PORTS                  NAMES
a1b2c3d4e5f6   nginx   Up 10 seconds  0.0.0.0:8080->80/tcp   web-server

# 访问Nginx欢迎页 ✅
curl http://localhost:8080


Welcome to nginx!
...

# 查看容器日志 ✅
docker logs web-server

# 查看容器详细信息
docker inspect web-server
端口映射原理: 宿主机 容器 ┌────────────────┐ ┌────────────────┐ │ │ │ │ │ :8080 ◄──────┼─── 端口映射 ──►│ :80 │ │ (外部访问) │ -p 8080:80 │ (Nginx监听) │ │ │ │ │ └────────────────┘ └────────────────┘ 外部请求 → 宿主机:8080 → iptables DNAT → 容器:80

🔄 容器生命周期管理

容器生命周期状态机: docker create │ ▼ ┌──────────┐ ┌────────►│ Created │◄───────┐ │ └────┬─────┘ │ │ │ docker start │ docker stop / kill │ ▼ │ │ ┌──────────┐ │ │ │ Running │───────┤ │ └────┬─────┘ │ │ │ │ │ docker pause│ ┌──────▼─────┐ │ ▼ │ │ Stopped │ │ ┌──────────┐ └──────┬─────┘ │ │ Paused │ │ │ └────┬─────┘ │ docker rm │ docker unpause│ │ │ │ ▼ │ │ ┌──────────┐ └──────────────┘ │ Deleted │ docker restart └──────────┘
# 创建容器(不启动)
docker create --name my-app nginx

# 启动已创建/已停止的容器 ✅
docker start my-app

# 停止容器(发送SIGTERM,10秒后SIGKILL)✅
docker stop my-app

# 强制停止(直接SIGKILL)
docker kill my-app

# 重启容器
docker restart my-app

# 暂停/恢复容器(冻结/解冻进程)
docker pause my-app
docker unpause my-app

# 删除已停止的容器 ✅
docker rm my-app

# 删除运行中的容器(先停止再删除)
docker rm -f my-app

📋 docker exec:进入运行中的容器

# 在运行中的容器内执行命令 ✅
docker exec web-server ls /usr/share/nginx/html

# 进入容器的交互终端 ✅
docker exec -it web-server bash

# 以指定用户执行命令
docker exec -u root web-server cat /etc/nginx/nginx.conf

# 设置环境变量执行命令
docker exec -e MY_VAR=hello web-server env
💡 docker exec vs docker attach

📊 容器资源查看

# 查看容器资源使用情况 ✅
docker stats
CONTAINER ID   NAME         CPU %   MEM USAGE / LIMIT   MEM %   NET I/O
a1b2c3d4e5f6   web-server   0.01%   2.5MiB / 7.77GiB   0.03%   1.2kB / 0B

# 查看指定容器资源(不刷新)✅
docker stats --no-stream web-server

# 查看容器内进程 ✅
docker top web-server
UID    PID    PPID    C    STIME   TTY     TIME       CMD
root   1234   5678    0    10:30   ?       00:00:00   nginx: master process
101    1245   1234    0    10:30   ?       00:00:00   nginx: worker process

# 查看容器端口映射
docker port web-server
80/tcp -> 0.0.0.0:8080

# 查看容器文件系统变更
docker diff web-server

📝 容器日志管理

# 查看容器日志 ✅
docker logs web-server

# 实时跟踪日志
docker logs -f web-server

# 查看最后100行日志
docker logs --tail 100 web-server

# 查看指定时间之后的日志
docker logs --since "2024-01-01T00:00:00" web-server

# 查看最近30分钟的日志
docker logs --since 30m web-server

# 查看日志时间戳
docker logs -t web-server

🧹 容器清理

# 删除单个已停止容器
docker rm web-server

# 删除所有已停止容器 ✅
docker container prune

# 删除所有容器(包括运行中)
docker rm -f $(docker ps -aq)

# 清理所有未使用资源(容器、镜像、网络)✅
docker system prune

# 清理所有未使用资源(含镜像)
docker system prune -a

# 查看磁盘使用 ✅
docker system df
TYPE            TOTAL   ACTIVE  SIZE      RECLAIMABLE
Images          5       2       450.3MB   320.1MB (71%)
Containers      3       1       12.5kB    8.19kB (65%)
Local Volumes   2       1       105.6MB   52.8MB (50%)
Build Cache     15              78.2MB    78.2MB (100%)

🔬 实战练习:多容器协作

# 1. 运行Redis容器 ✅
docker run -d --name redis -p 6379:6379 redis:7-alpine

# 2. 运行另一个容器连接Redis ✅
docker run -it --rm --link redis:redis redis:7-alpine redis-cli -h redis ping
PONG

# 3. 运行MySQL容器 ✅
docker run -d --name mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=myapp \
  -p 3306:3306 \
  mysql:8.0

# 4. 运行Adminer(数据库管理工具)✅
docker run -d --name adminer \
  --link mysql:db \
  -p 8080:8080 \
  adminer

# 5. 查看所有运行中的容器 ✅
docker ps
CONTAINER ID  IMAGE            STATUS       PORTS                    NAMES
f1a2b3c4d5e6  redis:7-alpine   Up 2 min     0.0.0.0:6379->6379/tcp   redis
a2b3c4d5e6f7  mysql:8.0        Up 1 min     0.0.0.0:3306->3306/tcp   mysql
b3c4d5e6f7a8  adminer          Up 30 sec    0.0.0.0:8080->8080/tcp   adminer
⚠️ --link已弃用--link是Docker早期的容器互联方式,已被自定义网络取代。上面的示例仅用于学习,生产环境请使用docker network(第05课详细讲解)。

❓ 常见问题

❓ 容器退出后数据还在吗? 容器停止后文件系统数据仍然存在,但删除容器(docker rm)后数据就会丢失。持久化数据需要使用数据卷(Volume),我们将在第06课学习。
❓ 容器里无法使用vim/top等命令怎么办? 精简镜像(如alpine)不包含这些工具。可以在容器内安装:apt-get install vim procps(Debian/Ubuntu)或apk add vim htop(Alpine)。但推荐的做法是用docker execdocker cp,不在容器内安装额外软件。
❓ 如何让容器在宿主机重启后自动启动? 使用--restart策略:docker run -d --restart=always nginx。策略选项:①no:不自动重启(默认)②on-failure[:max]:非正常退出时重启 ③always:总是重启 ④unless-stopped:总是重启,除非手动停止过。
❓ docker stop很慢怎么办? docker stop先发送SIGTERM,等待10秒后发送SIGKILL。如果应用不处理SIGTERM,就会等10秒。解决方案:①修复应用的信号处理 ②使用docker stop -t 3缩短等待时间 ③直接docker kill(但不优雅)。
❓ 如何查看容器退出原因? docker inspect <container> --format='{{.State.ExitCode}}'查看退出码。常见退出码:0=正常退出,1=应用错误,137=OOMKilled,139=段错误。查看OOM:docker inspect <container> --format='{{.State.OOMKilled}}'

🏆 第02课成就

下一课:深入学习Docker镜像管理——搜索、拉取、构建、推送!