为了账号安全,请及时绑定邮箱和手机立即绑定

在 Docker 中使用私有 gitlab 模块构建 Go 应用程序

在 Docker 中使用私有 gitlab 模块构建 Go 应用程序

Go
陪伴而非守候 2022-08-01 17:16:59
我正在尝试在 docker 文件上构建我的 go 应用程序。在我的go.mod中,有一个需要身份验证/ ssh的私有包。这个问题类似于在Docker中使用私有模块构建Go应用程序,但在我的情况下,我必须从中提取包而不是从中提取包。这是我的 dockerfile:gitlabgithub# builder imageFROM golang:1.14.11-alpine AS builder# specific directory for build processWORKDIR /usr/src/build# copying the source code # to the current working directoryCOPY . .RUN apk add --no-cache openssh-clientRUN apk add --no-cache git# create ssh directoryRUN mkdir ~/.sshRUN touch ~/.ssh/known_hostsRUN ssh-keyscan -t rsa gitlab.com >> ~/.ssh/known_hosts# allow private repo pullRUN git config --global url."https://my-personal-access-token:token@gitlab.com/".insteadOf "https://gitlab.com/"ADD . /go/src/gitlab.com/my-repo/backends/backend-structsCMD cd /go/src/gitlab.com/my-repo/backends/backend-structs; go get /go/src/gitlab.com/my-repo/backends/backend-structs && go build -o /go/bin/backend-structs# executing build processRUN GOOS=linux go build -ldflags="-s -w" -o app# runtime imageFROM golang:1.14.11-alpine AS runtime# create and use non-root user# to increase container security # ref https://pythonspeed.com/articles/root-capabilities-docker-security/RUN adduser myuser --disabled-passwordUSER myuserWORKDIR /home/myuser# copy the executable binary file from builder directory# to the current working directoryCOPY --from=builder /usr/src/build/app .# exposing portEXPOSE 8080# run the applicationCMD ["./app"]我试图按照本教程 https://divan.dev/posts/go_get_private/,通过更改为仍然失败。github.comgitlab.com以下是错误详细信息:#17 5.830       remote: HTTP Basic: Access denied#17 5.830       fatal: Authentication failed for 'https://gitlab.com/my-repo/backends.git/'------executor failed running [/bin/sh -c GOOS=linux go build -ldflags="-s -w" -o app]: exit code: 1这里有人知道如何用golang私有包创建dockerfile(repo托管在 gitlab.com 中)?
查看完整描述

2 回答

?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

根据我的经验,不要使用git配置来解决这个问题。仅使用 .以下是专门为此制作的指南:https://gist.github.com/MicahParks/1ba2b19c39d1e5fccc3e892837b10e21~/.netrc


我也会将其内容粘贴在下面。


问题

命令行工具需要能够从私有 GitLab 获取依赖项,但需要身份验证。go


这假设您的私有 GitLab 托管在 。privategitlab.company.com


环境变量

建议使用以下环境变量:


export GO111MODULE=on

export GOPRIVATE=privategitlab.company.com

上面的行可能最适合您的 shell 启动,例如 .~/.bashrc


解释

GO111MODULE=on告诉Golang命令行工具您正在使用模块。我还没有在私有GitLab上不使用Golang模块的项目上对此进行测试。


GOPRIVATE=privategitlab.company.com告诉Golang命令行工具不要对列出的主机名(如公共模块代理)使用公共互联网资源。


从您的私有 GitLab 获取个人访问令牌

为了将来证明这些说明,请按照 GitLab 文档中的本指南进行操作。我知道Golang命令行工具需要该范围才能工作,我可能也怀疑,但尚未确认这一点。read_apiread_repository


设置~/.netrc

为了使 Golang 命令行工具能够向 GitLab 进行身份验证,最好使用一个文件。~/.netrc


若要创建该文件(如果该文件不存在),请运行以下命令:


touch ~/.netrc

chmod 600 ~/.netrc

现在编辑文件的内容以匹配以下内容:


machine privategitlab.company.com login USERNAME_HERE password TOKEN_HERE

Where 将替换为您的 GitLab 用户名,并替换为上一节中获取的访问令牌。USERNAME_HERETOKEN_HERE


常见错误

不要使用如下内容设置全局 git 配置:


git config --global url."git@privategitlab.company.com:".insteadOf "https://privategitlab.company.com"

我相信在撰写本文时,Golang命令行工具并不完全支持SSH git,这可能会导致与.~/.netrc


奖励:SSH 配置文件

对于该工具的常规使用,而不是Golang命令行工具,设置文件很方便。为此,请运行以下命令:git~/.ssh/config


mkdir ~/.ssh

chmod 700 ~/.ssh

touch ~/.ssh/config

chmod 600 ~/.ssh/config

请注意,上述文件和目录的权限是essentail,以便SSH在大多数Linux系统上以默认配置工作。


然后,编辑该文件以匹配以下内容:~/.ssh/config


