当前位置: 首页 > 知识库问答 >
问题:

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

濮俊美
2023-03-14

我正在尝试在docker文件上构建我的go应用程序。在我的内心深处。mod有一个需要身份验证/ssh的私有包。这个问题类似于在Docker中使用私有模块构建Go应用程序,但在我的情况下,我必须从gitlab而不是github中提取包。这是我的dockerfile:

# builder image
FROM golang:1.14.11-alpine AS builder

# specific directory for build process
WORKDIR /usr/src/build

# copying the source code 
# to the current working directory
COPY . .
RUN apk add --no-cache openssh-client
RUN apk add --no-cache git

# create ssh directory
RUN mkdir ~/.ssh
RUN touch ~/.ssh/known_hosts
RUN ssh-keyscan -t rsa gitlab.com >> ~/.ssh/known_hosts

# allow private repo pull
RUN 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-structs
CMD 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 process
RUN GOOS=linux go build -ldflags="-s -w" -o app

# runtime image
FROM 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-password

USER myuser

WORKDIR /home/myuser

# copy the executable binary file from builder directory
# to the current working directory
COPY --from=builder /usr/src/build/app .

# exposing port
EXPOSE 8080

# run the application
CMD ["./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

这里有人知道如何使用Go语言私有包创建dockerfile(repo托管在gitlab.com)吗?

共有2个答案

乐正远航
2023-03-14

我用privategithub遇到了这个问题。com存储库。我使用了ssh代理作为解决方案,但是,我遇到了一些困难,因为在其他答案中有各种各样的假设。在我的例子中,我对密钥的文件名有一个问题,另一个问题是AppArmor。

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

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

# syntax=docker/dockerfile:experimental

这将允许我们使用--Mount=type=ssh选项。

注意:如果注释不在第一行,它将被忽略,扩展名如--mount= 失败。

和你一样,我们也使用高山滑雪。我们还确保获得openssh客户端

FROM golang:alpine AS build-env
RUN apk --no-cache add build-base git mercurial gcc curl openssh-client

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

ADD . .

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

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可以访问他们的known_hosts文件。我不认为这是安全的,如果你运行像CircleCI这样的在线工具,它很可能会崩溃。

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

ENV GO111MODULE=on
ENV GOPRIVATE=github.com/<company-name>
RUN --mount=type=ssh cd cmd/app/ && go build -o app

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

我们几乎准备好运行docker构建...。但是我们仍然需要在我们的ssh-agent中定义密钥。这很简单:

ssh-add id_rsa

超级非常重要:键的名称必须是ssh期望的默认值之一。id_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. ssh/config文件中摆弄Host条目)。

为了构建映像,我们现在运行docker,如下所示:

DOCKER_BUILDKIT=1 docker build --progress=plain .

(当然,您可以使用其他选项,如--build arg GO_VERSION=…强制生成golang版本)

--progress=plain使您能够更好地了解正在发生的事情。不知何故,DOCKER\u BUILDKIT=1阻止DOCKER保存中间映像和容器,因此如果没有该选项,您将无法进行大量调试。

此命令行选项可能仍然是必需的。我真的在用它。但是,在最新版本的docker中,如果git@github.com(或类似?)被检测到。我不太确定它是否能在所有情况下检测到这种情况。如果您遇到问题,请确保在中包含该选项。。。码头工人建造 命令行。

在我的经历中没有必要具体说明任何细节。只要默认就足够了。

如果您的连接有问题(即SSH告诉您连接被拒绝),那么您可以在RUN之前添加RUN命令。。。去建造 仅调试该部分:

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

-A选项告诉SSH使用SSH代理来检索私钥
-v要求SSH打印调试信息
-l选项定义用户名。对于github。com,您需要使用git作为用户名。默认情况下,ssh使用$USER,Docker中的root。那不行。

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

$ 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.

所有这些对我都不起作用。事实上,ssh代理创建了一个隐藏在/run/user下的套接字/

您可以通过查看您的/var/log/syslog或类似的文件(可以是/var/log/auth.log)来发现这一点。会有一个像这样的否认错误:

Oct28 10:42:13ubuntu2004内核:[78018.511407]审核:type=1400审核(1635442933.692:143):设备="拒绝"操作="连接"配置文件="snap.docker.docker"name="/run/user/1000/keyring/ssh"pid=36260 comm="docker"requested_mask="wr"denied_mask="wr"fsuid=1000 ouid=1000

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

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

如果不使用snap版本的Docker,则通常可以在/etc/apparmor下找到配置文件。d/ ,但我在更新版本的docker(2021)中看不到该文件。。。

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

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

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

显然,1000是一个特定的用户。使用您的用户ID(ID-u)或要运行docker build的用户标识符 如果不是你。

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

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

(它仍然是相当安全的,因为你只给权限docker,但你永远不知道...)

我在这里重复第二个问题,因为这非常重要。Docker的密钥查找将搜索名为id\u rsa(以及其他类似的默认密钥名,请参见上文)的密钥。如果您对密钥使用特殊名称,比如说github\u rsa,则Docker将不会提取该密钥。

