一、学习目标

  1. 理解前台运行与后台运行的区别

  2. 掌握 docker run -d 后台运行容器

  3. 掌握 docker exec -it 进入运行中的容器

  4. 学会使用 docker logs 查看容器日志

  5. 通过 Redis 实战巩固所学知识


二、前台运行 vs 后台运行

1. 前台运行(默认)

当不加 -d 参数时,容器会前台运行,容器的输出会直接打印在当前终端,并且终端会被“占用”。

# 前台运行 Nginx
docker run --name my-nginx nginx

特征:

  • 终端被容器进程“粘住”,无法执行其他命令

  • 按 Ctrl+C 会停止容器

  • 容器的日志实时显示在当前终端

2. 后台运行(detached mode)

使用 -d 参数让容器在后台运行,终端立即返回容器 ID。

# 后台运行 Nginx
docker run -d --name my-nginx nginx

特征:

  • 终端不被占用,可以继续执行其他命令

  • 容器在后台运行,不会因终端关闭而停止(除非使用 --rm)

  • 需要通过 docker logs 查看输出

对比总结

特性前台运行后台运行 (-d)
终端占用是否
Ctrl+C 行为停止容器无影响(只结束当前命令)
查看日志直接看到需用 docker logs
适用场景调试、开发生产环境、服务长期运行

三、交互式运行 -it

-it 是两个参数的组合:

  • -i(interactive):保持 STDIN 打开,允许输入

  • -t(tty):分配一个伪终端,让命令看起来像在普通终端中执行

通常用于需要与容器进行交互的场景(如执行 shell)。

# 交互式运行 Ubuntu,进入 bash
docker run -it --name my-ubuntu ubuntu:22.04 /bin/bash

# 进入后可以执行命令
root@container-id:/# ls
root@container-id:/# apt update
root@container-id:/# exit   # 退出并停止容器

注意:交互式运行默认为前台模式,退出(exit)后容器会停止。


四、核心命令详解

1. docker exec - 进入运行中的容器

在已运行的容器内执行新命令,最常用的场景是打开一个 shell。

# 语法
docker exec [选项] 容器名/ID 命令

# 常用选项
-d          # 后台执行命令(不进入交互)
-i          # 保持 STDIN 打开
-t          # 分配伪终端
-e          # 设置环境变量
-w          # 指定工作目录

# 示例1:进入容器并打开 bash
docker exec -it my-nginx /bin/bash

# 示例2:直接在容器内执行一条命令(不进入)
docker exec my-nginx ls /etc/nginx

# 示例3:以指定用户执行命令
docker exec -u root -it my-nginx /bin/bash

# 示例4:后台执行命令
docker exec -d my-nginx touch /tmp/hello.txt

注意:docker exec -it 进入的 shell 退出后,容器不会停止(因为容器主进程还在运行)。

2. docker logs - 查看容器日志

查看容器内部进程输出的 stdout/stderr。

# 语法
docker logs [选项] 容器名/ID

# 常用选项
-f, --follow       # 实时跟踪日志输出(类似 tail -f)
--tail <行数>      # 显示最后 n 行
--since <时间>     # 显示指定时间后的日志(如 2024-01-01T10:00:00 或 1h)
--until <时间>     # 显示指定时间前的日志
-t, --timestamps   # 显示时间戳

# 示例
docker logs my-nginx              # 查看所有日志
docker logs -f my-nginx           # 实时跟踪
docker logs --tail 100 my-nginx   # 最后100行
docker logs --since 30m my-nginx  # 最近30分钟
docker logs -t my-nginx           # 带时间戳

五、综合实战:运行 Redis 容器并进行交互操作

场景描述

运行一个 Redis 容器(后台模式),然后通过 docker exec 进入容器并使用 Redis CLI 执行 set 和 get 命令。

步骤详解

步骤 1:拉取 Redis 镜像(如果本地没有)
docker pull redis:alpine
步骤 2:后台运行 Redis 容器
docker run -d --name my-redis -p 6379:6379 redis:alpine
  • -d:后台运行

  • --name my-redis:容器命名为 my-redis

  • -p 6379:6379:将宿主机的 6379 端口映射到容器的 6379 端口(可选,便于外部连接)

  • redis:alpine:轻量级 Redis 镜像

