簡體   English   中英

在 Docker 中使用私有 gitlab 模塊構建 Go 應用程序

[英]Building Go apps with private gitlab modules in Docker

我正在嘗試在 docker 文件上構建我的 go 應用程序。 在我的 go.mod 中,有一個需要身份驗證/ssh 的私有 package。 This question is similar to Building Go apps with private modules in Docker , but in my case is i have to pull package from gitlab not from 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"]

i have tried to follow this tutorial https://divan.dev/posts/go_get_private/ , by changing github.com to gitlab.com still failed.

以下是錯誤詳情:

#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 中)?

根據我的經驗,不要使用 git 配置來解決這個問題。 僅使用~/.netrc 這是專門為此制作的指南: https://gist.github.com/MicahParks/1ba2b19c39d1e5fccc3e892837b10e21

我也會在下面粘貼它的內容。

問題

go命令行工具需要能夠從您的私有 GitLab 中獲取依賴項,但需要進行身份驗證。

這假設您的私有 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 文檔中的本指南 我知道read_api命令行工具需要 read_api scope 才能工作,我也可能懷疑read_repository ,但尚未確認這一點。

設置~/.netrc

為了讓 Golang 命令行工具對 GitLab 進行身份驗證,最好使用~/.netrc文件。

如果文件不存在,要創建該文件,請運行以下命令:

touch ~/.netrc
chmod 600 ~/.netrc

現在編輯文件的內容以匹配以下內容:

machine privategitlab.company.com login USERNAME_HERE password TOKEN_HERE

其中USERNAME_HERE替換為您的 GitLab 用戶名, TOKEN_HERE替換為上一節中獲取的訪問令牌。

常見錯誤

不要使用以下內容設置全局 git 配置:

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

我相信在撰寫本文時,Golang 命令行工具不完全支持 SSH git,這可能會導致與~/.netrc沖突。

獎勵:SSH 配置文件

為了經常使用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_HERE是您的 GitLab 用戶名,而~/.ssh/id_rsa是文件系統中 SSH私鑰的路徑。 您已經將其公鑰上傳到 GitLab。 這里有一些說明

我在私有github.com存儲庫中遇到了這個問題。 我使用ssh-agent作為解決方案,但是,我遇到了困難,因為有各種各樣的假設。 就我而言,密鑰的文件名存在問題,另一個問題是 AppArmor。 我將在下面詳細討論我的設置和這些問題。

實驗 Docker 特性

首先,在Dockerfile中,您希望通過在第一行添加類似這樣的注釋來允許更新的選項:

# syntax=docker/dockerfile:experimental

這將允許我們使用--mount=type=ssh選項。

基本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 不會識別密鑰。 為了避免問題,我們要添加github.comgitlab.com 我們還想確保github.com與 SSH 一起使用,而不是 Z0E8433F9A1404F1D32B601。

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 之類的工具,它很可能會崩潰。

構建 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

非常重要:密鑰的名稱必須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 ,如下所示:

DOCKER_BUILDKIT=1 docker build --progress=plain .

(當然,您可以使用其他選項,例如--build-arg GO_VERSION=...來強制使用 golang 版本)

--progress=plain使您能夠更好地了解正在發生的事情。 不知何故, DOCKER_BUILDKIT=1會阻止 Docker 保存中間圖像和容器,因此如果沒有它,您將無法進行太多調試。

--ssh default選項

可能仍需要此命令行選項。 我實際上使用它。 但是,在最新版本的 docker 中,如果檢測到git@github.com (或類似的?),它會自動打開。 我不太確定它是否可以在所有情況下檢測到這種情況。 如果您遇到問題,請確保在... docker build...命令行中包含該選項。

根據我的經驗,無需指定任何細節。 只要default就夠了。

調試 SSH 連接

如果您遇到連接問題(即 SSH 告訴您連接被拒絕),那么您可以在RUN... go build...之前添加一個 RUN 命令來調試該部分:

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

-A選項告訴 SSH 使用ssh-agent檢索私鑰。
-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.

問題一: apparmor

所有這些對我都不起作用。 事實是ssh-agent創建了一個隱藏/run/user/<uid>/keyring/ssh下的套接字,並且默認情況下不允許docker...工具和服務的路徑。 至少,如果您的 kernel 具有像 Ubuntu 服務器這樣的設備,那么它不會工作。

您可以通過查看您的/var/log/syslog或類似的文件(可能是/var/log/auth.log )來看到這種情況。 會有一個 DENIED 錯誤,如下所示:

10月28日10:42:13 Ubuntu2004 kernel:[78018.511407]審核:類型= 1400審核(1635442933.692:143:143)用戶/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

如果您不使用 Docker 的 snap 版本,配置文件通常位於/etc/apparmor.d/...下,但我無法在 docker (2021) 的較新版本中看到該文件...

編輯該文件 go 到末尾,在結束}字符之前,輸入以下行:

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

這意味着docker將能夠讀取和寫入此特定套接字。

顯然, 1000是一個特定的用戶。 使用您的用戶 ID ( id -u ) 或運行docker build...如果不是您的話。

您也可以允許該計算機上的所有用戶,但不建議這樣做:

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

(它仍然很安全,因為您只向docker授予該權限,但您永遠不知道......)

問題 2:密鑰文件名

我在這里重復第二個問題,因為那非常重要。 來自 Docker 的鍵查找將搜索名為id_rsa的鍵(以及其他類似的默認鍵名,見上文)。 如果您對密鑰使用特殊名稱,例如github_rsa ,則 Docker 不會獲取它。

您可以通過添加以下內容來使用.ssh/config文件:

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

在某些時候,我擺弄了這樣的東西,但無法讓它發揮作用。 可能是因為問題 1(又名 apparmor)。 但是,如果您與許多程序員共享您的Dockerfile ,則需要詳細記錄以這種方式使用特殊名稱。 大多數程序員不這樣做,他們可能需要一段時間才能找出為什么他們不能在他們的系統上創建 Docker 映像。

不要chmod任何東西!

在許多頁面/答案中,您會看到權限通常是使用chmod命令解決的。 例如,有人認為 Docker 無法訪問他們的密鑰,因為他們/run/user/1000文件夾的權限為 700 (rwx-----) 或 600 (rw--------)他們的~/.ssh/...文件可能認為更改這些權限會有所幫助。 它不會。 ssh-agent中的條目足以根據需要共享您的私鑰。

關於使用.netrc的旁注

據我所知,當您使用.netrc時,會將您的憑據包含在 Docker 映像中。 這意味着任何獲得您的圖像副本的人都擁有您的憑據。 可能不是你想要的東西。 如果您的圖像僅在內部使用,那可能沒問題...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM