抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

这是一篇通过配置hysteria2学习docker-compose的笔记

前言

用官方的docker和配置3分钟就搭好了,但是想试试通过bridge和通过nginx反代来实现(最后没有实验),于是就开始了折腾,,,

docker的network模式

docker会隔离文件、网络、进程,而网络的隔离程度分为4种:

  • host 这个相当于和主机共用一个网络
  • none 容器不需要内部和外部网络
  • container 似乎是容器内的网络,和主机分离。
  • bridge 命令docker network create的默认模式,连接到该网络的容器可以互相连通,而且可以暴露端口给主机和主机通讯。客户端通过主机ip:port访问。

NOTE

docker默认创建除container的三个网络。可以通过docker network ls查看。

bash
1
2
3
4
5
6
root@:/bin/hy2# docker network ls
NETWORK ID NAME DRIVER SCOPE
c069db7ead85 bridge bridge local
cf668a8174a8 host host local
162c8b1b3229 nginx-proxy bridge local # `nginx-proxy`是我自己创建的。
4f9ce671d49a none null local

NOTE

值得注意的是,docker默认创建一个名为docker0的网口用于连接主机和容器。通过ip link查看
进入hy2容器执行ip link命令可以看到,hy2的网卡(eth0)是和主机上的veth6f76815虚拟网卡连接(240:241)

bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@445:/bin/hy2# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether [隐私删除] brd ff:ff:ff:ff:ff:ff
altname enp0s3
altname ens3
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:4e:38:4d:51 brd ff:ff:ff:ff:ff:ff
12: br-162c8b1b3229: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:93:b0:6a:4a brd ff:ff:ff:ff:ff:ff
223: veth3452fbb@if222: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-162c8b1b3229 state UP mode DEFAULT group default
link/ether d2:85:53:63:a1:76 brd ff:ff:ff:ff:ff:ff link-netnsid 0
241: veth6f76815@if240: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-162c8b1b3229 state UP mode DEFAULT group default
link/ether aa:e0:71:cf:9e:50 brd ff:ff:ff:ff:ff:ff link-netnsid 1
root@445:/bin/hy2# docker exec -it hy2 /bin/bash
1cb800f27bd1:/# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
240: eth0@if241: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ff
1cb800f27bd1:/#

配置hy2的yaml

官方的yaml是使用的host模式,我现在要创建一个名为nginx-proxy的网络并且在配置文件中更改。

yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version: "3.9"
services:
hysteria:
image: tobyxdd/hysteria
container_name: hy2
restart: always
volumes:
- acme:/acme
- ./hysteria.yaml:/etc/hysteria.yaml
command: ["server", "-c", "/etc/hysteria.yaml"]
networks:
- nginx-proxy
ports:
- "10808:443"
# expose:
# - "443"
networks:
nginx-proxy:
external: true
volumes:
acme:

这样我以为就可以通过访问10808端口科学上网了。但是ping不通,,,

经过努力的排查,找到了docker inspect命令,发现容器被分配的IP是空的,,,

原来还需要手动通过输入docker network connect来连接,,,我看nginx是自动连接的,不知道对应的yaml怎么写。

结果还是是ping不通,,,

iptables -t nat -nvL --line-number查看发现,Chain DOCKER里也有容器IP的DNAT了,为什么还是不行。

不细心眼力不好还发现不了,是暴露端口的时候默认暴露tcp,,,。结合hy2文档也知道hy2是基于udp的,然后更改配置

yml
1
2
3
4
5
services:
hysteria:
ports:
- "10808:443/udp"
...

成功!

但是关闭连接的时候就会出错再也连不上,通过日志发现,原来关闭的时候通过tcp沟通的。

最终的配置文档应该像这样的

yml
1
2
3
4
5
6
services:
hysteria:
ports:
- "10808:443/udp"
- "10808:443/tcp"
...

最后删除多余的NAT,和设置新的NAT,并备份iptables

warning

iptables-save -f /etc/iptables/rules.v4适用于Debian,其他系统可能会恢复不了iptables

bash
1
2
3
4
iptables -t nat -D PREROUTING 1
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 20000:50000 -j DNAT --to-destination :10808
iptables-save -f /etc/iptables/rules.v4
systemctl restart iptables

nginx初次使用

由于nginx运行在docker内,而每个docker都会被network的虚拟网关分配一个ip,如果nginx要反代同一network内的docker container是不是就要预先知道它的ip呢?这样做其实也可以,但是如果机器重启就会出问题,因为重启后每个容器的ip会被重新分配,分配的规则我猜测是根据启动顺序来决定的。更优雅的方式是直接使用container的别名作为ip

例如在同一网络内有两个container,别名分别为nginx_testapi,则nginx_test的反代配置应该是类似于这样的。

.conf
1
2
3
4
5
6
7
server {
listen 80;
server_name localhost;
location /api {
proxy_pass http://api:3000;
}
}

评论