为此,您可以使用. ssh/config文件,方法是添加:

Host github.com
  IdentityFile /root/.ssh/github_rsa

在某个时候,我摆弄了一下,但没能让它发挥作用。可能是因为问题#1(又名幽灵)。然而,如果您与许多程序员共享您的Dockerfile,那么以这种方式使用特殊名称需要有很好的文档记录。大多数程序员不做这样的事情,他们可能需要一段时间来找出为什么他们不能在他们的系统上创建Docker映像。

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

据我所知,当您使用时。netrc,您可以将凭证包含在Docker映像中。这意味着任何获得您图像副本的人都拥有您的凭据。可能不是你想要的。如果你的图像只在内部使用,它可能是好的。。。

岳正阳
2023-03-14

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

我也会把它的内容贴在下面。

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

这假设您的私有GitLab托管在privategitlab。公司com

建议使用以下环境变量:

export GO111MODULE=on
export GOPRIVATE=privategitlab.company.com

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

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

GOPRIVATE=privategitlab。公司com告诉Golang命令行工具不要将公共internet资源用于列出的主机名(如公共模块代理)。

为了进一步验证这些说明,请遵循GitLab文档中的指南。我知道Golang命令行工具需要使用read_api范围,我可能也怀疑read_repository,但尚未确认这一点。

为了让Golang命令行工具验证到GitLab,最好使用~/. netrc文件。

要创建不存在的文件,请运行以下命令:

touch ~/.netrc
chmod 600 ~/.netrc

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

machine privategitlab.company.com login USERNAME_HERE password TOKEN_HERE

其中,USERNAME\u此处替换为您的GitLab用户名,TOKEN\u此处替换为上一节中获得的访问令牌。

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

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

我相信在写这篇文章的时候,Golang命令行工具不完全支持SSHgit,这可能会导致与~/. netrc冲突。

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

mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/config
chmod 600 ~/.ssh/config

请注意,上面的文件和目录上的权限对于SSH在大多数Linux系统上的默认配置中工作至关重要。

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

Host privategitlab.company.com
  Hostname privategitlab.company.com
  User USERNAME_HERE
  IdentityFile ~/.ssh/id_rsa

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

其中,USERNAME\u这里是您的GitLab用户名,~/。ssh/id\u rsa是文件系统中ssh私钥的路径。您已经将其公钥上载到GitLab。这里有一些说明。

 类似资料:
  • 问题内容: 我正在尝试使用我的go应用程序创建一个docker映像。该应用程序(在MacOS上开发)取决于哪个,而又取决于我在Docker映像中安装的对象,如下所示: 我收到以下错误: 我/app/folder/vendor/github.com/confluentinc/confluent-kafka-go/kafka ../folder/vendor/github.com/confluenti

  • 我有一个Spring boot应用程序,它有许多模块,如错误模块、持久性、控制器等,如下所示 使用Maven jib插件构建docker镜像,pom中的配置如下。xml 构建成功了。但是当我运行图像时,它的抛出错误是:找不到或加载主类com。a、 卑诗省申请 如何使用Jib构建图像?。我错过了什么?

  • 我在一台Ubuntu机器上安装了Gitlab。我在Gitlab中以ABC的名义拥有dotnetcore项目。 但是,在ABC存储库中有多个具有不同目录的小型doetnetcore应用程序,例如abc1 abc2 abc3 abc4。 我想在ABC下编写一个管道,在开发人员将代码推送到相应目录时创建docker映像。但这需要为那个唯一的目录创建docker镜像。 例如:开发人员将代码推送到abc3目

  • 我已经在一台乌班图机器上安装了Gitlab。我在Gitlab上有以ABC的名义的点网核心项目。 但是,在ABC repo中有多个不同目录的小doetnetcore应用程序,如abc1 abc2 abc3 abc4。 我想在ABC下编写一个管道,以便在开发人员在相应的目录中推送代码时创建docker映像。但这需要为该唯一的目录创建泊坞窗映像。 例如:开发人员将代码推送到abc3目录下,该时间管道运行

  • 我正在尝试创建一个管道,使用JIB(通过Maven插件)创建docker图像,并将其推送到我的Gitlab注册表。 当我登录到docker注册表时,这在本地运行良好。 说我有一个。gitlab ci。yml看起来像: 现在我在管道被触发时得到一个异常 我假设我得到了这个错误,因为我还没有运行docker login-u[用户名]-p[密码/令牌] 我怎么会需要一个.gitlab-ci.yml,它使

  • 问题内容: 我的Dockerfile位于文件夹的根目录中,包含在主包中。 看起来如下: 我收到以下错误: 我究竟做错了什么?码头工人完成后可以登录命令吗? 问题答案: 您正在将所有文件复制到Image根目录,未安装任何依赖项,尝试构建它,然后从运行二进制文件。该目录中不存在二进制文件,并且正在生成错误。 我建议使用这样的Dockerfile, 这将执行以下操作。 将项目文件复制到。 将工作目录设置