見出し画像

プライベートリポジトリを利用するgolangのdockerコンテナをビルドする際のfatal: could not read Username〜

概要

前回と同じ、プライベートリポジトリを利用するgolangアプリの構成で、Dockerコンテナビルドするとエラーになりつまづいたのでその対応などについて書きたい。

事前条件

プライベートリポジトリの「Go_T_Used_Private_Repo」の「mylog」パッケージを参照する実装。

.
├── go.mod
├── go.sum
└── main.go
package main

import (
	"fmt"

	"github.com/ArtefactGitHub/Go_T_Used_Private_Repo/mylog"
)

func main() {
	fmt.Printf("start\n")

	l := mylog.MyLog{}
	l.Print("hoge")
}


Dockerコンテナ化するためDockerfileを作成する。

.
├── Dockerfile
├── go.mod
├── go.sum
└── main.go
# syntax=docker/dockerfile:1

FROM golang:1.16-alpine

ENV ROOT=/usr/src/app

WORKDIR ${ROOT}

COPY . .

# for go mod download
RUN apk add --update --no-cache ca-certificates git \
      && go mod download \
      && go build -v -o /usr/local/bin/app ./...

CMD ["app"]

モジュールをダウンロードしてビルドを行う手続きを記述。
ちなみに「RUN apk add〜」はdocker build時に「go mod download」でエラーになる件の対応(参考リンク)。

> [4/5] RUN go mod download:
#12 0.449 go: github.com/ArtefactGitHub/Go_T_Used_Private_Repo@v0.0.0-20220514010304-64929e41f25d: git init --bare in /go/pkg/mod/cache/vcs/d3603b7e023f500f004f718c5436e0c7ac55af14caa872278d138802dc245e82: exec: "git": executable file not found in $PATH
------
executor failed running [/bin/sh -c go mod download]: exit code: 1


上記Dockerfileの状態でdocker buildを行うとエラーになる。

 > [5/6] RUN go mod download:                                                                                                                                                                            
#13 1.309 go: github.com/ArtefactGitHub/Go_T_Used_Private_Repo@v0.0.0-20220514010304-64929e41f25d: invalid version: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* in /go/pkg/mod/cache/vcs/d3603b7e023f500f004f718c5436e0c7ac55af14caa872278d138802dc245e82: exit status 128:                                                                                                             
#13 1.309       fatal: could not read Username for 'https://github.com': terminal prompts disabled
------
executor failed running [/bin/sh -c go mod download]: exit code: 1


GitHubのアクセストークンを使う.gitconfigの設定を行うことで解消する。
ARG構文を使い環境変数を渡すパターンでは、まずARGで宣言しておき、ビルド時のコマンドで値を渡してもらう(ホスト側環境変数を暗黙的に渡す方法は無いもよう)。

# syntax=docker/dockerfile:1

FROM golang:1.16-alpine

# ARG宣言し、ビルド時のコマンドで渡してもらう
ARG GITHUB_TOKEN

ENV ROOT=/usr/src/app

WORKDIR ${ROOT}

# 作業ディレクトリを全てコピー
COPY . .

# go mod download時エラー解消、プライベートのパッケージ取得のためトークン設定、パッケージダウンロード、ビルド
RUN apk add --update --no-cache ca-certificates git \
  && git config --global url."https://${GITHUB_TOKEN}:x-oauth-basic@github.com/".insteadOf "https://github.com/" \
  && go mod download \
  && go build -v -o /usr/local/bin/app ./...


CMD ["app"]
$ docker build -t <任意のイメージ名> --build-arg GITHUB_TOKEN=<GItHubアクセストークン> .

ビルドが行えるようになりこれでOKかと思ったが、Dockerイメージに秘密情報のトークンの値が入ってしまうという問題がある。

$ docker history <イメージ名>
〜割愛〜
RUN |1 GITHUB_TOKEN=<トークン>…   15.3MB    buildkit.dockerfile.v0


対応策

「git config --global」について考えると、要はDockerコンテナ内の必要な場所に必要な記述がされた「.gitconfig」ファイルが配置されていればビルド時に渡さなくてもいいんじゃ?と思った。
ローカルのプロジェクトディレクトリのルートに作成した「プロジェクト用の.gitconfig」をコンテナ内に配置してビルドが行えるようになるかやってみた(「.gitconfig」はビルド後(プライベートパッケージインストール後)に削除する)。

# syntax=docker/dockerfile:1

FROM golang:1.16-alpine

ENV ROOT=/usr/src/app

WORKDIR ${ROOT}

# 作業ディレクトリを全てコピー(本来は必要なものだけでよい)
COPY . .

# プライベートリポジトリのパッケージ取得のため、
# このプロジェクト用に作成した.gitconfigを/rootへコピー
# (↓コマンドを行なった際と同じrootへ配置する)
# git config --global url."https://<GitHub Personal Access Token>:x-oauth-basic@github.com/".insteadOf "https://github.com/"
COPY .gitconfig /root

# go mod download時エラー解消、パッケージダウンロード、ビルド、秘密情報ファイル削除
RUN apk add --update --no-cache ca-certificates git \
  && go mod download \
  && go build -v -o /usr/local/bin/app ./... \
  && rm .gitconfig /root/.gitconfig

# 待機する必要があるアプリ用
EXPOSE 8000

CMD ["app"]

上記内容で実行したところビルドが行えた。
history上もコピーコマンドしか残らず、コンテナ内に秘密情報ファイルも残らない。
懸念として、もしコンテナ実行後に動的に別のプライベートリポジトリのパッケージのインストールが行われるようなことがあると失敗するが、そうでなければこんなのでもいいんじゃないかと思った。

あとがき

非公開のイメージで開発中のコンテナの秘密情報をどうするかなんて頑張らなくてもいいかもだが、検証で色々試しているとコンテナの扱いの良い勉強になった。

パッケージのキャッシュ削除
→ go clean --modcache

イメージビルド時にARGに値を渡す
→ docker build -t <イメージ名> --build-arg <ARGのキー>=<値>

停止しているコンテナの中に入る
(中でgo mod download実行検証やパッケージのキャッシュの中身を確認
 するなどコンテナ内調査用)
→ docker run -it <コンテナ名> sh

イメージの詳細な内容閲覧
→ docker inspect image <イメージ名>

イメージビルド時の操作履歴閲覧
→ docker history <イメージ名>

未利用のコンテナ、イメージの全削除
→ docker container prune
  docker image prune

この記事が気に入ったらサポートをしてみませんか?