一、学习目标

  1. 理解容器端口映射的概念和作用

  2. 掌握 -p 参数的各种用法

  3. 实战:运行 Nginx 容器并通过浏览器访问

  4. 了解容器的资源限制(CPU、内存)

二、端口映射详解

1. 为什么需要端口映射?

容器拥有自己独立的网络命名空间,容器内的端口(如 Nginx 的 80)只暴露在容器内部。要从宿主机或外部网络访问容器内的服务,必须将宿主机端口映射到容器端口

外部访问流程:
浏览器 → 宿主机IP:宿主机端口 → 容器IP:容器端口 → 服务

2. 端口映射命令 -p

基本语法:

docker run -p [宿主机IP:]宿主机端口:容器端口[/协议] 镜像名

常用形式

格式 示例 说明
-p 宿主机端口:容器端口 -p 8080:80 宿主机所有IP的8080映射到容器80
-p IP:宿主机端口:容器端口 -p 127.0.0.1:8080:80 只绑定本地回环地址
-p 容器端口 -p 80 随机映射宿主机端口(较少用)
-p 宿主机端口:容器端口/udp -p 53:53/udp 指定 UDP 协议(默认 TCP)
-P(大写) -P 将容器所有 EXPOSE 的端口随机映射

3. 端口映射示例

# 基础用法:宿主机8080 → 容器80
docker run -d -p 8080:80 nginx

# 绑定多个端口
docker run -d -p 8080:80 -p 8443:443 nginx

# 绑定到指定IP(多网卡时有用)
docker run -d -p 127.0.0.1:8080:80 nginx

# UDP 端口映射(如 DNS)
docker run -d -p 53:53/udp --name dns-server some-dns

# 随机端口映射(查看命令:docker port 容器名)
docker run -d -P nginx
docker port 容器名  # 查看随机映射的端口

4. 查看端口映射

# 方法1:docker ps(显示 PORTS 列)
docker ps

# 方法2:docker port 命令
docker port 容器名
# 输出:80/tcp -> 0.0.0.0:8080

# 方法3:docker inspect
docker inspect 容器名 | grep -A 5 "PortBindings"

三、实战:运行 Nginx 并访问

步骤 1:拉取 Nginx 镜像(可选)

docker pull nginx:alpine   # 轻量级版本

步骤 2:后台运行 Nginx 并映射端口

docker run -d --name my-nginx -p 8080:80 nginx:alpine
  • -d:后台运行

  • --name my-nginx:容器命名

  • -p 8080:80:宿主机 8080 → 容器 80

  • nginx:alpine:使用轻量版 Nginx

步骤 3:验证容器运行状态

docker ps
# 输出示例:
# CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                  NAMES
# abcd1234       nginx:alpine   "/docker-entrypoint.…"   5 seconds ago   Up 4 seconds   0.0.0.0:8080->80/tcp   my-nginx

步骤 4:访问 Nginx 欢迎页

方式一:使用 curl 命令

curl http://localhost:8080
# 或
curl http://127.0.0.1:8080

应该能看到 HTML 输出,包含 "Welcome to nginx"。

方式二:浏览器访问
打开浏览器,地址栏输入 http://localhost:8080 或 http://你的虚拟机IP:8080(如果是远程服务器)。

步骤 5:修改 Nginx 默认页面(可选)

# 进入容器
docker exec -it my-nginx /bin/sh

# 修改首页
echo "<h1>Hello from Docker!</h1>" > /usr/share/nginx/html/index.html

# 退出容器
exit

# 刷新浏览器,页面内容已改变

步骤 6:停止并清理

docker stop my-nginx
docker rm my-nginx

四、资源限制

1. 为什么要限制资源?

默认情况下,容器可以无限制使用宿主机资源。为防止某个容器耗尽所有 CPU 或内存,需要设置资源限制。

2. 内存限制

# 语法
docker run -m <值> --memory-swap <值> ...

# 常用参数
-m, --memory           # 最大内存限制(如 -m 512m)
--memory-swap          # 内存+swap的总限制(-m 512m --memory-swap 1g → 内存512M + swap512M)
--memory-reservation   # 软限制,尽力保证
--memory-swappiness    # 容器使用swap的倾向(0-100,默认60)
--oom-kill-disable     # 超出内存时是否杀死容器

# 示例
docker run -d --name limited-nginx -m 256m nginx

单位说明b(字节)、k(KB)、m(MB)、g(GB)

3. CPU 限制

# 方式一:指定 CPU 份额(相对权重,默认1024)
--cpu-shares 512    # 该容器 CPU 权重为 512,其他为 1024 时,它占用一半

# 方式二:限制使用的 CPU 核心数(推荐)
--cpus 1.5          # 最多使用 1.5 个 CPU 核心

# 方式三:指定使用哪些 CPU 核心(绑定)
--cpuset-cpus "0,2"     # 只使用 CPU 0 和 2
--cpuset-cpus "0-3"     # 使用 CPU 0-3

# 方式四:CPU 时间配额(更精细)
--cpu-period 100000     # 调度周期(微秒)
--cpu-quota 50000       # 每个周期内分配的时间(微秒),即 0.5 核

