Docker容器启动中需要增加一个端口

已经在运行的 Docker 容器:不能"直接新开端口映射"

✅ 但你有 2 种可行补救方案,不需要重建业务环境

下面我按真实可操作顺序给你说清楚。


✅ 一、为什么"跑着的 Docker 不能直接加端口"?

你启动容器时用的命令类似:

bash 复制代码
docker run -p 80:80 nginx

端口映射是在 容器创建阶段 固定写入的,

运行后 Docker 内部的 iptables 规则已经生成:

🔒 运行中 无法动态修改端口映射规则

所以这个命令是 不存在的(很多人会误以为有):

bash 复制代码
❌ docker port add xxxx   # 不存在

✅ 二、方案 1(✅ 推荐):停止 → 重建容器 → 重新映射端口

这是 最标准、最安全、100%可控方案

✅ 第零步:确认当前容器是否发生过环境变更

基于备份无大错的思路,建议,对当前容器进行备份保存,并保留下来docker信息

1️⃣基本信息
shell 复制代码
root@xiaocai:~# docker ps
CONTAINER ID   IMAGE                       COMMAND                   CREATED      STATUS         PORTS                                         NAMES
042b02e76d3d   nginx:1.27.0                "/docker-entrypoint...."   8 days ago   Up 4 minutes   0.0.0.0:80->80/tcp, [::]:80->80/tcp           nginx
2️⃣保存当前容器基本信息
shell 复制代码
root@xiaocai:/data/docker# cd /data/docker/backups/
root@xiaocai:/data/docker/backups# ls
root@xiaocai:/data/docker/backups# # 备份 nginx 容器的 inspect 信息
root@xiaocai:/data/docker/backups# docker inspect 042b02e76d3d > nginx_042b02e76d3d_$(date +%Y%m%d).json
root@xiaocai:/data/docker/backups# 
root@xiaocai:/data/docker/backups# # 顺手把 ps 结果也存一下(包含命令行、镜像等)
root@xiaocai:/data/docker/backups# docker ps --no-trunc | grep 042b02e76d3d >> docker_ps_backup_$(date +%Y%m%d).txt
root@xiaocai:/data/docker/backups# ls
docker_ps_backup_20251204.txt  nginx_042b02e76d3d_20251204.json
3️⃣ 对当前容器做一个镜像快照

给这个容器拍个"系统镜像",防止你在容器里动过环境(装包、改配置)再也复现不出来:

