最近在折腾过程中, 使用到了 FRP 这款软件, 碰巧作者在几天前更新的 v0.34.1 版本只发布了容器版本, 并未像之前一样发布多种编译版本.
距离上一次写 FRP 相关的内容, 已经过去了两年. 本文就基于官方容器版本, 介绍该软件的简单使用方法吧.
在容器中使用 FRP 服务端
首先在服务端找一个合适的目录, 创建 frps.INI 配置文件, 考虑到后续的便捷使用, 这里我们使用环境变量来对配置进行抽象.
- [common]
- bind_port = {
- {
- .Envs.FRP_SERVER_PORT
- }
- }
- token = {
- {
- .Envs.FRP_SERVER_TOKEN
- }
- }
- dashboard_addr = 0.0.0.0
- dashboard_port = {
- {
- .Envs.FRP_ADMIN_PORT
- }
- }
- dashboard_user = {
- {
- .Envs.FRP_ADMIN_USER
- }
- }
- dashboard_pwd = {
- {
- .Envs.FRP_ADMIN_PASS
- }
- }
- [common]bind_port = {
- {
- .Envs.FRP_SERVER_PORT
- }
- }token = {
- {
- .Envs.FRP_SERVER_TOKEN
- }
- } dashboard_addr = 0.0.0.0dashboard_port = {
- {
- .Envs.FRP_ADMIN_PORT
- }
- }dashboard_user = {
- {
- .Envs.FRP_ADMIN_USER
- }
- }dashboard_pwd = {
- {
- .Envs.FRP_ADMIN_PASS
- }
- }
接着, 就可以在 docker-compose.YAML 中使用环境变量来对程序的服务端进行 "动态" 配置了:
- version: "3.7"
- services:
- frps:
- restart: always
- container_name: frps
- image: fatedier/frps:v0.34.1
- volumes:
- - /etc/localtime:/etc/localtime:ro
- - /etc/timezone:/etc/timezone:ro
- - ./frps.INI:/App/frps.INI:ro
- command: frps -c /App/frps.INI
- ports:
- - 9870:9870
- - 7890:7890
- - YOURPORT:YOURPORT
- environment:
- - FRP_SERVER_PORT=9870
- - FRP_SERVER_TOKEN=CMW9viCpy1FZ
- - FRP_ADMIN_PORT=7890
- - FRP_ADMIN_USER=soulteary
- - FRP_ADMIN_PASS=soulteary
- networks:
- - frps
- logging:
- driver: "json-file"
- options:
- max-size: "1m"
- # docker network create frps
- networks:
- frps:
- external: true
- version: "3.7" services: frps: restart: always container_name: frps image: fatedier/frps:v0.34.1 volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - ./frps.INI:/App/frps.INI:ro command: frps -c /App/frps.INI ports: - 9870:9870 - 7890:7890 - YOURPORT:YOURPORT environment: - FRP_SERVER_PORT=9870 - FRP_SERVER_TOKEN=CMW9viCpy1FZ - FRP_ADMIN_PORT=7890 - FRP_ADMIN_USER=soulteary - FRP_ADMIN_PASS=soulteary networks: - frps logging: driver: "json-file" options: max-size: "1m" # docker network create frpsnetworks: frps: external: true
上面配置中需要注意的是, ports 字段中, 目前只声明了 FRP_SERVER_PORT 服务端通讯接口和 FRP_ADMIN_PORT 服务端管理接口, 所以我们需要再根据自己的情况添加一个 / 一些应用接口.
当然, 更好的方案是搭配 Traefik 使用服务发现来对外提供服务. 后面有机会, 我再行文详述.
在服务端使用 docker-compose up -d 启动服务, 如果顺利的话, 将看到类似下面的日志:
- frps | 2020/10/04 19:52:27 [I] [service.go:190] frps tcp listen on 0.0.0.0:9870
- frps | 2020/10/04 19:52:27 [I] [service.go:289] Dashboard listen on 0.0.0.0:9870
- frps | 2020/10/04 19:52:27 [I] [root.go:212] start frps success
- frps | 2020/10/04 19:52:27 [I] [service.go:190] frps tcp listen on 0.0.0.0:9870frps | 2020/10/04 19:52:27 [I] [service.go:289] Dashboard listen on 0.0.0.0:9870frps | 2020/10/04 19:52:27 [I] [root.go:212] start frps success
接着我们来配置客户端.
在容器中使用 FRP 客户端
同服务端一样, 我们先确定客户端配置 frpc.INI 的 "架子":
- [common]
- server_addr = {
- {
- .Envs.FRP_SERVER_ADDR
- }
- }
- server_port = {
- {
- .Envs.FRP_SERVER_PORT
- }
- }
- token = {
- {
- .Envs.FRP_SERVER_TOKEN
- }
- }
- [App]
- type = tcp
- remote_port = {
- {
- .Envs.APP_REMOTE_PORT
- }
- }
- local_ip = {
- {
- .Envs.APP_HOST
- }
- }
- local_port = {
- {
- .Envs.APP_PORT
- }
- }
- [common]server_addr = {
- {
- .Envs.FRP_SERVER_ADDR
- }
- }server_port = {
- {
- .Envs.FRP_SERVER_PORT
- }
- }token = {
- {
- .Envs.FRP_SERVER_TOKEN
- }
- } [App]type = tcpremote_port = {
- {
- .Envs.APP_REMOTE_PORT
- }
- }local_ip = {
- {
- .Envs.APP_HOST
- }
- }local_port = {
- {
- .Envs.APP_PORT
- }
- }
接着是完成客户端的 docker-compose.YAML 配置文件:
- version: "3.7"
- services:
- frpc:
- restart: always
- image: fatedier/frpc:v0.34.1
- volumes:
- - /etc/localtime:/etc/localtime:ro
- - /etc/timezone:/etc/timezone:ro
- - ./frpc.INI:/App/frpc.INI:ro
- environment:
- - FRP_SERVER_ADDR=123.456.789.012
- - FRP_SERVER_PORT=9870
- - FRP_SERVER_TOKEN=CMW9viCpy1FZ
- - APP_REMOTE_PORT=YOURPORT
- - APP_HOST=YOUR_APP_HOST
- - APP_PORT=YOUR_APP_PORT
- networks:
- - frpc
- logging:
- driver: "json-file"
- options:
- max-size: "1m"
- # docker network create frpc
- networks:
- frpc:
- external: true
- version: "3.7" services: frpc: restart: always image: fatedier/frpc:v0.34.1 volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - ./frpc.INI:/App/frpc.INI:ro environment: - FRP_SERVER_ADDR=123.456.789.012 - FRP_SERVER_PORT=9870 - FRP_SERVER_TOKEN=CMW9viCpy1FZ - APP_REMOTE_PORT=YOURPORT - APP_HOST=YOUR_APP_HOST - APP_PORT=YOUR_APP_PORT networks: - frpc logging: driver: "json-file" options: max-size: "1m" # docker network create frpcnetworks: frpc: external: true
这里 APP_HOST 和 APP_PORT 指代的是 FRPC 客户端在容器网络中能够访问到的要映射到前文服务器中的应用的地址及端口. 而 APP_REMOTE_PORT 指的则是上文中的 YOURPORT, 比如 80 端口, 或者 443 端口.
在客户端同样使用 docker-compose up -d 启动服务, 然后可以看到客户端的运行日志:
- frpc | 2020/10/04 20:42:56 [I] [service.go:288] [62e9e2de742523fe] login to server success, get run id [62e9e2de742523fe], server udp port [0]
- frpc | 2020/10/04 20:42:56 [I] [proxy_manager.go:144] [62e9e2de742523fe] proxy added: [confluence-App]
- frpc | 2020/10/04 20:42:56 [I] [control.go:180] [62e9e2de742523fe] [App] start proxy success
- frpc | 2020/10/04 20:42:56 [I] [service.go:288] [62e9e2de742523fe] login to server success, get run id [62e9e2de742523fe], server udp port [0]frpc | 2020/10/04 20:42:56 [I] [proxy_manager.go:144] [62e9e2de742523fe] proxy added: [confluence-App]frpc | 2020/10/04 20:42:56 [I] [control.go:180] [62e9e2de742523fe] [App] start proxy success
服务端此时也会多一条连接日志:
- frps | 2020/10/04 20:42:56 [I] [control.go:446] [62e9e2de742523fe] new proxy [App] success
- frps | 2020/10/04 20:42:56 [I] [control.go:446] [62e9e2de742523fe] new proxy [App] success
至此, FRP 在容器内的使用就全部完毕了, 随后就由你自由发挥啦.
其他
软件的发布页面 https://github.com/fatedier/frp/releases 中, 作者提到了 "Official docker image support on DockerHub and Github registry."
查阅 DockerHub 官方页面, 可以看到下面两个镜像仓库中有两个不同的推送记录, 不过目前使用人数不多, 或许是因为作者尚未给出明确的文档示例吧 (开源仓库 / 容器仓库):
- https://hub.docker.com/r/fatedier/frps
- https://hub.docker.com/r/fatedier/frpc
不过在短暂使用几天后发现, 当前版本不论是镜像尺寸还是运行性能都还不错, 而且相比较之前的版本, 在容器中使用更加方便了, 希望后续作者有时间能够完善文档吧.
最后
FRP 是一款优秀的软件, 随着越来越多的廉价公有云的面世, 使用这款软件搭配家用服务器使用, 可以大幅降低调试开发成本, 以及简化一些临时场景下的复杂组网, 值得一试.
最后, 希望本文能对你想在容器中玩 FRP 的你.
-EOF
来源: https://soulteary.com/2020/10/04/frp-in-docker.html