4. 综合示例:同时限制 CPU 和内存

docker run -d \
  --name limited-nginx \
  -p 8080:80 \
  --cpus 0.5 \
  --memory 256m \
  --memory-swap 512m \
  nginx

限制:

  • 最多使用 0.5 个 CPU 核心

  • 内存上限 256MB

  • swap 上限 512MB(即额外 256MB swap)

5. 查看资源使用情况

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

# 查看特定容器
docker stats limited-nginx

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

# 格式化输出
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

6. 压力测试资源限制(可选)

使用 stress 工具测试:

# 运行一个 Ubuntu 容器,安装 stress
docker run -it --name stress-test --memory 256m ubuntu:22.04 /bin/bash

# 在容器内安装 stress
apt update && apt install -y stress

# 尝试分配 300MB 内存(超出限制)
stress --vm 1 --vm-bytes 300M --vm-keep

# 观察容器是否被 OOM Kill(可能需要另开终端查看 docker stats)

五、综合实战:运行一个 WordPress 博客(多容器)

这个实战会用到端口映射和资源限制,同时引入多容器协作的概念(更多内容在后续 Docker Compose 中深入)。

# 1. 运行 MySQL 容器(后台,限制资源)
docker run -d \
  --name wordpress-db \
  -e MYSQL_ROOT_PASSWORD=rootpass \
  -e MYSQL_DATABASE=wordpress \
  -e MYSQL_USER=wpuser \
  -e MYSQL_PASSWORD=wppass \
  --memory 512m \
  --cpus 0.5 \
  mysql:8.0

# 2. 运行 WordPress 容器,映射端口 8888:80
docker run -d \
  --name wordpress-app \
  -p 8888:80 \
  -e WORDPRESS_DB_HOST=wordpress-db:3306 \
  -e WORDPRESS_DB_USER=wpuser \
  -e WORDPRESS_DB_PASSWORD=wppass \
  -e WORDPRESS_DB_NAME=wordpress \
  --memory 256m \
  --cpus 0.3 \
  wordpress:latest

# 3. 查看容器状态
docker ps

# 4. 浏览器访问 http://localhost:8888,完成 WordPress 安装向导

# 5. 清理(运行完后可删除)
docker stop wordpress-app wordpress-db
docker rm wordpress-app wordpress-db

六、端口映射常见问题

Q1:端口已被占用怎么办?

错误信息bind: address already in use
解决方案

# 换一个宿主机端口
docker run -d -p 8081:80 nginx

# 或杀死占用端口的进程(Linux)
sudo lsof -i :8080
sudo kill -9 <PID>

Q2:如何让容器使用宿主机的网络栈(不隔离)?

docker run -d --network host nginx

此时容器直接使用宿主机的 IP 和端口(-p 无效),访问 http://宿主机IP 即可。

Q3:容器内服务监听在 127.0.0.1 而非 0.0.0.0?

有些应用默认只监听本地回环,需要在容器内修改配置为 0.0.0.0

Q4:Windows/macOS 上无法通过 localhost 访问?

Docker Desktop 默认可以,如果不行尝试使用 127.0.0.1 或 192.168.x.x(docker0 网桥 IP)。


七、资源限制最佳实践

  1. 生产环境必须设置资源限制,防止容器失控影响宿主机

  2. 内存限制要留有余地-m 设置的值应略高于应用正常运行所需

  3. CPU 限制使用 --cpus 更直观(Docker 1.13+)

  4. 监控资源使用docker stats 或集成监控系统(Prometheus + cAdvisor)

  5. 测试时模拟限制:使用压力工具验证限制是否生效


八、课后练习

练习 1:运行多个 Nginx 实例

# 启动三个 Nginx,映射不同端口
docker run -d --name web1 -p 8081:80 nginx
docker run -d --name web2 -p 8082:80 nginx
docker run -d --name web3 -p 8083:80 nginx

# 分别 curl 验证
curl http://localhost:8081
curl http://localhost:8082
curl http://localhost:8083

# 清理
docker stop web1 web2 web3 && docker rm web1 web2 web3

练习 2:资源限制实验

# 启动一个内存限制为 128M 的 Ubuntu 容器
docker run -it --memory 128m ubuntu:22.04 /bin/bash

# 安装 stress
apt update && apt install -y stress

# 分配 200M 内存(预期 OOM kill)
stress --vm 1 --vm-bytes 200M --timeout 10s

# 观察结果

练习 3:查看端口映射的多种方法

# 启动 Redis 容器,映射 6379
docker run -d --name myredis -p 6380:6379 redis

# 使用不同方式查看映射
docker port myredis
docker inspect myredis | grep -A 5 "PortBindings"
docker ps --format "table {{.Names}}\t{{.Ports}}"

# 清理
docker stop myredis && docker rm myredis

九、下一步预告

第五天将学习:

  • 数据持久化(Volume 挂载)

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

  • docker cp 文件复制

今日检查清单

  • 理解端口映射的作用和语法

  • 能成功运行 Nginx 并通过浏览器访问

  • 掌握查看端口映射的方法

  • 能设置容器的 CPU 和内存限制

  • 会使用 docker stats 监控资源

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