复制代码
docker commit 042b02e76d3d nginx-snapshot:20251204`
4️⃣停掉并删除旧容器(只删容器,不动数据卷)
复制代码
docker stop nginx
docker rm nginx

✅ 第一步:查看当前容器

bash 复制代码
docker ps

假设你的容器叫:

复制代码
nginx

✅ 第二步:停止并删除(不会删数据,前提是你做了 volume 映射)

bash 复制代码
docker stop nginx
docker rm nginx

✅ 第三步:用【原参数 + 新端口】重新启动

例如你现在要加一个 9090 端口:

bash 复制代码
docker run -d \
  --name nginx \
  -p 80:80 \
  -p 8021:8021 \
  -v /data/nginx:/etc/nginx \
  nginx

✅ 这样是 最干净、安全、官方推荐方式


✅ 三、方案 2(⚠️ 应急抢救方案):用 iptables 给运行中容器"硬转发端口"

✅ 不重启容器

❌ 但 重启 Docker 或服务器会失效

❌ 运维规范上不推荐长期使用

✅ 例子:给运行中的容器临时开放 8022 → 8021

🛡️【强烈推荐】iptables 全量备份 & 一键恢复(防止误操作炸整台服务器)

任何大规模改 iptables 之前,都必须先做这一步

这是你现在这套应急方案的终极保险丝


🔐 ①【修改前】完整备份当前所有规则
bash 复制代码
iptables-save > /root/iptables.backup.$(date +%F_%H-%M-%S).rules

✅ 示例生成文件:

text 复制代码
/root/iptables.backup.2025-12-04_17-32-10.rules

✅ 你可以用下面命令查看所有历史备份:

bash 复制代码
ls -lh /root/iptables.backup*.rules

♻️ ②【任意时刻】一键完整恢复到"备份时状态"

🚨 当你出现以下情况,直接执行:

  • 端口全部访问异常

  • SSH 变慢 / 丢包

  • Docker 网络全乱

  • FORWARD 全被挡

✅ 一键恢复命令:
bash 复制代码
iptables-restore < /root/iptables.backup.2025-12-04_17-32-10.rules

⚠️ 注意:

这里的文件名要换成你真实存在的那个备份文件


0️⃣ 查询当前iptables表信息

bash 复制代码
root@xiaocai:~# iptables -t nat -L -n -v --line-numbers
Chain PREROUTING (policy ACCEPT 19 packets, 3019 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        2   104 DOCKER     0    --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 140 packets, 11934 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 DOCKER     0    --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 140 packets, 11934 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 MASQUERADE  0    --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
2        0     0 MASQUERADE  0    --  *      !br-9f7a719c7ff7  172.20.0.0/16        0.0.0.0/0           
3        0     0 MASQUERADE  0    --  *      !br-8c2229fc08be  172.18.0.0/16        0.0.0.0/0           
4        0     0 MASQUERADE  0    --  *      !br-758e39dacb73  172.19.0.0/16        0.0.0.0/0           
5        0     0 MASQUERADE  0    --  *      !br-51b64db485d2  172.21.0.0/16        0.0.0.0/0           
6        0     0 MASQUERADE  0    --  *      !br-045e200a876d  172.22.0.0/16        0.0.0.0/0           
7        1    60 MASQUERADE  0    --  *      !br-e5549e575c2f  172.23.0.0/16        0.0.0.0/0           

Chain DOCKER (2 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 RETURN     0    --  docker0 *       0.0.0.0/0            0.0.0.0/0           
2        0     0 RETURN     0    --  br-9f7a719c7ff7 *       0.0.0.0/0            0.0.0.0/0           
3        0     0 RETURN     0    --  br-8c2229fc08be *       0.0.0.0/0            0.0.0.0/0           
4        0     0 RETURN     0    --  br-758e39dacb73 *       0.0.0.0/0            0.0.0.0/0           
5        0     0 RETURN     0    --  br-51b64db485d2 *       0.0.0.0/0            0.0.0.0/0           
6        0     0 RETURN     0    --  br-045e200a876d *       0.0.0.0/0            0.0.0.0/0           
7        0     0 RETURN     0    --  br-e5549e575c2f *       0.0.0.0/0            0.0.0.0/0           
8        0     0 DNAT       6    --  !br-51b64db485d2 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.21.0.2:80
9        0     0 DNAT       6    --  !br-e5549e575c2f *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.23.0.2:8080

2️⃣查容器 IP

bash 复制代码
root@xiaocai:/data/docker/backups# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx
172.21.0.2

假设得到:

复制代码
172.21.0.2

3️⃣ 确认并开启内核转发

复制代码
sysctl net.ipv4.ip_forward
  • 如果输出是 net.ipv4.ip_forward = 1 → 可以跳过下一条

  • 如果是 0,执行:

    sysctl -w net.ipv4.ip_forward=1

3️⃣ 添加【外部访问用】PREROUTING DNAT

🔹 插入规则
bash 复制代码
iptables -t nat -A PREROUTING -p tcp -d 192.168.1.47 --dport 8022 \
  -j DNAT --to-destination 172.21.0.2:8021

🔹 立即查看"是否插入成功"
bash 复制代码
iptables -t nat -L PREROUTING -n -v --line-numbers | grep 8022
✅ 正常期望
text 复制代码
root@xiaocai:~# iptables -t nat -L PREROUTING -n -v --line-numbers | grep 8022
2        4   208 DNAT       6    --  *      *       0.0.0.0/0            192.168.1.47         tcp dpt:8022 to:172.21.0.2:8021
❌ 如果这一步加错 / 重复了,恢复方式:
方法 1:按行号删(推荐)
复制代码
iptables -t nat -D PREROUTING 2
方法 2:按规则内容删
复制代码
iptables -t nat -D PREROUTING -p tcp -d 192.168.1.47 --dport 8022 -j DNAT --to 172.21.0.2:8021

4️⃣添加【本机访问用】OUTPUT DNAT

🔹 插入规则
bash 复制代码
iptables -t nat -A OUTPUT -p tcp -d 192.168.1.47 --dport 8022 \
  -j DNAT --to-destination 172.21.0.2:8021

🔹 立即验证
bash 复制代码
iptables -t nat -L OUTPUT -n -v --line-numbers | grep 8022
✅ 正常期望
text 复制代码
root@xiaocai:~# iptables -t nat -L OUTPUT -n -v --line-numbers | grep 8022
2        1    60 DNAT       6    --  *      *       0.0.0.0/0            192.168.1.47         tcp dpt:8022 to:172.21.0.2:8021
❌ 如果 OUTPUT 加错 / 重复,恢复方式:
复制代码
iptables -t nat -D OUTPUT 2

或:

复制代码
iptables -t nat -D OUTPUT -p tcp -d 192.168.1.47 --dport 8022 -j DNAT --to 172.21.0.2:8021

✅ 第 5 步:


5️⃣添加【转发放行】FORWARD → 去容器

🔹 插入
bash 复制代码
iptables -I FORWARD 1 -p tcp -d 172.21.0.2 --dport 8021 \
  -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
🔹 查看
bash 复制代码
iptables -L FORWARD -n -v --line-numbers | grep 8021

✅ 期望

text 复制代码
root@xiaocai:~# iptables -L FORWARD -n -v --line-numbers | grep 8021
2       22  2120 ACCEPT     6    --  *      *       0.0.0.0/0            172.21.0.2           tcp dpt:8021 ctstate NEW,RELATED,ESTABLISHED

❌ 如果这一步失败 / 插错,恢复:

复制代码
iptables -D FORWARD 2

6️⃣添加【转发放行】FORWARD → 从容器返回

🔹 插入
bash 复制代码
iptables -I FORWARD 1 -p tcp -s 172.21.0.2 --sport 8021 \
  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
🔹 查看
bash 复制代码
iptables -L FORWARD -n -v --line-numbers | grep 172.21.0.2
✅ 期望看到两条
text 复制代码
root@xiaocai:~# iptables -L FORWARD -n -v --line-numbers | grep 172.21.0.2
1        0     0 ACCEPT     6    --  *      *       172.21.0.2           0.0.0.0/0            tcp spt:8021 ctstate RELATED,ESTABLISHED
2        0     0 ACCEPT     6    --  *      *       0.0.0.0/0            172.21.0.2           tcp dpt:8021 ctstate NEW,RELATED,ESTABLISHED

注意,第5步和第6步一个是d一个是s

❌ 如果第 6 步插错,恢复:
复制代码
iptables -D FORWARD 1

7️⃣本机功能测试(最关键的一步)

bash 复制代码
curl -v http://192.168.1.47:8022/demo001/
✅ 正确结果
html 复制代码
<h1>小菜很帅</h1>

8️⃣外部(Windows)测试

cmd 复制代码
curl -v http://192.168.1.47:8022/demo001/

或浏览器:

text 复制代码
http://192.168.1.47:8022/demo001/
xshell 复制代码
C:\Users\caimingyang>curl http://192.168.1.47:8022/demo001/
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>测试</title>
</head>
<body>
    <h1>小菜很帅</h1>
</body>
</html>

C:\Users\caimingyang>curl http://192.168.1.47/demo001/
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>测试</title>
</head>
<body>
    <h1>小菜很帅</h1>
</body>
</html>

9️⃣最终你现在的"最小正确规则集合"就是这 4 条

bash 复制代码
# 外部访问
iptables -t nat -A PREROUTING -p tcp -d 192.168.1.47 --dport 8022 -j DNAT --to 172.21.0.2:8021

# 本机访问
iptables -t nat -A OUTPUT -p tcp -d 192.168.1.47 --dport 8022 -j DNAT --to 172.21.0.2:8021

# 放行去容器
iptables -I FORWARD 1 -p tcp -d 172.21.0.2 --dport 8021 -j ACCEPT

# 放行从容器返回
iptables -I FORWARD 1 -p tcp -s 172.21.0.2 --sport 8021 -j ACCEPT

相关推荐
功德+n7 小时前
Linux下安装与配置Docker完整详细步骤
linux·运维·服务器·开发语言·docker·centos
小敬爱吃饭8 小时前
Ragflow Docker部署及问题解决方案(界面为Welcome to nginx,ragflow上传文件失败,Docker中的ragflow-cpu-1一直重启)
人工智能·python·nginx·docker·语言模型·容器·数据挖掘
木子欢儿9 小时前
Docker Hub 镜像发布指南
java·spring cloud·docker·容器·eureka
coppher10 小时前
Ubuntu 22.04 amd64 离线安装 Docker 完整教程
linux·docker
虚伪的空想家11 小时前
k8s集群configmap和secrets备份脚本
linux·容器·kubernetes
SXJR11 小时前
k8s中的Pod
云原生·容器·kubernetes
文静小土豆11 小时前
K8s 滚动更新在 Java 应用中的实践与优化
java·容器·kubernetes
w61001046612 小时前
CKA-2026-Ingress
云原生·容器·kubernetes·cka
bloglin9999912 小时前
docker logs 如何一直监听日志输出
运维·docker·容器
说实话起个名字真难啊13 小时前
Docker 入门之网络基础
网络·docker·php