【问题标题】:How to securely git clone/pip install a private repository into my docker image?如何安全地 git clone/pip 将私有存储库安装到我的 docker 映像中?
【发布时间】:2019-09-19 14:47:15
【问题描述】:

我有一个私人仓库,其中包含我想要 pip 安装的软件包。我花了很多时间阅读各种论坛和文章,了解安全执行此操作的不同方法。对于如何最好地做到这一点(如果可能的话)似乎没有达成共识。我显然不想在我的 dockerfile 中公开任何 ssh 密钥/秘密——我想小心通过 docker 历史记录使它们可用。

【问题讨论】:

    标签: git ssh-keys docker-image


    【解决方案1】:

    如“Securely build small python docker image from private git repos”中所述,您需要使用 Docker 18.09+

    • --ssh
      您可以使用 --ssh 标志将现有的 SSH 代理密钥转发给构建器。 docker 不会传输关键数据,而是只会通知构建器此类功能可用。
      现在,当构建器需要通过 SSH 访问远程服务器时,它会回拨到客户端并要求它签署此连接所需的特定请求。
      密钥本身永远不会离开客户端,并且会尽快由于请求访问的命令已完成,因此构建器端没有信息可以稍后重新建立该远程连接

    • 秘密
      /var/run/secrets 的构建过程中提供一个挂载选项,仅适用于使用它的命令,并且不包含在创建的层中。

    即:

    docker build --ssh github_ssh_key=/path/to/.ssh/git_ssh_id_rsa .
    

    只有代理连接与该命令共享,而不是私钥的实际内容。
    Dockerfile 中没有其他命令/步骤可以访问它。

    Dockerfile 在多阶段的第一步中会给出一个键名github_ssh_key,这样我们就可以在调用docker build 时使用它:

    RUN --mount=type=ssh,id=github_ssh_key pip wheel \
        --no-cache \
        --requirement requirements.txt \
    --wheel-dir=/app/wheels
    

    OP Jesus Garcia 确实报告了(在 cmets 中)使其工作:

    我必须使用 2 个单独的 RUN 命令。

    我不确定这是否是这个新功能的限制,或者我试图在 RUN 中将多个命令串在一起的方式,但是当我将它添加为 other commands && /bin/sh -c "mount=type=ssh,id=github_ssh_key pip install private-repo" 时,我一直收到一个 publickey permission denied 错误与RUN --mount=type=ssh,id=github_ssh_key pip install private-repo && more commands ...

    【讨论】:

    • 我在运行 RUN --mount-type=ssh ... 部分时遇到了问题。我得到了/bin/sh: 1: --mount=type=ssh,: not found 我做了一些谷歌搜索,但我找不到任何有用的东西。
    • @JesusGarcia 这看起来像:medium.com/@tonistiigi/…。您没有使用 BuildKit 后端。检查您的 Docker 版本和文章的“使用机密”部分,您需要在其中设置 DOCKER_BUILDKIT=1
    • 我确实设置了 DOCKER_BUILDKIT=1 并且我也在正确的 docker 版本上。我设法通过以/bin/sh -c "mount=type=ssh,id=github_ssh_key pip install private-repo" 运行它来消除错误,但我现在得到了Permission denied (publickey). #12 35.87 fatal: Could not read from remote repository.
    • 我确实让它工作了。我不得不使用 2 个单独的 RUN 命令。我不确定这是否是这个新功能的限制,或者我试图在我的RUN 中将多个命令串在一起的方式,但是当我将它添加为other commands && /bin/sh -c "mount=type=ssh,id=github_ssh_key pip install private-repo" 和@987654344 时,我一直收到公钥权限被拒绝错误@ 感谢您向我指出 --ssh 标志功能
    • @dallonsi 对于受保护的私钥密码短语,您需要 buildkit:stackoverflow.com/a/64036342/6309
    【解决方案2】:

    这对我来说适用于 docker 19.03.5(但应该适用于 18.09+):

    假设你的私人仓库在 Github 上,github.com/user/repo.git 并且你想将 pip install 它作为 docker 构建的一部分。 repo 的 ssh 密钥位于主机上~/.ssh/my_key

    在 Dockerfile 中:

    RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
    RUN --mount=type=ssh pip install git+ssh://git@github.com/user/repo.git
    

    然后,在主机上:

    export DOCKER_BUILDKIT=1
    eval `ssh-agent`
    ssh-add ~/.ssh/my_key
    docker build --ssh default=$SSH_AUTH_SOCK .
    

    【讨论】:

    • 为我工作。感谢您通知主机中的 ssh-agent 应该可以工作,即使我们将 ssh 密钥传递给 docker 容器进行构建。
    【解决方案3】:

    尽管使用了现代 (19.03.8) Docker,但如果没有我在 Alexandra Ulsh's blog post 中找到的额外行,上述解决方案都对我不起作用(即使在添加 DOCKER_BUILDKIT=1 之后),我认为这足以值得额外回答而不是被埋在cmets中。

    虽然--secret 标志出现在Docker的生产版本中, 有一些迹象表明支持仍处于试验阶段。

    例如,使用构建机密的 Dockerfile 的第一行必须 是# syntax = docker/dockerfile:1.0-experimental。没有这条线 你会得到错误failed to create LLB definition: Dockerfile parse error line 6: Unknown flag: mount。此行使 Docker CLI 能够为 Moby BuildKit 使用“experimental Dockerfile frontend”。

    TL;DR 在 Dockerfile 顶部添加评论 # syntax = docker/dockerfile:1.0-experimental,然后关注 Dave Rejkher's answer

    【讨论】:

    • 有趣的更新,比我的回答更准确。赞成。
    【解决方案4】:

    我使用的是 Docker 版本 19.03.13(构建 4484c46d9d),并且使用 --ssh 中描述的功能 VonC'sDave Reikher's 答案对我不起作用。我仍然不断收到以下错误:

    错误:命令出错,退出状态为 128:git clone -q 'ssh://git@hostname:port/group/repository.git' /tmp/pip-install-8eeeaipo/baseapi 检查日志以获取完整命令输出。

    请注意,我不是来自 Github 存储库的 pip install-ing,而是来自一些 真正 私有/内部存储库。来自Docker docs on --ssh 的示例也显示了一个“github.com”repo URL。我不确定是否是这种情况(不应该是这样),但我已经追踪到 pip/git 无法识别 URL 的主机名,而如果使用“github.com”它可以作为广告。

    我只使用普通的 --secret 函数(仍然是 BuildKit 的一部分),通过传入 SSH 密钥 (~/.ssh/id_rsa) 和 ~/.ssh/known_hosts 文件作为机密来使它工作。

    Dockerfile

    # syntax=docker/dockerfile:1.0-experimental
    
    FROM python:3.8-alpine3.11
    
    RUN apk add openssh-client git
    RUN mkdir -p -m 0600 /root/.ssh
    RUN --mount=type=secret,id=known_hosts,dst=/root/.ssh/known_hosts \
        --mount=type=secret,id=ssh_key,dst=/root/.ssh/id_rsa \
        ssh-keyscan -H -t rsa hostname.of.private.repo \
        && pip install --no-cache-dir git+ssh://git@hostname:port/group/repository.git@12345678#egg=baseapi
    

    构建命令

    DOCKER_BUILDKIT=1 docker build \
        --secret id=known_hosts,src=~/.ssh/known_hosts \
        --secret id=ssh_key,src=~/.ssh/id_rsa \
        -t name:tag \
        -f Dockerfile \
        .
    

    我检查了构建映像上的~/.ssh 文件夹,它似乎仍然正确,它不保留 SSH 密钥。挂载的文件仍然存在,但它们是空的:

    /app # ls -l ~/.ssh/
    total 0
    -rwxr-xr-x    1 root     root             0 Nov 19 11:29 id_rsa
    -rwxr-xr-x    1 root     root             0 Nov 19 11:29 known_hosts
    /app # cat ~/.ssh/id_rsa 
    /app # cat ~/.ssh/known_hosts
    

    尝试pip install 相同的私有包应该会失败。

    供参考:

    * Docker: 19.03.13 (build 4484c46d9d)
    * Image
        - pip 20.2.4 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)
        - git 2.22.4
        - OpenSSH_8.1p1, OpenSSL 1.1.1g  21 Apr 2020
    

    【讨论】:

    • 如果该私有存储库还对某些私有/内部存储库具有其他私有依赖项,这是否有效。
    • @LukAron apk 是 Alpine 的包管理器。如果您没有找到命令,那么您的 Docker 映像可能不在 Alpine 上。使用容器上可用的任何一个。
    • @LukAron 至于你的第一个问题,不清楚你的意思,我认为你必须发布你自己的 separate 问题来描述你自己的 separate 问题。
    【解决方案5】:

    使用RUN --mount=type=ssh

    ci.yml

    build_docker:
      stage: build
      image: docker:latest
      variables:
        DOCKER_HOST: tcp://docker:2375
        # This instructs Docker not to start over TLS.
        DOCKER_TLS_CERTDIR: ""
    
      before_script:
        - apk add --no-cache curl jq python3 py3-pip git bind-tools openssh-client
        - echo $DOCKERPASS | docker login --username $DOCKERUSER --password-stdin
        - mkdir -p -m 0700 ~/.ssh
        - ssh-keyscan private-url >> ~/.ssh/known_hosts 
        - chmod 600 $SSH_KEY
    
      services:
        - docker:dind
    
      script:
        - export DOCKER_BUILDKIT=1
        - eval $(ssh-agent)
        - ssh-add $SSH_KEY
        - docker build -t tag_name  --ssh default=$SSH_AUTH_SOCK .
    
    

    dockerfile

    FROM puckel/docker-airflow:1.10.1
    
    ARG SSH_PRIVATE_KEY
    
    USER root
    RUN apt-get update && apt-get install -y git openssh-client
    
    
    RUN ssh-keyscan private-url >> ~/.ssh/known_hosts
    
    COPY requirements.txt .
    
    RUN --mount=type=ssh pip install git+ssh://private-url/project/repo.git
    RUN pip install -r requirements.txt
    

    看图https://feiyang233.club/img/vm/23.png

    【讨论】:

      猜你喜欢
      • 2020-10-12
      • 2012-12-19
      • 2013-04-06
      • 1970-01-01
      • 2018-11-29
      • 1970-01-01
      • 2014-11-13
      • 2014-01-01
      • 2020-09-26
      相关资源
      最近更新 更多