系统版本:CentOS Linux release 7.9.2009
Docker版本:version 24.0.7

问题

Docker 容器映射端口会自动打开宿主机的相应端口,无法用 firewalldufw 管理

解决办法

host 模式

创建 Docker 容器时使用 host 模式

1
2
3
4
5
6
7
version: '3'

services:
nginx:
image: nginx:latest
network_mode: host
restart: unless-stopped
  • 优点:可以用 firewalldufw 管理端口了
  • 缺点:可能会造成端口冲突

在映射端口时添加 127.0.0.1

  • 操作:
    • 首次创建:例如 docker run -p 127.0.0.1:8090:8090 -d your-image
    • 正在运行:修改 /etc/docker/daemon.json 加上"ip":"127.0.0.1",然后执行 systemctl daemon-reload && systemctl restart docker
    • docker-compose 直接改就好了
  • 优点:不再暴露宿主机的端口
  • 缺点:只能本机访问,且有跨容器通信的问题
  • 如果要使用 Nginx Proxy Manager 等反代的话,须确保反代工具处于 host 模式,反代用 127.0.0.1:映射的端口

将容器放在同一个网桥内,不再映射端口

Nginx Proxy Manager 反代为例

  1. 新建一个 reverse-network 网桥
    1
    docker network create reverse-network
  2. 只暴露 Nginx Proxy Manager80443 端口
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    version: '3'

    services:
    app:
    image: jc21/nginx-proxy-manager:latest
    container_name: npm
    ports:
    - '80:80'
    - '443:443'
    networks:
    - reverse-network
    restart: unless-stopped
    volumes:
    - ./data:/data
    - ./letsencrypt:/etc/letsencrypt

    networks:
    reverse-network:
    external: true
  3. 将其他容器也放在 reverse-network 这个网桥
    • 直接修改 docker-compose 文件
    • 使用 CLI 创建的正在运行的容器的话麻烦一点:
      1. 断开和原网桥的连接连上新网桥
        1
        2
        3
        docker network disconnect default <container_id> # 断开旧网桥

        docker network connect reverse-network <container_id> # 连上新网桥
      2. 修改配置文件删除端口映射
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        # 查看容器完整的 hash_of_the_container 数值
        docker inspect {容器的名称或者 id } | grep Id

        # 停止 docker 服务
        systemctl stop docker

        # 修改配置文件
        vim /var/lib/docker/containers/{hash_of_the_container}/hostconfig.json

        # 找到 PortBindings, 删除 {} 里的内容
        "PortBindings":{}

        # 启动 docker 服务
        systemctl start docker

ufw-docker 管理

懒得写了,看这个吧:https://ivonblog.com/posts/fix-ufw-docker/

注意

  • 网上禁用 Docker 的 iptables 规则的办法基本都失效了,例如:
    • 修改 /lib/systemd/system/docker.service 加上--iptables=false
    • 修改 /etc/docker/daemon.json 加上 { "iptables" : false }
    • 以上皆会造成重启 Docker 时报错:在初始化网络控制器时遇到问题,其中涉及到不能创建新的 iptables 链,EnableIPTable 被禁用