Host privategitlab.company.com

  Hostname privategitlab.company.com

  User USERNAME_HERE

  IdentityFile ~/.ssh/id_rsa

请注意,上述文件中的间距很重要,如果文件不正确,将使文件无效。


您的 GitLab 用户名在哪里,并且是文件系统中 SSH 私钥的路径。您已经将其公钥上传到GitLab。以下是一些说明。USERNAME_HERE~/.ssh/id_rsa


查看完整回答
反对 回复 2022-08-01
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

我在私有仓库中遇到了这个问题。我使用作为解决方案,但是,我遇到了困难,因为其他答案中存在各种假设。在我的情况下,我的密钥文件名有问题,另一个问题是AppArmor。github.comssh-agent


我将在下面详细讨论我的设置和这些问题。


实验性 Docker 功能

首先,在 中,您希望通过在第一行添加类似这样的注释来允许较新的选项:Dockerfile


# syntax=docker/dockerfile:experimental

这将使我们能够使用该选项。--mount=type=ssh


注意:如果注释不在第一行,它将被忽略,并且诸如--mount=...之类的扩展名将失败。


基本设置Dockerfile

像你一样,我们使用Go alpine。我们还确保获得.openssh-client


FROM golang:alpine AS build-env

RUN apk --no-cache add build-base git mercurial gcc curl openssh-client

详细,我们添加我们的代码(整个文件夹):


ADD . .

创建 & 文件known_hosts.gitconfig

现在我们有一个问题,因为默认情况下,SSH不会识别密钥。为避免此问题,我们希望将(在您的情况下)密钥添加到我们的已知主机。我们还希望确保将其与SSH一起使用,而不是与HTTPS一起使用。github.comgitlab.comgithub.com


RUN mkdir -p -m 0700 ~/.ssh && \

    ssh-keyscan github.com >> ~/.ssh/known_hosts && \

    echo -e "[url \"git@github.com:<company-name>\"]\n\tinsteadOf = https://github.com/<company-name>" >> ~/.gitconfig

注意:此时 docker 中的 ~ 始终是 /root。


有些人附加一个卷,让 Docker 访问他们的文件。我不认为这是安全的,如果你运行CircleCI等在线工具,它很可能会崩溃。known_hosts


构建 Go 应用程序

这为我们提供了最终构建应用程序的所有必要元素:


ENV GO111MODULE=on

ENV GOPRIVATE=github.com/<company-name>

RUN --mount=type=ssh cd cmd/app/ && go build -o app

我们的 Dockerfile 还有几行,这里没有介绍,用于定义其他文件和最终的 ENTRYPOINT。


加载键输入ssh-agent

我们几乎准备好运行 .但是我们仍然需要在我们的.这很简单:docker build ...ssh-agent


ssh-add id_rsa

超级非常重要:密钥的名称必须是预期的默认值之一。 就是其中之一。如果您的密钥名称不是默认值之一,则不会选取该密钥。sshid_rsa


以下是在我的一个测试中检查的名称。运行命令时会看到这些内容(见下文)。ssh -A -v ...


#18 0.828 debug1: identity file /root/.ssh/id_rsa type -1

#18 0.828 debug1: identity file /root/.ssh/id_rsa-cert type -1

#18 0.828 debug1: identity file /root/.ssh/id_dsa type -1

#18 0.828 debug1: identity file /root/.ssh/id_dsa-cert type -1

#18 0.829 debug1: identity file /root/.ssh/id_ecdsa type -1

#18 0.829 debug1: identity file /root/.ssh/id_ecdsa-cert type -1

#18 0.829 debug1: identity file /root/.ssh/id_ecdsa_sk type -1

#18 0.829 debug1: identity file /root/.ssh/id_ecdsa_sk-cert type -1

#18 0.829 debug1: identity file /root/.ssh/id_ed25519 type -1

#18 0.829 debug1: identity file /root/.ssh/id_ed25519-cert type -1

#18 0.829 debug1: identity file /root/.ssh/id_ed25519_sk type -1

#18 0.829 debug1: identity file /root/.ssh/id_ed25519_sk-cert type -1

#18 0.829 debug1: identity file /root/.ssh/id_xmss type -1

#18 0.829 debug1: identity file /root/.ssh/id_xmss-cert type -1

您可以使用以下命令检查密钥是否已加载:


ssh-add -l

每个键的名称应显示在行的末尾。它必须是上面提到的默认值之一(您也可以摆弄docker文件中的条目)。Host.ssh/config


构建 Docker 映像

为了构建映像,我们现在按如下方式运行:docker


DOCKER_BUILDKIT=1 docker build --progress=plain .

(当然,您可以使用其他选项,例如--build-arg GO_VERSION=...来强制使用golang的一个版本)


这使您能够更好地了解正在发生的事情。不知何故,它会阻止 Docker 保存中间映像和容器,因此如果没有该选项,您将无法进行太多调试。--progress=plainDOCKER_BUILDKIT=1


