You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Docker镜像执行Capistrano部署时forward_agent密钥认证失败问题

问题:容器化Ruby环境下Capistrano部署时,部署目标服务器无法连接Bitbucket

我用Capistrano部署静态网站(静态页面由Ruby工具生成),目前正切换到容器化Ruby环境替代本地Ruby安装。

我的容器配置如下:

  • Dockerfile创建了用户dockerguy,UID/GID和本地用户一致,同时将本地用户的.ssh目录映射到容器内dockerguy的主目录,理论上可共用SSH密钥

docker-compose.yml

services:
  app:
    container_name: <project>-ruby
    build:
      context: .
      dockerfile: Dockerfile
      no_cache: true
    shm_size: 128mb
    ports:
      - 4567:4567
    volumes:
      - .:/app
      - ~/.ssh:/home/dockerguy/.ssh
    tty: true

Dockerfile

FROM ruby:3.4

# 这两个值和我的本地用户一致(后续会改成非硬编码)
ARG UID=501
ARG GID=20

WORKDIR /app

RUN apt update
RUN apt --assume-yes install nodejs
RUN adduser --uid $UID --gid $GID --disabled-password --gecos "" dockerguy \
    && echo 'nonroot ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers

USER dockerguy

执行bundle exec cap production deploy时,能正常连接部署目标服务器,但部署目标服务器与Bitbucket仓库的连接失败,报错信息如下:

INFO [2f3b6a35] Running /usr/bin/env git ls-remote git@bitbucket.org:<user>/<reponame>.git HEAD on <deploy-target>
 DEBUG [2f3b6a35] Command: ( export GIT_ASKPASS="/bin/echo" GIT_SSH="/tmp/git-ssh-0056b902611677dcfbca.sh" ; /usr/bin/env git ls-remote git@bitbucket.org:<user>/<reponame>.git HEAD )
 DEBUG [2f3b6a35]   Error reading response length from authentication socket.
 DEBUG [2f3b6a35]   Permission denied (publickey).
 DEBUG [2f3b6a35]   fatal: The remote end hung up unexpectedly

我的Capistrano配置已启用forward_agent:

# config/deploy/production.rb
[...]

server '<deploy-target>', roles: %w{web db app}, ssh_options: {
    user: <username-on-deploy-target>,
    forward_agent: true,
    auth_methods: %w(publickey)
}

请问部署目标与Bitbucket的连接为何失败?


问题分析与解决思路

这是SSH代理转发未正确穿透容器层导致的问题,具体原因和修复步骤如下:

1. 核心原因

虽然你挂载了本地.ssh目录到容器,但Capistrano的代理转发依赖容器能访问本地主机的SSH代理套接字,而非仅共享密钥文件。当前容器内的dockerguy用户无法连接本地ssh-agent,导致部署目标服务器无法通过代理获取你的本地密钥访问Bitbucket。

2. 验证步骤

进入容器内部,检查SSH代理环境变量:

# 进入容器
docker-compose exec app bash
# 查看代理套接字路径
echo $SSH_AUTH_SOCK

若输出为空,说明容器未继承本地SSH_AUTH_SOCK环境变量,代理转发无法工作。

3. 修复方案

方案一:挂载SSH代理套接字到容器

修改docker-compose.yml,添加代理套接字挂载与环境变量配置:

services:
  app:
    # 保留原有配置
    volumes:
      - .:/app
      - ~/.ssh:/home/dockerguy/.ssh
      # 挂载本地SSH代理套接字
      - ${SSH_AUTH_SOCK}:/ssh-agent
    # 告诉容器代理套接字位置
    environment:
      - SSH_AUTH_SOCK=/ssh-agent

方案二:修复容器内SSH权限

检查容器内.ssh目录及密钥文件权限:

docker-compose exec app ls -l /home/dockerguy/.ssh/

确保.ssh目录权限为700,密钥文件(如id_rsa)权限为600,若权限错误,在容器内执行:

chmod 700 /home/dockerguy/.ssh
chmod 600 /home/dockerguy/.ssh/id_rsa

方案三:确认本地SSH代理状态

本地主机需确保ssh-agent已启动且密钥已加载:

# 启动代理
eval "$(ssh-agent -s)"
# 添加密钥
ssh-add ~/.ssh/id_rsa
# 验证密钥是否加载
ssh-add -l

4. 额外优化建议

  • macOS用户需注意:Docker Desktop默认允许容器访问本地代理,但需确保SSH_AUTH_SOCK路径正确(通常为/private/tmp/com.apple.launchd.xxxx/Listeners)
  • 避免硬编码UID/GID,后续可通过docker-compose.yml动态传递:
    build:
      args:
        UID: ${UID}
        GID: ${GID}
    

内容的提问来源于stack exchange,提问作者Grant Birchmeier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:34:56