容器是镜像的运行实例

前几章我们说镜像是"模板",容器就是"根据模板做出来的实例"。今天深入学习容器的操作。

容器的生命周期

┌─────────┐   create    ┌─────────┐
│   创建   │ ────────>  │  启动   │
└─────────┘            └────┬────┘
                            │
                         start
                            ↓
┌─────────┐   restart   ┌────┴────┐
│  停止   │ <────────── │  运行中  │
└────┬────┘             └─────────┘
     │
  kill/stop
     ↓
┌─────────┐   rm       ┌─────────┐
│  删除   │ ────────>  │  已结束  │
└─────────┘            └─────────┘

创建和启动容器

docker run 详解

docker run 是最常用的命令,它包含了创建和启动两个步骤:

docker run [选项] 镜像 [命令] [参数]

常用选项

后台运行

# -d, --detach
docker run -d nginx

端口映射

# -p 宿主机端口:容器端口
docker run -d -p 8080:80 nginx

# 多个端口
docker run -d -p 80:80 -p 443:443 nginx

# 随机端口
docker run -d -P nginx

容器名称

# --name 给容器起名
docker run -d --name my-nginx nginx

为什么建议给容器起名?

  • 方便管理(不用记容器ID)
  • 容器重启后名称不变
  • 其他容器可以通过名称访问

环境变量

# -e, --env 设置环境变量
docker run -d -e MYSQL_ROOT_PASSWORD=123456 mysql

# 多个环境变量
docker run -d -e TZ=Asia/Shanghai -e LANG=C.UTF-8 nginx

# 从文件读取
cat > env.txt << 'EOF'
TZ=Asia/Shanghai
LANG=C.UTF-8
EOF
docker run -d --env-file env.txt nginx

数据卷挂载

# -v 宿主机路径:容器路径
docker run -d -v /data/nginx:/usr/share/nginx/html nginx

# 只读挂载
docker run -d -v /data:/data:ro nginx

# 命名卷
docker run -d -v mydata:/data nginx

工作目录

# -w, --workdir 设置工作目录
docker run -d -w /app python:3.11 python app.py

用户

# -u, --user 指定运行用户
docker run -d -u 1000:1000 nginx

资源限制

# 限制内存
docker run -d -m 512m nginx

# 限制CPU(使用0.5个核心)
docker run -d --cpus 0.5 nginx

# 组合限制
docker run -d -m 512m --cpus 1 nginx

自动重启

# --restart=always 容器退出后自动重启
docker run -d --restart=always nginx

# --restart=on-failure 只在失败时重启
docker run -d --restart=on-failure:3 nginx

# --restart=unless-stopped 除非手动停止,否则自动重启
docker run -d --restart=unless-stopped nginx

交互式运行

# -i, --interactive 保持标准输入打开
# -t, --tty 分配一个伪终端
docker run -it ubuntu bash

# 示例:进入Python交互环境
docker run -it python:3.11 python

清理容器

# --rm 容器退出后自动删除
docker run --rm nginx

查看容器

查看运行中的容器

docker ps

# 只显示容器ID
docker ps -q

# 显示完整信息(包括停止的)
docker ps -a

# 显示最后创建的容器
docker ps -l

# 显示最近N个容器
docker ps -n 5

输出说明:

CONTAINER ID   IMAGE      COMMAND                  CREATED       STATUS       PORTS               NAMES
a1b2c3d4e5f6   nginx      "/docker-entrypoint.…"   2 hours ago   Up 2 hours   0.0.0.0:80->80/tcp  my-nginx
  • CONTAINER ID:容器ID(前12位)
  • IMAGE:使用的镜像
  • COMMAND:启动命令
  • CREATED:创建时间
  • STATUS:状态(Up X hours/Exited with code X)
  • PORTS:端口映射
  • NAMES:容器名称

查看容器详细信息

docker inspect 容器名或ID

# 查看容器的IP地址
docker inspect my-nginx | grep IPAddress

停止和启动容器

停止容器

# 优雅停止(发送SIGTERM信号,等待10秒)
docker stop my-nginx

# 强制停止(发送SIGKILL信号,立即终止)
docker kill my-nginx

# 停止所有容器
docker stop $(docker ps -q)

# 停止多个容器
docker stop my-nginx my-redis

启动容器

# 启动已停止的容器
docker start my-nginx

# 启动所有停止的容器
docker start $(docker ps -a -q)

重启容器

docker restart my-nginx

删除容器

删除单个容器

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

# 强制删除运行中的容器
docker rm -f my-nginx

批量删除

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

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

# 删除所有Exited状态的容器
docker rm $(docker ps -q -f status=exited)

注意:删除容器不会删除镜像。

查看容器日志

# 查看容器日志
docker logs my-nginx

# 实时查看日志(类似tail -f)
docker logs -f my-nginx