步骤 3:查看容器是否正常运行
docker ps
# 应该看到 my-redis 状态为 Up
步骤 4:查看 Redis 日志
docker logs my-redis
# 输出类似:Ready to accept connections
步骤 5:进入 Redis 容器并执行命令

方法一:直接执行 redis-cli 命令(不进入交互 shell)

docker exec -it my-redis redis-cli
# 进入 redis-cli 交互界面
127.0.0.1:6379> set name docker
OK
127.0.0.1:6379> get name
"docker"
127.0.0.1:6379> exit

方法二:先进入容器的 shell,再执行 redis-cli

# 进入容器的 /bin/sh(Alpine 默认没有 bash)
docker exec -it my-redis /bin/sh

# 现在在容器内部
/data # redis-cli
127.0.0.1:6379> set city Shanghai
OK
127.0.0.1:6379> get city
"Shanghai"
127.0.0.1:6379> exit

# 退出容器 shell
/data # exit
步骤 6:验证数据持久性(可选)
# 停止并删除容器
docker stop my-redis
docker rm my-redis

# 重新运行一个新 Redis 容器(相同镜像,不同数据目录)
docker run -d --name my-redis-new redis:alpine

# 进入后尝试获取之前的 key
docker exec -it my-redis-new redis-cli
127.0.0.1:6379> get name
(nil)   # 数据丢失,因为容器删除后数据没有持久化

说明:Redis 数据默认保存在容器内部,删除容器后数据会丢失。数据持久化需要使用 Volume,将在后续课程学习。


六、进阶:组合命令使用技巧

1. 后台运行 + 立即进入 shell

有时候你希望容器在后台运行,但同时进入 shell 进行操作:

docker run -d --name my-ubuntu ubuntu:22.04 sleep infinity
docker exec -it my-ubuntu /bin/bash

注意:Ubuntu 容器如果不指定持续运行的命令,会立即退出。sleep infinity 可以让容器一直运行。

2. 查看容器内运行的进程

docker exec my-redis ps aux
# 或者使用 docker top
docker top my-redis

3. 在容器内后台执行长时间任务

docker exec -d my-ubuntu sh -c "while true; do echo hello >> /tmp/log; sleep 10; done"

4. 实时跟踪日志并过滤

docker logs -f my-nginx 2>&1 | grep "error"

七、常见问题与注意事项

Q1:为什么我运行 docker run ubuntu 后容器立刻退出了?

A:Ubuntu 镜像的默认命令是 /bin/bash,但如果没有交互式终端(-it),bash 会立即退出。解决方法:

  • 交互式运行:docker run -it ubuntu

  • 后台运行并指定持续命令:docker run -d ubuntu sleep infinity

Q2:docker exec 提示 "container is not running"

A:容器已停止。使用 docker start 容器名 启动后再 exec。

Q3:如何优雅地停止容器?

A:使用 docker stop(发送 SIGTERM,等待 10 秒后强制 SIGKILL)。如果需要立即强制停止,用 docker kill。

Q4:docker logs 显示太多内容怎么办?

A:使用 --tail 限制行数,或使用 --since 限定时间范围。

八、课后练习

练习 1:运行一个 MySQL 容器

# 后台运行 MySQL,设置 root 密码
docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0

# 进入容器并登录 MySQL
docker exec -it my-mysql mysql -uroot -p123456

# 在 MySQL 中创建一个数据库并查看
CREATE DATABASE testdb;
SHOW DATABASES;
EXIT;

练习 2:使用 docker logs 排查问题

# 故意运行一个错误命令的容器
docker run --name bad-container nginx:alpine sh -c "exit 1"

# 查看容器状态(应该为 Exited)
docker ps -a | grep bad-container

# 查看退出容器的日志(如果没有输出,可以用 docker inspect 查看退出码)
docker logs bad-container
docker inspect bad-container | grep -i "exitcode"

练习 3:写一个简单的脚本监控容器日志

#!/bin/bash
# monitor.sh
CONTAINER_NAME=$1
docker logs -f --tail 20 $CONTAINER_NAME

九、下一步学习预告

第四天将学习:

  • 数据持久化(Volume 挂载)

  • 容器与宿主机之间的文件复制(docker cp)

  • 解决 Redis/MySQL 容器删除后数据丢失的问题

今天任务完成标准:

  • 能正确区分前台与后台运行

  • 熟练使用 docker exec -it 进入容器

  • 能查看和跟踪容器日志

  • 成功运行 Redis 容器并执行 set/get 命令

更多推荐