Files
docker_practice/05_container/5.1_run.md
T
yeasy ac5ec03ab5 fix(安全,版本): seccomp 示例是安全降级,另修三处凭据/暴露面与九处版本过时
安全(四条,前三条都是书自己打自己):

- 18.5 的自定义 seccomp 示例用 `"defaultAction": "SCMP_ACT_ALLOW"` 写了一个
  blocklist。但 `--security-opt seccomp=<file>` 是**整体替换**默认 profile
  而非叠加(官方 seccomp 文档:容器"uses the default profile unless you
  override it"),而默认 profile 恰恰是 deny-by-default 的 allowlist——本节
  第 11 行自己就这么写的。净效果是:挡住了 chmod,却把默认拦下的那 ~44 个
  高危调用(unshare / keyctl / add_key / bpf / perf_event_open / init_module
  / reboot 等)全部放行,**比不加这个参数更危险**,而读者会以为自己加固了。
  改为从官方 default.json 派生,并在示例前置醒目警告。
- 7.6 把 `docker run -e DB_PASSWORD=xxx` 标成「✅ 正确」。它只是把泄漏路径
  从镜像换到了别处:进 shell history、进宿主机进程 argv(同机任何用户 ps
  可见)、并永久固化在 `docker inspect` 的 Config.Env 里。而本书 11.8:102
  明写「不要把数据库密码写入 compose.yaml、.env、**命令行** 或 Git」,
  16.3:251 也要求「避免把真实口令写入命令历史」。改为标注 -e 的泄漏面,
  并给出 --env-file / Compose secrets 的正确做法。
- 6.2 教读者起一个**无认证、无 TLS** 的 registry,且引导把它绑到内网地址、
  开 insecure-registries,全节零安全提示。同网段任意主机可匿名 push,即
  镜像投毒。而 18.3:17 用最强语气写着「绝不能在没有任何安全控制的情况下
  强行开启」。示例改为绑 127.0.0.1,并在两处补上风险说明与指向 6.3 的出口。
- 18.6 的 CI 示例里,Trivy 那条注释写着「务必使用不可变的 commit SHA 引用,
  而非可变标签」(引的是 2026-03-19 Trivy Actions 76 个 tag 被劫持事件),
  可同一 workflow 里另外九条 uses 全是可变标签,包括持有凭据的
  docker/login-action。补一段说明点破这一点。(本仓库自己的
  .github/workflows/ 确实全部按 SHA 钉死,已实测确认后才写进书里。)

版本时效(对 GitHub releases / endoflife.date / docs.docker.com 逐条核实):

- 5.1 与 6.3 说 `ubuntu:24.04`「是最新 LTS」——最新 LTS 已是 26.04
  (2026-04-23 发布);而本书 3.1 早就列出了 26.04,属书内不一致。更糟的是
  5.1 建议可替换为 `ubuntu:20.04`,而 3.1:33 正警告 20.04 已不在支持列表。
- 3.1 的支持列表里的 Ubuntu 25.10 已被 Docker 官方安装文档移除(该版本本身
  也已于 2026-07-01 EOL),删去。
- 4.6 拿 `alpine:3.20` 当"锁定版本以确保可重现性"的范例,而 3.20 已于
  2026-04 EOL;改为 3.24。
- 3.2 的「Debian Bullseye 11 将于 2026 年 8 月底结束长期支持」时态已过期。
- kind v0.31.0 → v0.33.0(落后两个小版本);etcd v3.5.29 → v3.5.33。
- 10_buildx/README 推荐「Docker v28 及以上」,而紧接着的段落就在用
  「自 Docker Engine 29 起」立论;改为 v29。
2026-09-04 14:53:09 -07:00

5.3 KiB
Raw Blame History

5.1 启动

本节将详细介绍 Docker 容器的启动方式,包括新建启动和重新启动已停止的容器。

5.1.1 启动方式概述

启动容器有两种方式:

  • 新建并启动:基于镜像创建新容器
  • 重新启动:将已终止的容器重新运行

由于 Docker 容器非常轻量,实际使用中常常是随时删除和新建容器,而不是反复重启同一个容器。

5.1.2 新建并启动

基本语法

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

最简单的例子

输出 “Hello World” 后容器自动终止:

$ docker run ubuntu:24.04 /bin/echo 'Hello world'
Hello world

这与直接执行 /bin/echo 'Hello world' 几乎没有区别,但实际上已经启动了一个完整的 Ubuntu 容器来执行这条命令。

版本说明:示例使用 ubuntu:24.04,这是仍受 Docker 支持的 LTS 版本(当前最新 LTS 为 26.04)。如需其他版本,可替换为 ubuntu:26.04、ubuntu:22.04 等;不要用已不在支持列表中的 ubuntu:20.04(见 3.1 节)。

交互式容器

启动一个可以交互的 bash 终端:

$ docker run -it ubuntu:24.04 /bin/bash
root@af8bae53bdd3:/#

参数说明:

参数 作用
-i 保持标准输入 (stdin) 打开,允许输入
-t 分配伪终端 (pseudo-TTY),提供终端界面
-it 两者组合使用,获得交互式终端

在交互模式下可以执行命令:

root@af8bae53bdd3:/# pwd
/
root@af8bae53bdd3:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@af8bae53bdd3:/# exit  # 退出容器

5.1.3 docker run 的完整流程

执行 docker run 时,Docker 在后台完成以下操作:

flowchart TD
    Cmd["docker run ubuntu:24.04 /bin/echo 'Hello'"] --> Step1

    Step1{"1. 检查本地是否有 ubuntu:24.04 镜像"}
    Step1 -- 有 --> Step1_Yes["使用本地镜像"]
    Step1 -- 无 --> Step1_No["从 Registry 下载"]

    Step1_Yes --> Step2
    Step1_No --> Step2

    Step2["2. 创建容器<br/>• 基于镜像的只读层<br/>• 添加一层可读写层(容器存储层)"] --> Step3
    Step3["3. 配置网络<br/>• 创建虚拟网卡<br/>• 分配 IP 地址<br/>• 连接到 Docker 网桥"] --> Step4
    Step4["4. 启动容器,执行指定命令"] --> Step5
    Step5["5. 命令执行完毕,容器停止"]

5.1.4 常用启动选项

基础选项

选项 说明 示例
-d 后台运行 (detach) docker run -d nginx:latest
-it 交互式终端 docker run -it ubuntu:24.04 bash
--name 指定容器名称 docker run --name myapp nginx:latest
--rm 退出后自动删除容器 docker run --rm ubuntu:24.04 echo hi

端口映射

## 将容器的 80 端口映射到宿主机的 8080 端口

$ docker run -d -p 8080:80 nginx:latest

## 随机映射端口

$ docker run -d -P nginx:latest

## 只绑定到 localhost

$ docker run -d -p 127.0.0.1:8080:80 nginx:latest

数据卷挂载

## 挂载命名卷

$ docker run -v mydata:/data nginx:latest

## 挂载宿主机目录

$ docker run -v /host/path:/container/path nginx:latest

## 只读挂载

$ docker run -v /host/path:/container/path:ro nginx:latest

环境变量

## 设置单个环境变量

$ docker run -e MYSQL_ROOT_PASSWORD=secret mysql

## 从文件加载环境变量

$ docker run --env-file .env myapp

资源限制

## 限制内存

$ docker run -m 512m nginx:latest

## 限制 CPU

$ docker run --cpus=1.5 nginx:latest

5.1.5 启动已终止容器

使用 docker start 重新启动已停止的容器:

## 查看所有容器(包括已停止的)

$ docker ps -a
CONTAINER ID  IMAGE   STATUS                     NAMES
af8bae53bdd3  ubuntu  Exited (0) 2 minutes ago   myubuntu

## 重新启动

$ docker start myubuntu

## 启动并附加终端

$ docker start -ai myubuntu

5.1.6 容器内进程的特点

容器内只运行指定的应用程序及其必需资源:

root@ba267838cc1b:/# ps
  PID TTY          TIME CMD
    1 ?        00:00:00 bash
   11 ?        00:00:00 ps

可见容器中仅运行了 bash 进程。这种特点使得 Docker 对资源的利用率极高。

💡 笔者提示:容器内的 PID 1 进程很重要——它是容器的主进程,该进程退出则容器停止。详见后台运行章节。

5.1.7 常见问题

Q:容器启动后立即退出

原因:主进程执行完毕或无法保持运行

## 这个容器会立即退出(echo 执行完就结束了)

$ docker run ubuntu:24.04 echo "hello"

## 解决:使用能持续运行的命令

$ docker run -d nginx:latest  # nginx 是持续运行的服务

详细解释见后台运行。

Q:无法连接容器内的服务

原因:未正确映射端口

## 错误:没有 -p 参数,外部无法访问

$ docker run -d nginx:latest

## 正确:映射端口

$ docker run -d -p 80:80 nginx:latest

Q:容器内修改的文件丢失

原因:未使用数据卷,数据保存在容器存储层

## 使用数据卷持久化

$ docker run -v mydata:/app/data myapp

详见数据管理。