# 查看最后N行
docker logs --tail 100 my-nginx

# 查看最近N分钟的日志
docker logs --since 10m my-nginx

# 查看指定时间的日志
docker logs --since "2023-01-01T00:00:00" my-nginx

# 显示时间戳
docker logs -t my-nginx

进入容器

docker exec

# 进入容器的交互式终端
docker exec -it my-nginx bash

# 在容器内执行命令
docker exec my-nginx ls /usr/share/nginx/html

# 在容器内执行命令并返回结果
docker exec my-nginx cat /etc/nginx/nginx.conf

常用场景:

  1. 调试容器内的问题
  2. 查看容器内的文件
  3. 在容器内执行维护操作

docker attach

# 附加到容器的主进程
docker attach my-nginx

区别:

  • docker exec:启动新进程进入容器
  • docker attach:附加到容器的主进程

推荐使用docker exec,更安全可控。

容器内文件操作

复制文件到容器

# 复制本地文件到容器
docker cp index.html my-nginx:/usr/share/nginx/html/

# 复制本地目录到容器
docker cp ./data my-nginx:/app/

从容器复制文件到本地

docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf
docker cp my-nginx:/var/log/nginx ./logs/

场景:备份容器内的配置文件和日志。

容器资源监控

查看资源使用情况

# 查看所有容器的资源使用
docker stats

# 只显示指定容器
docker stats my-nginx

# 只显示一次(不持续更新)
docker stats --no-stream my-nginx

输出说明:

CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O       BLOCK I/O   PIDS
a1b2c3d4e5f6   my-nginx  0.00%     5.5MiB / 1GiB       0.54%     1.2kB / 0B    0B / 0B     3
  • CPU %:CPU使用率
  • MEM USAGE / LIMIT:内存使用情况
  • NET I/O:网络输入/输出
  • BLOCK I/O:磁盘读写
  • PIDS:进程数量

容器更新

更新容器的配置

# 更新容器重启策略
docker update --restart=always my-nginx

# 更新资源限制
docker update -m 1g --cpus 1 my-nginx

# 更新多个容器
docker update --restart=always my-nginx my-redis

容器导出和导入

导出容器

# 导出容器为tar文件
docker export my-nginx > my-nginx.tar

# 导出容器
docker export -o my-nginx.tar my-nginx

导入容器

# 导入为镜像
docker import my-nginx.tar my-nginx-imported:latest

区别

  • docker save/load:导出/导入镜像(包含镜像的所有层)
  • docker export/import:导出/导入容器(只包含容器当前状态)

容器实战

实战1:运行一个Web应用

# 1. 运行一个Flask应用
docker run -d -p 8000:8000 --name my-flask python:3.11 \
  python -m http.server 8000

# 2. 访问
curl http://localhost:8000

# 3. 查看日志
docker logs -f my-flask

# 4. 停止容器
docker stop my-flask

实战2:运行一个数据库

# 1. 运行MySQL
docker run -d \
  --name my-mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -e MYSQL_DATABASE=mydb \
  -p 3306:3306 \
  mysql:8.0

# 2. 等待MySQL启动
docker logs -f my-mysql

# 3. 连接MySQL
docker exec -it my-mysql mysql -uroot -p123456

# 4. 在MySQL内执行
CREATE DATABASE testdb;
SHOW DATABASES;
EXIT;

# 5. 停止容器
docker stop my-mysql

实战3:数据持久化

# 1. 创建数据卷
docker volume create mysql-data

# 2. 使用数据卷运行MySQL
docker run -d \
  --name my-mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# 3. 插入一些数据
docker exec -it my-mysql mysql -uroot -p123456 -e \
  "CREATE DATABASE testdb; USE testdb; CREATE TABLE users (id INT, name VARCHAR(100)); INSERT INTO users VALUES (1, 'Alice');"

# 4. 删除容器
docker rm -f my-mysql

# 5. 用新容器恢复数据
docker run -d \
  --name my-mysql-new \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# 6. 验证数据还在
docker exec -it my-mysql-new mysql -uroot -p123456 -e "USE testdb; SELECT * FROM users;"

容器排错技巧

1. 查看容器日志

docker logs my-nginx

2. 进入容器查看

docker exec -it my-nginx bash

3. 查看容器状态

docker inspect my-nginx

4. 查看容器进程

docker top my-nginx

5. 查看容器网络

docker inspect my-nginx | grep -A 20 Networks

本章小结

  • 容器生命周期:创建、启动、运行、停止、删除
  • docker run选项:后台运行、端口映射、环境变量、数据卷等
  • 容器管理:查看、停止、启动、重启、删除
  • 日志和排错:查看日志、进入容器、查看状态
  • 资源监控:查看CPU、内存、网络、磁盘使用情况

现在已经掌握了容器操作,下一章我们来学习Dockerfile!

继续学下去,马上就能构建自己的镜像了!