我有一个 Docker 容器,它向应用程序公开端口(例如 Redis,它公开端口 6379)。我不想在我的主机上公开 6379(因此 1. 占用我为数不多的 65535 端口号之一,2. 将 Redis 缓存公开给我主机上的所有用户),而是想通过本地目录中的 Unix 套接字连接到 Redis(例如通过使用$ redis-cli -s ~/redis.sock
)。
然而,Docker 似乎只提供端口到端口的转发(通过ports
中的选项docker compose
,或-p
中的开关docker run
)或套接字到套接字转发(通过公开套接字所在的目录)。是否有其他方法(在任何符合 GCI 的容器系统中)可以进行我正在寻找的直接套接字到端口转换,或者这是 GCI 标准固有的限制?
我知道 Redis 本身可以监听 Unix 套接字,但我对没有该功能的应用程序很感兴趣。
答案1
docker 没有原生支持此功能,但你可以使用类似socat
在容器中运行以在 unix 套接字和网络套接字之间进行代理(并使用绑定挂载在主机文件系统中公开 unix 套接字)。
举redis
个例子,我们可以做这样的事情:
services:
redis:
image: docker.io/redis
healthcheck:
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
interval: 10s
redis-socket-proxy:
image: docker.io/alpine/socat
volumes:
- ./sockets:/sockets
command:
- unix-listen:/sockets/redis.socket,fork,mode=0777
- tcp-connect:redis:6379
depends_on:
redis:
condition: service_healthy
./sockets/redis.socket
现在您有一个可以连接 redis 服务的unix 套接字。
也就是说,您不仅有 65535 个可用的网络套接字;因为您可以将套接字绑定到特定的 IP 地址,所以您可以拥有比这多很多倍的套接字。这里有两个 redis 服务器,它们都使用两个不同的本地主机地址绑定到主机上的端口 6379:
services:
redis1:
image: docker.io/redis
ports:
- 127.0.0.1:6379:6379
redis2:
image: docker.io/redis
ports:
- 127.0.0.2:6379:6379
在许多情况下,您甚至不需要在主机上绑定端口;如果您有一个像 redis 或数据库这样的服务,或者被用作另一个容器化应用程序的后端的东西,就不需要发布后端服务端口;您只需要公开前端服务。
当然,无论您是否发布了端口,您始终可以使用容器 IP 地址连接到服务方向。
对于本身不支持绑定到 unix 套接字的服务,您可能很难找到知道如何通过 unix 套接字连接到服务的客户端库或其他工具。