本文目录导读:

- 使用 Docker API(推荐)
- 使用 iptables 动态修改(不重启容器)
- 使用 docker-compose 动态更新
- 高级脚本:完整端口管理工具
- 使用 Python + Docker SDK
- 使用建议
在 Shell 脚本中动态修改容器端口映射,主要有以下几种方法:
使用 Docker API(推荐)
通过更新容器配置
#!/bin/bash
# 方法1:重新创建容器(会丢失数据,除非使用卷)
update_port_mapping() {
local container_name="$1"
local old_port="$2"
local new_port="$3"
# 停止容器
docker stop "$container_name" 2>/dev/null
# 获取容器配置(不包括端口映射)
local config=$(docker inspect "$container_name" --format '{{json .Config}}' | \
jq 'del(.ExposedPorts)' | \
jq 'del(.PortSpecs)')
# 重新创建容器
docker rm "$container_name" 2>/dev/null
docker run -d \
--name "$container_name" \
-p "${new_port}:${old_port}" \
$(echo "$config" | jq -r '.Image') \
$(echo "$config" | jq -r '.Cmd[]' 2>/dev/null | xargs)
}
# 使用示例
update_port_mapping "myapp" 8080 9090
使用 iptables 动态修改(不重启容器)
#!/bin/bash
# 方法2:直接修改 iptables 规则(不重启容器)
modify_iptables_port() {
local container_ip="$1" # 容器IP地址
local old_port="$2"
local new_port="$3"
# 查找并删除旧的 DNAT 规则
iptables -t nat -L DOCKER --line-numbers -n | \
grep "${container_ip}:${old_port}" | \
awk '{print $1}' | \
sort -r | \
while read line; do
iptables -t nat -D DOCKER "$line"
done
# 添加新的 DNAT 规则
iptables -t nat -A DOCKER \
-p tcp --dport "${new_port}" \
-j DNAT --to-destination "${container_ip}:${old_port}"
# 更新防火墙规则
iptables -D DOCKER -p tcp --dport "${old_port}" -j ACCEPT 2>/dev/null
iptables -A DOCKER -p tcp --dport "${new_port}" -j ACCEPT
}
# 使用示例
container_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' myapp)
modify_iptables_port "$container_ip" 8080 9090
使用 docker-compose 动态更新
#!/bin/bash
# 方法3:使用 docker-compose 重新部署
update_compose_port() {
local compose_file="$1"
local service_name="$2"
local old_port="$3"
local new_port="$4"
# 备份原文件
cp "$compose_file" "${compose_file}.bak"
# 修改端口映射
sed -i "s/${old_port}:${new_port}/${new_port}:${old_port}/g" "$compose_file"
# 重新创建服务
docker-compose -f "$compose_file" up -d "$service_name"
}
# 使用示例
update_compose_port "docker-compose.yml" "web" 8080 9090
高级脚本:完整端口管理工具
#!/bin/bash
# 完整的端口管理脚本
PORT_MANAGER_SCRIPT="/tmp/docker_port_manager.sh"
cat > "$PORT_MANAGER_SCRIPT" << 'SCRIPT'
#!/bin/bash
# 函数:显示当前端口映射
show_ports() {
local container="$1"
echo "当前容器 $container 的端口映射:"
docker port "$container"
}
# 函数:添加端口映射(不重启)
add_port_mapping() {
local container="$1"
local host_port="$2"
local container_port="$3"
# 获取容器网络设置
local network_mode=$(docker inspect -f '{{.HostConfig.NetworkMode}}' "$container")
if [ "$network_mode" != "bridge" ]; then
echo "错误:仅支持 bridge 网络模式的容器"
return 1
fi
# 获取容器IP
local container_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container")
if [ -z "$container_ip" ]; then
echo "错误:无法获取容器IP"
return 1
fi
echo "添加端口映射:主机 $host_port -> 容器 $container_ip:$container_port"
# 添加 iptables 规则
iptables -t nat -A DOCKER \
-p tcp --dport "$host_port" \
-j DNAT --to-destination "${container_ip}:${container_port}"
iptables -A DOCKER \
-p tcp --dport "$host_port" \
-j ACCEPT
echo "端口映射添加成功"
}
# 函数:删除端口映射
remove_port_mapping() {
local container="$1"
local host_port="$2"
local container_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container")
if [ -z "$container_ip" ]; then
echo "错误:无法获取容器IP"
return 1
fi
echo "删除端口映射:主机端口 $host_port"
# 查找并删除对应的 iptables 规则
iptables -t nat -L DOCKER --line-numbers -n | \
grep "${host_port}" | \
grep "${container_ip}" | \
awk '{print $1}' | \
sort -r | \
while read line; do
iptables -t nat -D DOCKER "$line"
done
# 删除 ACCEPT 规则
iptables -D DOCKER -p tcp --dport "${host_port}" -j ACCEPT 2>/dev/null
echo "端口映射删除成功"
}
# 主逻辑
case "$1" in
show)
show_ports "$2"
;;
add)
add_port_mapping "$2" "$3" "$4"
;;
remove)
remove_port_mapping "$2" "$3"
;;
*)
echo "用法:$0 {show|add|remove} [参数]"
echo "示例:"
echo " $0 show container_name"
echo " $0 add container_name 8080 80"
echo " $0 remove container_name 8080"
;;
esac
SCRIPT
chmod +x "$PORT_MANAGER_SCRIPT"
echo "端口管理脚本已创建:$PORT_MANAGER_SCRIPT"
echo "使用方法:"
echo "$PORT_MANAGER_SCRIPT show container_name"
echo "$PORT_MANAGER_SCRIPT add container_name 8080 80"
echo "$PORT_MANAGER_SCRIPT remove container_name 8080"
使用 Python + Docker SDK
#!/usr/bin/env python3
# 保存为 docker_port_update.py
import docker
import sys
def update_port_mapping(container_name, old_host_port, new_host_port):
"""使用 Docker SDK 更新端口映射"""
client = docker.from_env()
try:
container = client.containers.get(container_name)
# 停止容器
print(f"停止容器: {container_name}")
container.stop()
# 获取当前配置
container_config = container.attrs['Config']
host_config = container.attrs['HostConfig']
# 更新端口映射
ports = host_config.get('PortBindings', {})
for container_port in list(ports.keys()):
bindings = ports[container_port]
for binding in bindings:
if str(binding.get('HostPort')) == str(old_host_port):
binding['HostPort'] = str(new_host_port)
print(f"端口映射更新: {old_host_port}:{container_port} -> {new_host_port}:{container_port}")
# 重新创建容器
container.remove()
new_container = client.containers.run(
image=container_config['Image'],
name=container_name,
ports=ports,
detach=True
)
print(f"容器 {container_name} 已重新创建")
return True
except Exception as e:
print(f"错误: {e}")
return False
if __name__ == "__main__":
if len(sys.argv) != 4:
print("用法: python docker_port_update.py <容器名> <旧端口> <新端口>")
sys.exit(1)
update_port_mapping(sys.argv[1], sys.argv[2], sys.argv[3])
使用建议
-
生产环境推荐:使用 Docker API 或 docker-compose 方式,避免直接修改 iptables
-
测试环境:可以使用 iptables 方式快速调试
-
数据持久化:确保使用数据卷存储重要数据,避免重建容器时丢失
-
安全性:
# 检查 iptables 规则 iptables-save > /tmp/iptables_backup.txt # 还原 iptables 规则 iptables-restore < /tmp/iptables_backup.txt
选择哪种方法取决于你的具体需求和环境限制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播