Dozzle 容器 Shell 访问完全指南:浏览器内 Attach 与 Exec 实战
Dozzle 容器 Shell 访问完全指南浏览器内 Attach 与 Exec 实战【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzleDozzle 是一款面向容器的实时日志查看器支持 Docker、Swarm 与 Kubernetes 等编排平台。除了日志流式查看它还内置了基于 Web 的容器终端能力允许用户直接从浏览器附加attach到运行中的容器或在容器内执行命令exec。本文以官方文档 docs/guide/shell.md含 德语版、中文版 等多语言副本为核心骨架结合仓库后端路由、CLI 参数解析、认证角色与前端 Terminal 组件的源码实现系统讲解该功能的启用方式、工作原理、安全边界与 Kubernetes 下的注意事项。读完本文你将掌握如何安全地为 Dozzle 开启 Shell 访问并理解从浏览器点击到容器内进程间建立会话的完整链路。功能概览Dozzle 如何提供容器 ShellDozzle 的 Shell 访问能力包含两种操作模式Attach附加接入运行中容器的主进程直接观察并参与该进程的输入输出流效果等同于docker attachExec执行在容器内启动一个新的交互式命令默认探测并启动bash或sh效果等同于docker exec。这两种操作都通过浏览器内的 WebSocket 会话完成前端对应组件为 assets/components/containers/Terminal.vue。该组件基于 xterm.js 渲染终端界面在挂载时通过new WebSocket(withBase(\/api/hosts/${container.host}/containers/${container.id}/${action}))见 Terminal.vue建立连接随后将用户在终端中的输入与窗口 resize 事件编码为 JSON 事件发送到服务端并把服务端回传的输出写入终端。[!NOTE] 根据官方文档Shell 访问应当适用于所有类型的容器包括 Docker、Kubernetes 以及其他编排平台。默认关闭与启用方式由于浏览器终端意味着对容器的完全控制权Dozzle 将该功能默认禁用。其开关在 CLI 参数定义中一目了然见 internal/support/cli/args.goEnableShell bool arg:--enable-shell,env:DOZZLE_ENABLE_SHELL default:false help:enables shell access to containers from the web interface.参数--enable-shell与环境变量DOZZLE_ENABLE_SHELL一一对应默认值均为false。这意味着你既可以在启动命令中传参也可以在容器编排文件中注入环境变量两种方式等价。方式一docker run 命令行参数docker run --volume/var/run/docker.sock:/var/run/docker.sock -p 8080:8080 amir20/dozzle --enable-shell注意--volume挂载 Docker Socket 是 Dozzle 与 Docker 守护进程通信的前提实际生产部署还应配置restartalways、时区、日志轮转等参数此处仅保留与 Shell 功能直接相关的核心配置。方式二docker-compose 环境变量services: dozzle: image: amir20/dozzle:latest volumes: - /var/run/docker.sock:/var/run/docker.sock ports: - 8080:8080 environment: DOZZLE_ENABLE_SHELL: true方式三Kubernetes / Swarm 编排在 Kubernetes 下部署时只需在 Dozzle 的 Deployment 容器配置中加入同样的环境变量即可env: - name: DOZZLE_ENABLE_SHELL value: true完整可参考仓库中的 examples/k8s.dozzle.ymlSwarm 模式请参考 examples/docker.swarm.yml 与 examples/docker.swarm.auth.yml。路由注册开关如何在服务端生效开关并不只是前端显示上的差异而是决定后端是否注册对应 API 路由。在 internal/web/routes.go 中路由创建逻辑如下if h.config.EnableShell { r.Get(/hosts/{host}/containers/{id}/attach, h.attach) r.Get(/hosts/{host}/containers/{id}/exec, h.exec) }当--enable-shell未开启时/api/hosts/{host}/containers/{id}/attach与/api/hosts/{host}/containers/{id}/exec这两个 WebSocket 端点根本不会被注册——这与镜像检查等其他功能的“端点不存在”策略一致见 routes.go 的注释意味着关闭状态下连接请求将直接返回 404从网络层面杜绝了攻击面。同时可以注意到这两个路由与日志流、容器操作等一样位于认证中间件之后见 routes.go也就是说任何访问这些端点的请求都会先经过认证层。安全模型从默认关闭到角色控制官方文档明确警告任何能访问 Dozzle 界面的人都能在你的容器里打开终端其权限等同于docker exec。因此在公开可访问的 Dozzle 实例上启用--enable-shell之前必须先配置认证。仓库实现的认证体系位于 internal/auth支持simple用户名密码、oidcOpenID Connect SSO、forward-proxy等多种提供方详细说明见 docs/guide/authentication.md。角色shell 权限的精细控制仅开启认证还不够——Dozzle 提供基于角色的权限来进一步限制谁能使用 Shell。角色定义位于 internal/auth/roles.gotype Role int const ( None Role 0 Shell Role 1 iota // ... Actions、Download、Notifications、Cloud ) const All Shell | Actions | Download | Notifications | Cloud角色解析支持shell与dozzle_shell两种写法见 roles.go并支持^前缀的排除语法例如all,^shell表示“除 shell 外授予全部权限”见 roles.go 的注释与实现。这意味着即使启用了 Shell 功能管理员仍可只将shell角色授予特定用户。服务端二次校验权限检查并不仅仅停留在路由层。即使某用户拿到了 WebSocket 端点地址服务端处理器也会再次校验角色。在 internal/web/terminal.go 的attach处理器中permit : true if h.config.Authorization.Provider ! NONE { user : auth.UserFromContext(r.Context()) ... permit user.Roles.Has(auth.Shell) } if !permit { log.Warn().Msg(user is not permitted to attach to container) conn.WriteMessage(websocket.TextMessage, []byte(⛔ Access denied: attaching to this container is forbidden\r\n)) return }exec处理器terminal.go采用完全相同的校验逻辑。双重保障路由注册 处理器内角色检查确保安全边界在服务端得到严格执行。容器过滤标签此外认证用户还可以通过容器过滤标签user.ContainerLabels见 terminal.go将可访问范围限制到特定容器集合从而实现“即使有 shell 权限也只能进入被授权的那部分容器”的细粒度隔离。浏览器到容器的完整链路服务端处理流程浏览器通过 WebSocket 连接/api/hosts/{host}/containers/{id}/attach或/api/hosts/{host}/containers/{id}/execupgrader.Upgrade将 HTTP 请求升级为 WebSocket 连接terminal.go基于 gorilla/websocket 且刻意未开放任意 Origin以防止跨站 WebSocket 劫持见文件头部注释处理器从 URL 参数中取出容器id通过h.hostService.FindContainer(hostKey(r), id, userLabels)按用户标签过滤后找到目标容器服务attach调用containerService.Attach(ctx, eventReader, wsWriter)建立附加会话exec则调用containerService.Exec(...)执行命令terminal.go服务端把 WebSocket 包装为webSocketWriter输出写入连接与jsonEventReader从连接读取 JSON 编码的ExecEvent见 terminal.go实现双向数据流。exec 的默认命令探测值得注意的细节是exec模式并非简单地执行用户输入的第一条命令而是先做一次 Shell 探测terminal.go[]string{sh, -c, command -v bash /dev/null 21 exec bash || exec sh}即优先尝试bash若容器内不存在则回退到sh。这保证了在仅有 POSIX sh 的精简镜像中也能打开终端。远端主机与 Agent 支持当目标容器位于远端主机时Dozzle 通过 Agent 转发会话。仓库中的 internal/agent/client.go 与 internal/agent/client.go 分别实现了ContainerAttach与Exec的远程调用gRPC 协议侧由 protos/rpc.proto 中的ContainerExecRequest/ContainerExecResponse双向流承载对应服务端实现见 internal/agent/server.go 的ContainerExec。这印证了官方文档“适用于所有编排平台”的说明在架构上是有保障的。Kubernetes 模式下的特殊说明在 k8s 模式下Shell 访问不再经过 Docker API而是直接走 Kubernetes API。因此目标 Pod 必须满足一个硬性前提目标 Pod 内必须存在可执行的 Shell/bin/sh、/bin/bash等。以下两类镜像无法附加基于FROM scratch构建的极简镜像不含任何用户空间工具不带 Shell 的 Distroless 镜像如仅含单一静态二进制、以非 root 运行的镜像。这类镜像连command -v bash探测都无法执行docker exec/kubectl exec同样无能为力。实际排障时若你的应用镜像确实缺少 Shell可以考虑临时改用带 Shell 的调试镜像或 sidecar 容器方案而非试图在 Dozzle 中强行附加。生产环境安全清单综合官方文档与源码实现在公开环境启用 Dozzle Shell 访问前建议按以下清单逐项确认认证先行至少配置一种认证提供方docs/guide/authentication.md避免匿名访问 UI角色收敛仅向确有排障需求的用户授予shell角色可利用^shell排除语法做反向收权internal/auth/roles.go容器过滤为不同用户配置容器过滤标签缩小可进入的容器范围internal/web/terminal.go网络隔离通过反向代理参考 examples/ingress.yml限制 Dozzle 的暴露范围必要时启用 HTTPS日志审计保持 Dozzle 日志级别可用Shell 访问的失败尝试会以 warn 级别记录见 terminal.go 的log.Warn()最小化开启仅在实际需要调试时开启--enable-shell日常日志查看场景保持默认关闭从路由注册层面routes.go消除攻击面。小结Dozzle 的 Shell 访问功能把docker attach/docker exec的能力完整搬进了浏览器配合日志流、容器分组等能力为容器化应用的日常排障提供了统一的 Web 入口。理解其「默认关闭 → 显式开启 → 认证 角色双重校验」的安全设计以及 Docker / Kubernetes 两种后端路径的差异是安全使用该功能的前提。若需进一步了解相关能力可继续阅读仓库中的 docs/guide/authentication.md、docs/guide/container-groups.md 与 docs/guide/remote-hosts.md。【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考