引言

docker 这个东西呢,对于我来说又爱又恨吧,爱的事情是可以很快速的进行部署项目,解决一些复杂和繁琐的问题,这也是docker 设计的初衷。恨得呢,本身我对于docker 来说是是一个小白用户,我只会 docker run xxxx 来完成我在github 找到的有趣应用,但是出了问题的时候,我需要去使用搜索引擎查阅的知识。

需要准备的东西?

  • 掌握搜索引擎技能(下面的文章只会叫你如何进行使用基本的iptables)
  • 一个大脑🧠
  • 一台运行了Linux系统的电脑
  • 掌握基本的Linux基本知识

抛出问题

应该在阅读这篇文章的人,都在很疑惑,为什么我在docker上使用 docker run -p 指令的时候,和宿主机进行绑定端口,本来我是想使用nginx 进行反代的,我自己的防火墙也没有放行这个端口,但从外部确确实实的可以访问。

为什么会出现这个问题?

在docker 官方文档上就有这个解释,docker 使用 -p 进行放行端口的时候,低层使用 iptables防火墙 FORWARD将流量转发到docker 运行的容器里面。

我拿 Iptables防火墙 这篇文章的图进行来说明一下

iptables.png

因为 流量在进入iptables 防火墙的时候 会经过路由选择进行判定,这个流量是要转发还是要流入本机里面,由于docker 自身创建了一个单独的内网环境一般这个 IP段是 172.17.0.0/16 ,然后流浪回去转入对应的容器里面。

解决办法

知道了为什么会出现这个问题,其实就可以知道其中一种解决办法了,就是不适用 -p 指令不让宿主机和容器进行绑定,然后使用nginx 进行,反向代理就可以了,一般情况下是,docker 使用 桥接网络模式 ,Docker 会为每个容器分配一个唯一的 IP 地址。可以查询这个docker 容器的ip 就可以实现反代,但是这个方法会有些问题,

  1. 有点麻烦,你需要创建一个docker 容器就要进行配置反代。
  2. nginx 不支持 udp 代理所以说还要安装和配置能代理udp 的软件实现反代。
  3. 还有一种办法就是直接在docker 的配置文件中关闭使用 IP tables 防护墙,交给其他防火墙进行保护例如 ufw 等

方法一: nginx 反向代理

使用这个方法需要拿到容器的IP

1
sudo docker inspect <你的容器唯一id或者容器的名字> | grep "IPAddress"

应该会返回,一下信息,例如我的这个测试容器的IP就是 172.17.0.4

1
2
3
4
docker inspect nginx-8080 | grep "IPAddress"
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.4",
"IPAddress": "172.17.0.4",

然后去你的nginx 配置新增你的配置文件

1
2
3
4
5
6
7
8
server {
listen 80; //监听端口
server_name localhost; // localhost 是监听域名或者是ip

location / {
proxy_pass http://容器的IP地址:容器内部Nginx服务器监听的端口;
}
}

如果你是使用BT面板进行管理的,只需要去网站 - 创建一个新的站点,然后打开配置选择反向代理,填入对应信息即可。

方法二: 修改docker 配置文件

这个方法就比较简单和直接,一般默认情况下docker 的配置文件会在 /etc/docker/daemon.json 如果没有这个 daemon.json可以直接创建就行了。

注意如果你不会使用vi 或者是vim 编辑器的基本使用,你应该需要去学习一下vi或者vim 的简单使用即可。

1
sudo vi /etc/docker/daemon.json

加入这段配置

1
2
3
{
"iptables": false
}

重启一下docker 以及docker 的守护进程

1
sudo systemctl restart docker

注意重启 docker 和docker的守护进程,会需要手动重启创建的docker 容器。在docker 容器重新启动之后 -p 只会绑定宿主机端口号,宿主机端口受现在防火墙进行管理。