05-容器操作-运行你的第一个程序
容器是镜像的运行实例
前几章我们说镜像是"模板",容器就是"根据模板做出来的实例"。今天深入学习容器的操作。
容器的生命周期
┌─────────┐ 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
常用场景:
- 调试容器内的问题
- 查看容器内的文件
- 在容器内执行维护操作
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!
继续学下去,马上就能构建自己的镜像了!