Docker容器内安装依赖私有Git仓库的包失败问题求助
你的问题核心在于容器内运行npm的用户身份和SSH密钥挂载路径不匹配,再加上文件权限限制,导致Git无法读取正确的SSH密钥。
为什么会出现这个问题?
node:12-alpine镜像默认会以node用户(而非root)运行后续命令(包括你ENTRYPOINT里的npm i)。你之前把主机的.ssh挂载到了容器的/root/.ssh,但node用户的家目录是/home/node,npm运行时会默认读取$HOME/.ssh下的密钥,也就是/home/node/.ssh,自然找不到你挂载的密钥文件。
而你后来尝试挂载到/home/node/.ssh时出现反向问题,大概率是手动进入容器后切换到了root用户执行npm i,此时$HOME变成了/root,Git又会去读取/root/.ssh的密钥,再次出现找不到的情况。
另外,主机.ssh目录的权限通常是700,密钥文件是600,容器内的node用户UID可能和主机的paul用户UID不一致,即使路径对了,也可能因为权限不足无法读取密钥。
正确的解决步骤
1. 修正SSH密钥的挂载路径
把主机的.ssh目录挂载到容器内node用户的家目录,也就是/home/node/.ssh,而不是/root/.ssh。修改后的Docker运行命令:
sudo docker run -it \ --volume=/home/paul/PROJECTDIR/javascript:/javascript \ --volume=/home/paul/.ssh/:/home/node/.ssh/ \ IMAGEID
2. 调整挂载目录的权限(关键)
因为主机的.ssh目录权限是700,只有主机的paul用户能访问,而容器内node用户的UID可能和paul不同,导致无法读取。可以通过两种方式解决:
方式A:让容器内的node用户使用主机paul用户的UID
先通过id -u paul获取主机paul的UID(比如假设是1000),然后在运行容器时指定用户UID:
sudo docker run -it \ --user=$(id -u paul):$(id -g paul) \ --volume=/home/paul/PROJECTDIR/javascript:/javascript \ --volume=/home/paul/.ssh/:/home/node/.ssh/ \ IMAGEID
方式B:在Dockerfile中提前配置权限
修改你的Dockerfile,添加调整/home/node/.ssh权限的步骤,确保node用户能读取:
FROM node:12-alpine RUN apk update && apk upgrade && apk add rsync git less openssh RUN mkdir /javascript WORKDIR /javascript # 确保node用户对/home/node/.ssh有读取权限 RUN chown -R node:node /home/node/.ssh || true ENTRYPOINT npm i --only=production
(|| true是为了避免在挂载目录之前执行时出现错误,因为此时/home/node/.ssh还不存在)
3. 解决已知主机问题
如果还是提示主机不在已知主机列表,因为你已经挂载了主机的.ssh目录,里面的known_hosts会被同步到容器,这个问题应该会自动解决。如果仍有问题,可以在Dockerfile中预先添加主机指纹:
# 替换HOST为你的实际私有Git仓库主机地址 RUN ssh-keyscan HOST >> /home/node/.ssh/known_hosts
验证方法
你可以先修改运行命令,进入容器的shell手动测试:
sudo docker run -it \ --volume=/home/paul/PROJECTDIR/javascript:/javascript \ --volume=/home/paul/.ssh/:/home/node/.ssh/ \ --user=$(id -u paul):$(id -g paul) \ IMAGEID sh
进入容器后,执行ssh -T git@HOST验证SSH连接是否正常,再执行npm i --only=production测试安装。
内容的提问来源于stack exchange,提问作者paul23

