Ped*_*o A 9 networking sles linux-networking docker sles12
我在 SUSE Linux Enterprise Server 12 SP1 中遇到了 Docker 的奇怪情况。
我使用 SSH 连接到服务器。首先,我尝试运行一个简单的 nginx 服务器来测试:
docker run -d -p 8081:80 nginx:alpine --name nginxtest
Run Code Online (Sandbox Code Playgroud)
容器启动成功。然后,跑步curl http://localhost:8081就可以了!
<!-- [...] -->
<title>Welcome to nginx!</title>
<!-- [...] -->
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试从我的计算机上的浏览器访问它时,http://10.etc.etc.etc:8081请求超时。
但令人惊讶的是,如果我暂时忘记 docker,并直接从服务器使用简单的 HTTP 服务器,例如python3 -m http.server,我会得到:
Serving HTTP on 0.0.0.0 port 8000 ...
Run Code Online (Sandbox Code Playgroud)
当我从计算机上的浏览器访问它时,http://10.etc.etc.etc:8000它就可以工作了!
所以这一定是关于 docker 如何公开其端口的,但这很奇怪,因为它curl http://localhost:8081有效......
我该如何进一步排除故障并解决此问题?
注意:直到昨天我跑步时一切都运行良好systemctl restart wicked(我试图调查另一个不相关的问题)。我也尝试重新启动服务器,但没有帮助。
这是一些可能相关的更多输出......
ifconfig docker0docker0 Link encap:Ethernet HWaddr 02:49:68:4D:40:9B
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:8e6e:ee3f:6918/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:353842611 errors:0 dropped:0 overruns:0 frame:0
TX packets:450340200 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:509803756314 (486186.7 Mb) TX bytes:497391388709 (474349.3 Mb)
Run Code Online (Sandbox Code Playgroud)
brctl show docker0bridge name bridge id STP enabled interfaces
docker0 8000.0249143a607f no veth0e4b1f4
veth1f2fcc2
veth389f6fe
[[others]]
Run Code Online (Sandbox Code Playgroud)
docker ps | grep nginx是0.0.0.0:8081->80/tcp
cat /etc/sysctl.conf
# net.ipv6.conf.all.disable_ipv6 = 1
# net.ipv6.conf.all.disable_ipv6 = 1
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0
Run Code Online (Sandbox Code Playgroud)
(netstat -ltunp | head -2) && (netstat -ltunp | grep docker)Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 :::9000 :::* LISTEN 28216/docker-proxy
tcp 0 0 :::5000 :::* LISTEN 28165/docker-proxy
tcp 0 0 :::8081 :::* LISTEN 30341/docker-proxy
Run Code Online (Sandbox Code Playgroud)
iptables -n --listChain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER-ISOLATION all -- 0.0.0.0/0 0.0.0.0/0
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 172.17.0.11 tcp dpt:5000
ACCEPT tcp -- 0.0.0.0/0 172.17.0.13 tcp dpt:9000
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:80
Chain DOCKER-ISOLATION (1 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
Run Code Online (Sandbox Code Playgroud)
iptables -nt nat -LChain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.11 172.17.0.11 tcp dpt:5000
MASQUERADE tcp -- 172.17.0.13 172.17.0.13 tcp dpt:9000
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5000 to:172.17.0.11:5000
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9000 to:172.17.0.13:9000
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8081 to:172.17.0.2:80
Run Code Online (Sandbox Code Playgroud)
docker network lsNETWORK ID NAME DRIVER SCOPE
20c691cc38e6 bridge bridge local
cd95c7d14c38 host host local
eb6d8228f366 none null local
Run Code Online (Sandbox Code Playgroud)
docker network inspect bridge[
{
"Name": "bridge",
"Id": "20c691cc38e65be9bf0a377fd8560d49430f523608094b68145e8769e24b1764",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Containers": {
"26887c686d3c8612e460b923692f371bef881065a525496dff9af993ed4b7949": {
"Name": "sleepy_fermi",
"EndpointID": "3e79d8c15423b2e145a900e796d316159d2dc51dcc10ced2099b77d1111b03e7",
"MacAddress": "02:49:68:4D:40:9B",
"IPv4Address": "172.17.0.6/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
Run Code Online (Sandbox Code Playgroud)
iptables -S-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION
-A FORWARD -j DOCKER-ISOLATION
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.11/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
-A DOCKER -d 172.17.0.13/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 9000 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION -j RETURN
Run Code Online (Sandbox Code Playgroud)
docker versionClient:
Version: 1.12.6
API version: 1.24
Go version: go1.6.2
Git commit: 78d1802
Built: Thu Mar 2 12:26:00 2017
OS/Arch: linux/amd64
Server:
Version: 1.12.6
API version: 1.24
Go version: go1.6.2
Git commit: 78d1802
Built: Thu Mar 2 12:26:00 2017
OS/Arch: linux/amd64
Run Code Online (Sandbox Code Playgroud)
在这里,我们的 Docker 容器可以通过 docker0 访问(网络:172.17.xx)
您正在尝试从浏览器连接到某个 10.xxx 地址。
假设您只想从浏览器连接到本地托管的容器,那么更简单的方法就是访问您的容器地址 (172.17.xx)。
在某些情况下,您甚至可以ssh -X连接到 Docker 主机,然后启动 Web 浏览器,而无需将它们暴露在 LAN 中。
假设您想向 LAN 上的客户端公开 http/https 服务,那么您可以使用一些反向代理(nginx、traefik、apache,...)。
dnf install httpd
setsebool -P httpd_can_network_connect on
cat <<EOF >/etc/httpd/conf.d/welcome.conf
<VirtualHost *:80>
ServerName my-application.example.com
LogLevel debug
ErrorLog logs/tunnel_error.log
CustomLog logs/tunnel_access.log combined
<Location />
Require all granted
</Location>
ProxyPass / http://<container-address>:8080/
ProxyPassReverse / http://<container-address>:8080/
</VirtualHost>
EOF
systemctl enable httpd
systemctl start httpd
Run Code Online (Sandbox Code Playgroud)
假设您想向 LAN 上的客户端公开 tcp/udp 服务,您可以相应地设置防火墙:
sysctl -w net.ipv4.conf.all.forwarding=1
echo net.ipv4.conf.all.forwarding=1 >>/etc/sysctl.conf
iptables -A FORWARD -i docker0 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp -d <my-eth0-address> --dport 8080 -j DNAT --to <my-container-address>:8080
Run Code Online (Sandbox Code Playgroud)
请注意,如果您重新启动系统或以某种方式重置防火墙,这些 iptables 规则将不会持续存在。对《恶人》不太熟悉。