ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Dozzle Agent 模式完全指南:用 TLS 加密连接远程 Docker 主机

Dozzle Agent 模式完全指南:用 TLS 加密连接远程 Docker 主机 Dozzle Agent 模式完全指南用 TLS 加密连接远程 Docker 主机【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzleDozzle 的 Agent代理模式允许你在远程 Docker 主机上部署一个轻量代理进程让本地或其他位置的 Dozzle 实例通过一条 TLS 加密的私有通道连接它从而安全地查看、流式读取甚至操作远端容器日志全程无需暴露 Docker Socket。本文将基于 Dozzle 官方 Agent 模式文档docs/guide/agent.md结合仓库内internal/agent、internal/support/cli等源码实现完整讲解 Agent 的创建、连接、主机分组、健康检查、过滤器与自定义证书并给出 Agent 与远程连接Remote Hosts的选型对比。Agent 模式是什么Dozzle 可以以agent子命令启动进入 Agent 模式。运行中的 Agent 会把自己所在主机的 Docker 容器暴露给其他 Dozzle 实例——换句话说你可以在远程主机上部署 Dozzle Agent然后从本地机器连接它像查看本机容器一样查看远程容器的实时日志。Agent 模式有两个关键特性所有通信走 TLS 加密连接Agent 与主 Dozzle 实例之间的所有流量都通过一条安全通道传输。从源码看这条通道是建立在 gRPC 之上的 TLS 连接详见 internal/agent/server.go并且要求客户端证书tls.RequireAndVerifyClientCert即双向 TLS 认证通信双方都需要持有私有的 Dozzle 证书。仅限 DockerAgent 模式是为 Docker含 Swarm 节点设计的。如果你使用的是Docker Swarm 模式则不需要 Agent——Dozzle 会自动发现自身并通过 Swarm 模式组建集群相关说明见 Swarm 模式指南。注意Agent 只展示运行 Agent 的这台主机上的容器不会透传主实例所在主机的内容。如何创建 Agent创建 Agent 只需要以agent子命令运行 Dozzle 镜像并挂载 Docker Socket 即可。以下两种方式等价docker run -v /var/run/docker.sock:/var/run/docker.sock -p 7007:7007 amir20/dozzle:latest agent或使用 docker-composeservices: dozzle-agent: image: amir20/dozzle:latest command: agent volumes: - /var/run/docker.sock:/var/run/docker.sock:ro ports: - 7007:7007Agent 启动后会监听7007端口。你可以在 Dozzle 界面中通过输入 Agent 的 IP 和端口来连接它。几点实用提示不必暴露 7007 端口如果 Agent 与其他容器处于同一个 Docker 网络同一网络内的容器直接访问 Agent 即可无需把 7007 端口映射到宿主机。不要再叠加 Socket 代理如果你打算使用远程 Agent不能在 Agent 之上再套一层 Docker Socket 代理。Dozzle 的 Agent 本身就是用来取代Socket 代理方案的如果想用 Socket 代理而不是 Agent请参考 远程主机指南。Socket 挂载权限官方 compose 示例使用:ro只读挂载 Socket但注意 Agent 需要向 Docker 请求 API 才能工作如果后续你需要在远程界面执行容器操作启动/停止/重启等请确保权限满足要求。源码视角Agent 启动过程agent子命令对应 internal/support/cli/agent_command.go 中的AgentCmd.Run。它的大致流程是创建本地 Docker 客户端docker.NewLocalClient读取或生成内嵌的TLS 证书在--agent-addr默认:7007环境变量DOZZLE_AGENT_ADDR上监听 TCP以该 Docker 客户端为基础构建ClientService并交给 internal/agent/server.go 的agent.NewServer启动 gRPC 服务。Agent 对外暴露的是AgentService这一 gRPC 服务服务定义见 protos/rpc.proto涵盖了容器列表、实时日志流、历史日志、原始字节流、事件流、统计信息、容器操作、镜像更新检查、终端 Exec/Attach 等全部能力。如何连接到 Agent在主 Dozzle 实例侧通过--remote-agent参数或环境变量DOZZLE_REMOTE_AGENT指定 Agent 的地址与端口即可docker run -p 8080:8080 amir20/dozzle:latest --remote-agent agent:7007services: dozzle: image: amir20/dozzle:latest environment: - DOZZLE_REMOTE_AGENTagent:7007 ports: - 8080:8080 # Dozzle 界面端口连接 Agent 时无需挂载本机的 Docker Socket——这种情况下界面只会显示各 Agent 上的容器。若你希望界面上同时展示主实例本机的容器再按快速开始中的示例挂载docker.sock即可。同时连接多个 Agent可以用逗号分隔多个地址一次连接多个 AgentDOZZLE_REMOTE_AGENTagent1:7007,agent2:7007命令行对应写法是重复传入--remote-agent参数每个参数对应一个 Agent 地址。源码视角连接串如何解析--remote-agent/DOZZLE_REMOTE_AGENT在 internal/support/cli/args.go 中定义为RemoteAgent []string支持separate分隔。真正解析连接串的是 internal/agent/client.go 中的ParseEndpoint它会按|把address|name|group拆成三部分见下文主机分组地址部分必填名称与分组可省略。客户端还会对 gRPC 调用启用gzip 压缩grpc.UseCompressor(gzip.Name)、10 MiB 的最大接收消息上限以及 30 秒/10 秒的 keepalive 参数以应对大流量日志流。主机分组Host Groups当需要管理分布在多个环境中的大量 Agent 时可以给每个 Agent 分配一个命名分组。分组在侧边栏中以可折叠区块呈现每个分组带一个合并全部按钮可查看组内所有主机的合并日志流。连接串的完整格式为endpoint|name|group三部分均可选格式结果agent:7007无名称覆盖无分组agent:7007|web-1有名称覆盖无分组agent:7007|web-1|Production有名称覆盖 分组agent:7007||Production默认主机名 分组命令行示例docker run -p 8080:8080 amir20/dozzle:latest \ --remote-agent agent1:7007|web-1|Production \ --remote-agent agent2:7007|web-2|Production \ --remote-agent agent3:7007|dev-1|Developmentdocker-compose 等价写法services: dozzle: image: amir20/dozzle:latest environment: - DOZZLE_REMOTE_AGENTagent1:7007|web-1|Production,agent2:7007|web-2|Production,agent3:7007|dev-1|Development ports: - 8080:8080此时侧边栏将显示▾ Production web-1 web-2 ▾ Development dev-1 ungrouped-host ← 未分组的 Agent 显示在下方点击分组名旁的合并图标会打开一个从该分组所有主机实时流式合并日志的视图。合并视图也可以通过 URL 直接访问/host-group/group-name。未分组的 Agent 行为与之前完全一致显示在分组区块下方。从源码看name与group两个字段被保存在Client结构体internal/agent/client.go中并在Host()拉取主机信息时覆盖主机显示名称、填充分组归属——即使 Agent 暂时不可达也会以Available: false的占位形式返回带名称与分组的主机信息保证界面布局稳定。常见问题Agent 不出现如果你在日志中看到An agent with an existing ID was found. Removing the duplicate host.说明有两台主机使用了相同的服务器 IDServer ID。Dozzle 通过 Docker API 收集主机信息每个 Agent 都需要一个跨重启保持稳定且全局唯一的主机 ID 以便正确识别。目前 Agent 使用 Docker 的**系统 IDsystem ID或节点 IDnode ID**来标识主机在 Swarm 环境中使用节点 ID如果发现并非所有主机都可见很可能是配置了多个具有相同主机 ID 的重复主机。解决办法删除系统中的/var/lib/docker/engine-id文件并重启 Docker即可消除因主机 ID 重复引发的冲突。更多诊断信息可参考常见问题FAQ。源码视角主机 ID 的派生规则主机 ID 的派生逻辑集中在 internal/container/host_id.go。DerivedHostID.Resolve会按优先级选择SwarmNodeIDSwarm 节点 ID Podman 专属派生 ID EngineIDDocker 写入/var/lib/docker/engine-id的引擎 ID重启后仍存活Fallback。也就是说文档中删除 engine-id 以修复重复主机的建议正对应 Docker 引擎首次启动时把 ID 写入该文件、之后一直复用的实现细节。若派生 ID 仍冲突还可以通过--host-id/DOZZLE_HOST_ID手工指定一个静态主机 ID仅允许字母、数字、短横线、下划线和点。高级选项配置健康检查Healthcheck你可以为 Agent 配置健康检查用法与主 Dozzle 实例相同。Agent 模式下健康检查会检测 Agent 与 Docker 的连接——如果 Docker 不可达Agent 会被标记为不健康且不会显示在界面中。使用healthcheck子命令配置services: dozzle-agent: image: amir20/dozzle:latest command: agent healthcheck: test: [CMD, /dozzle, healthcheck] interval: 5s retries: 5 start_period: 5s start_interval: 5s volumes: - /var/run/docker.sock:/var/run/docker.sock:ro ports: - 7007:7007源码视角internal/support/cli/health_command.go 展示了healthcheck子命令的分流逻辑——Agent 启动时会把监听地址写入/tmp/dozzle-agent.addrhealthcheck 命令若读到该文件就以 Agent 身份对127.0.0.1:port发起一次 RPC 探测见 internal/healthcheck/rpc.go 的RPCRequest实际是调用 Agent 的ListContainers否则回退为主实例的 HTTP 健康检查。因此healthcheck同一个子命令可以同时服务于两种模式。修改 Agent 名称与主 Dozzle 实例一致Agent 名称可以通过环境变量DOZZLE_HOSTNAME或启动参数--hostname修改docker run -v /var/run/docker.sock:/var/run/docker.sock -p 7007:7007 amir20/dozzle:latest agent --hostname my-special-nameservices: dozzle-agent: image: amir20/dozzle:latest command: agent environment: - DOZZLE_HOSTNAMEmy-special-name volumes: - /var/run/docker.sock:/var/run/docker.sock:ro ports: - 7007:7007连接该 Agent 后界面中即会以my-special-name显示。从源码看--hostname对应 internal/support/cli/args.go 的Hostname字段DOZZLE_HOSTNAME在创建本地 Docker 客户端时传入并体现在主机信息中。注意此名称与连接串第二段|name的名称覆盖是两套机制——前者在 Agent 侧生效后者在连接侧生效client 侧覆盖优先级更高。配置过滤器Filters可以在 Agent 上配置过滤器限制它能访问的容器范围。过滤器会直接传给 Docker从而限制 Dozzle 可见的容器services: dozzle-agent: image: amir20/dozzle:latest command: agent environment: - DOZZLE_FILTERlabelcolor volumes: - /var/run/docker.sock:/var/run/docker.sock:ro上面的配置会让 Agent 只显示带有color标签的容器。需要理解的是Agent 过滤器会与 UI 过滤器叠加生效共同收窄可见容器集合。举例来说如果 UI 层设置了--filter labelcolorAgent 层设置了--filter labeltype那么只有同时具备color和type两个标签的容器才会被展示。过滤器语法与各类过滤条件详见过滤器文档其中还提到了 UI 过滤器、Agent 过滤器、用户过滤器三层组合的规则。源码视角DOZZLE_FILTER/--filter在 internal/support/cli/args.go 中被解析为keyvalue形式的 mapargs.Filter随后在 Agent 启动时通过docker_support.NewDockerClientService(client, args.Filter)注入。在 gRPC 服务端过滤器会随ListContainers/FindContainer请求中的filter字段map 类型见 protos/rpc.proto传递并在 internal/agent/server.go 中还原成container.ContainerLabels交给 Docker API——因此过滤器直接传给 Docker从实现上完全成立。使用自定义证书Custom Certificates默认情况下Dozzle 在 Agent 之间使用自签名证书进行通信。这份证书是私有的仅对其他 Dozzle 实例有效对大多数场景是安全且推荐的做法。但有一种攻击场景需要防范如果 Dozzle 对外暴露且攻击者精确知道 Agent 运行的端口那么他可以自己起一个 Dozzle 实例并连接到你的 Agent。要杜绝这种可能请提供你自己的证书。提供自定义证书有两种方式挂载文件或使用Docker secrets。默认情况下 Dozzle 从/dozzle_cert.pem与/dozzle_key.pem读取证书可通过--cert/--key参数或DOZZLE_CERT/DOZZLE_KEY环境变量自定义路径。方式一使用默认路径 Docker secretsservices: agent: image: amir20/dozzle:latest command: agent volumes: - /var/run/docker.sock:/var/run/docker.sock secrets: - source: cert target: /dozzle_cert.pem - source: key target: /dozzle_key.pem ports: - 7007:7007 secrets: cert: file: ./cert.pem key: file: ./key.pem方式二自定义路径 环境变量services: agent: image: amir20/dozzle:latest command: agent environment: - DOZZLE_CERT/certs/my-cert.pem - DOZZLE_KEY/certs/my-key.pem volumes: - /var/run/docker.sock:/var/run/docker.sock - ./certs:/certs ports: - 7007:7007方式三命令行参数docker run -v /var/run/docker.sock:/var/run/docker.sock -v ./certs:/certs -p 7007:7007 amir20/dozzle:latest agent --cert /certs/my-cert.pem --key /certs/my-key.pemservices: agent: image: amir20/dozzle:latest command: agent --cert /certs/my-cert.pem --key /certs/my-key.pem volumes: - /var/run/docker.sock:/var/run/docker.sock - ./certs:/certs ports: - 7007:7007要点提醒官方推荐优先使用Docker secrets提供证书既可以通过docker secret create命令创建也可以像上面的 compose 示例一样在docker-compose.yml中声明。连接 Agent 的那台 Dozzle 实例也必须使用同一套证书否则双向 TLS 校验无法通过。生成证书可参考以下 openssl 命令Ed25519 算法 自签 X.509$ openssl genpkey -algorithm Ed25519 -out key.pem $ openssl req -new -key key.pem -out request.csr -subj /CUS/STCalifornia/LSan Francisco/OMy Company $ openssl x509 -req -in request.csr -signkey key.pem -out cert.pem -days 365源码视角证书加载逻辑在 internal/support/cli/certs.go 的ReadCertificates——优先尝试加载--cert/--key指定的自定义证书对若文件不存在则回退到内嵌于二进制中的shared_cert.pem/shared_key.pem即默认自签名证书。而 internal/agent/server.go 的NewServer会把同一份证书同时用作服务端证书与 CA 证书池ClientCAstls.RequireAndVerifyClientCert强制客户端也出示由该 CA 签发的证书——这正是同一套证书必须同时给 Agent 和主实例的根本原因。另外internal/agent/client.go 的 TLS 配置中设置了InsecureSkipVerify: true注释说明其目的是容忍证书主机名与地址不匹配自签名证书场景真正的认证保障来自双向证书校验。附带功能agent-test 子命令除了文档中的健康检查仓库还提供一个有用的调试子命令agent-test见 internal/support/cli/agent_test_command.go用法为dozzle agent-test address:port。它会用同样的证书建立连接并拉取一次HostInfo成功后打印 Agent 的版本、名称与 ID方便在界面排查之前快速验证 Agent 连通性与证书配置。Agent 与远程连接Remote Hosts对比Agent 与远程连接Remote Hosts即直接连接远端 Docker API / Socket 代理功能相似但 Agent 有若干优势官方总体更推荐 Agent主要出于性能与安全考量功能Agent远程连接性能更好负载被分摊到远端更差压力集中在本机界面侧安全性私有 SSL双向 TLS不安全或依赖 Docker TLS易用性开箱即用需要暴露 Docker Socket权限控制对 Docker 具有完整访问权限可以通过 Socket 代理做细粒度控制重连机制自动重连需要重启界面健康检查内置 healthcheck无过滤器支持 Agent 级过滤器不支持之所以 Agent 性能更好从架构上很容易理解日志抓取、解析、统计等工作在 Agent 侧完成主实例只消费经过 gRPC 压缩传输的结果参见 internal/agent/client.go 中的 gzip 压缩与 10 MiB 消息上限网络开销显著降低。如果你确实要使用远程连接请务必用Docker TLS或反向代理保护连接相关配置见远程主机指南。总结Dozzle Agent 模式是连接多台远程 Docker 主机的推荐方案它用一个轻量容器承载本地 Docker API 的访问与日志处理通过双向 TLS 的 gRPC 通道与主实例通信天然具备自动重连、内置健康检查与过滤器支持还能通过endpoint|name|group连接串组织起跨环境的主机分组并在/host-group/group-name上直接查看合并日志流。若追求最大安全性可以按本文方式用 openssl 生成自签证书、以 Docker secrets 挂载并将同一套证书同时提供给 Agent 与连接方。当遇到 Agent 不显示的异常时优先检查/var/lib/docker/engine-id是否存在重复的主机 ID必要时删除该文件并重启 Docker 以重建唯一身份。【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表