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

相关推荐
cqsztech10 小时前
docker环境下 Oracle 19c 标准版如何转换为19c 企业版
docker·oracle·容器
❀͜͡傀儡师11 小时前
docker部署 paperless-ngx
运维·docker·容器
卌卄11 小时前
Linux下安装Docker
linux·运维·docker
派阿喵搞电子11 小时前
配置srs的鉴权时遇到的问题
服务器·docker·容器·srs
Archie_IT12 小时前
openEuler 软件生态深度勘探:从六万软件包到多语言融合
linux·容器·性能测试·openeuler·多语言开发
❀͜͡傀儡师14 小时前
K8s 部署Doris 高可用集群
云原生·容器·kubernetes
月亮!14 小时前
移动端测试重磅升级:跨平台自动化测试框架深度对比
运维·网络·人工智能·测试工具·容器·自动化·测试用例
凯子坚持 c14 小时前
Docker 容器全生命周期管理与运维命令深度解析
运维·docker·php