选项--ssh default

可能仍需要此命令行选项。我实际上使用它。但是,在最新版本的 docker 中,如果检测到(或类似的?),它会自动打开。我不太确定它是否可以在所有情况下检测到这种情况。如果遇到问题,请确保在命令行中包含该选项。git@github.com... docker build ...


在我的经验中,没有必要具体说明任何细节。就足够了。default


调试 SSH 连接

如果您在连接时遇到问题(即SSH告诉您连接被拒绝),那么您可以在调试之前添加RUN命令以调试该部分:RUN ... go build ...


RUN ssh -A -v -l git github.com

该选项告诉 SSH 使用 检索私钥。

要求 SSH 打印出调试信息。

该选项定义用户名。对于 ,您需要用作用户名。默认情况下,使用 Docker 内部的 .这是行不通的。-Assh-agent-v-lgithub.comgitssh$USERroot


如果连接有效,则告诉您已获得授权,但没有要连接的 shell,因此您立即被踢出。如果您没有看到该友好消息,则 SSH 尚未正确设置。实际上,您可以在控制台中测试该连接,如下所示:github.com


$ ssh -l git github.com

PTY allocation request failed on channel 0

Hi <your-name>! You've successfully authenticated, but GitHub does not provide shell access.

Connection to github.com closed.

问题 1:apparmor

所有这些都对我不起作用。事实是,会创建一个隐藏在下方的套接字,并且默认情况下不允许该路径进入工具和服务。至少,如果你的内核像Ubuntu服务器一样有apparmor,它就不会起作用。ssh-agent/run/user/<uid>/keyring/sshdocker ...


您可以通过查看您的或类似文件(可能是 )来查看这种情况。将出现“已拒绝”错误,如下所示:/var/log/syslog/var/log/auth.log


Oct 28 10:42:13 ubuntu2004 kernel: [78018.511407] audit: type=1400 audit(1635442933.692:143): apparmor=“DENIED” operation=“connect” profile=“snap.docker.docker” name=“/run/user/1000/keyring/ssh” pid=36260 comm=“docker” requested_mask=“wr” denied_mask=“wr” fsuid=1000 ouid=1000


我们看到我的密钥环套接字的完整路径,拒绝访问的apparmor配置文件的名称,以及操作,这里是“连接”。要解决此问题,您首先需要找到配置文件。这是在 :/var/lib/snapd


/var/lib/snapd/apparmor/profiles/snap.docker.docker

然后运行以下命令:


$ sudo apparmor_parser -r \

          /var/lib/snapd/apparmor/profiles/snap.docker.docker

以刷新 apparmor 设置。


如果您不使用Docker的快照版本,则配置文件通常位于下,但我无法在较新版本的Docker(2021)中看到该文件.../etc/apparmor.d/...


编辑该文件,转到末尾,然后在结束字符之前,输入以下行:}


/run/user/1000/keyring/ssh rw,

这意味着将能够读取和写入此特定套接字。docker


显然,这是一个特定的用户。如果不是您,请使用您的用户 ID () 或要运行的用户标识符。1000id -udocker build ...


您也可以允许该计算机上的所有用户,但不建议这样做:


/run/user/[0-9]*/keyring/ssh rw,

(它仍然非常安全,因为你只给docker权限,但你永远不会知道...)


问题 2:密钥文件名

我在这里重复第二个问题,因为这非常重要。来自 Docker 的密钥查找将搜索一个名为 (和其他类似的默认密钥名称,见上文)的密钥。如果你为密钥使用特殊名称,比如说 ,那么 Docker 不会选取它。id_rsagithub_rsa


您可以通过添加以下内容来将该文件用于此目的:.ssh/config


Host github.com

  IdentityFile /root/.ssh/github_rsa

在某个时候,我摆弄了这样,但无法使它工作。可能是因为问题#1(又名apparmor)。但是,如果您要与许多程序员共享您的名称,则需要很好地记录以这种方式使用特殊名称。大多数程序员不做这样的事情,他们可能需要一段时间才能找出为什么他们不能在他们的系统上创建Docker映像。Dockerfile


什么都不做!chmod

在许多页面/答案中,您会看到权限通常使用命令进行解析。例如,如果有人认为 Docker 无法访问他们的密钥,因为其文件夹上的权限为 700 (rwx-----) 或文件的权限为 600 (rw-------),则可能认为更改这些权限会有所帮助。它不会。中的条目足以根据需要共享您的私钥。chmod/run/user/1000~/.ssh/...ssh-agent


关于使用的附注.netrc

据我所知,当您使用 时,您会在 Docker 映像中包含您的凭据。这意味着任何获得图像副本的人都有您的凭据。可能不是你想要的东西。如果您的图像仅在内部使用,则可能没问题....netrc


查看完整回答
反对 回复 2022-08-01
  • 2 回答
  • 0 关注
  • 147 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号