エラーの内容
go: could not create module cache: mkdir /go/pkg/mod: permission denied
GoがモジュールキャッシュディレクトリへのThe cannot write. これは主に、Dockerコンテナ内でのビルド、CI/CDパイプラインでのジョブ実行、あるいは誰かがsudo付きでgoコマンドを実行した場合に発生します。sudoで実行するとキャッシュがrootの所有になり、通常ユーザーが書き込めなくなってしまいます。
原因
Goはダウンロードしたモジュールを$GOPATH/pkg/modにキャッシュします。Dockerイメージ内では通常/go/pkg/mod、通常のLinuxやmacOSマシンではデフォルトで~/go/pkg/modになります。
よくある原因:
- Dockerイメージで前のステップがrootとして実行されたため、アプリユーザーが
go buildを実行する前に/go/pkg/modがroot所有で作成されてしまっている。 - 共有マシン上で
sudo go getやsudo go buildを実行したため、キャッシュがrootの所有でシードされてしまっている。 - GOPATHがシステムディレクトリ(
/go、/usr/local/go)に設定されており、現在のユーザーが書き込めない。 - CI/CDランナーがボリュームやキャッシュをマウントしているが、それが以前のジョブで別のユーザーによって作成されたものである。
修正方法1 — キャッシュディレクトリの所有者を変更する(最も一般的)
キャッシュがrootに乗っ取られた場合は、所有権を取り戻しましょう:
# 所有者を確認する
ls -la $(go env GOPATH)/pkg/mod
# 所有権を修正する(必要に応じて$USERをユーザー名に置き換えてください)
sudo chown -R $USER:$USER $(go env GOPATH)/pkg/mod
go buildまたはgo mod downloadを再実行すれば、すぐに動作するはずです。
修正方法2 — GODMODCACHEを書き込み可能なディレクトリに変更する
共有サーバーや制限された環境でchownできない場合は、自分が所有するディレクトリにキャッシュをリダイレクトしましょう:
# 一時的(現在のセッションのみ)
export GOMODCACHE=$HOME/go/pkg/mod
# 永続的 — ~/.bashrcまたは~/.zshrcに追加する
echo 'export GOMODCACHE=$HOME/go/pkg/mod' >> ~/.bashrc
source ~/.bashrc
# 確認
go env GOMODCACHE
設定後にgo mod downloadを実行してください。Goはホームディレクトリ以下に新しいキャッシュパスを作成し、以降はそこを使用します。
修正方法3 — GOPATHを修正する(システムディレクトリを指している場合)
現在GOPATHがどこを指しているか確認します:
go env GOPATH
/goや/usr/local/goのような出力が原因です — これらのパスはrootが所有しています。ユーザーが所有する場所にリセットしましょう:
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
# シェルプロファイルに追加して永続化する
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc
source ~/.bashrc
修正方法4 — Dockerコンテナの修正
このエラーが最もよく発生するのはDockerです。あるレイヤーがrootとしてgoコマンドを実行し、/go/pkg/modをroot所有にしてしまいます。その後のステップで非rootユーザーに切り替わると、そのユーザーはキャッシュにアクセスできなくなります。
オプションA — すべて同じユーザーとして実行する:
FROM golang:1.22
# すべてのgoコマンドはrootとして実行 — 一貫性があり、パーミッションの不一致がない
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o myapp .
オプションB — 非rootユーザーを作成し、そのホーム以下にGOPATHを設定する:
FROM golang:1.22
RUN useradd -m -u 1001 appuser
USER appuser
WORKDIR /home/appuser/app
# GOPATHはデフォルトで~/goになり、appuserが所有する
COPY --chown=appuser:appuser go.mod go.sum ./
RUN go mod download
COPY --chown=appuser:appuser . .
RUN go build -o myapp .
オプションC — Dockerfile内でGODMODCACHEを書き込み可能なパスに明示的に設定する:
ENV GOMODCACHE=/tmp/gomodcache
RUN go mod download
修正方法5 — CI/CDパイプライン(GitHub Actions / GitLab CI)
パイプライン実行間でGoモジュールをキャッシュすると速度が上がりますが、誤ったユーザーが所有する古いキャッシュボリュームがあるとすべてが壊れてしまいます。最も安全なアプローチ: 公式のセットアップアクションにGODMODCACHEを任せ、GOPATHを手動でオーバーライドしないことです。
# GitHub Actionsの例
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
# setup-goアクションがGODMODCACHEを正しく設定するため、GOPATHを手動でオーバーライドしない
- name: Download modules
run: go mod download
セルフホストランナーを使用している場合、前のジョブがroot所有のキャッシュを残している可能性があります。クリアしてやり直しましょう:
sudo rm -rf ~/go/pkg/mod
go mod download
修正の確認
上記のいずれかの修正を適用した後、以下を実行してください:
# キャッシュディレクトリが存在しアクセス可能か確認する
ls -la $(go env GOMODCACHE)
# モジュールを新たにダウンロードする
go mod download
# またはプロジェクトをビルドする
go build ./...
パーミッションエラーがなく、クリーンなビルド出力が得られれば完了です。
予防のヒント
sudo go ...は絶対に使わない —goコマンドに昇格アクセスが必要な場合、セットアップに何か問題があります。sudoで回避するのではなく、根本的なパーミッションの問題を修正してください。- Dockerの場合: Dockerfileの設計初期にrootか非rootかを決め、
goコマンドを実行するすべてのレイヤーで一貫して守りましょう。 - GOPATHはシェルプロファイルで明示的に設定する — デフォルトに頼らず、特に複数ユーザーが同じGoインストールを共有するサーバーでは明示的に設定しましょう。
- ディレクトリのパーミッションを目視で確認する:
chmodやchownコマンドが正しい結果を出しているか不安な場合は、ToolCraftのUnix Permissions Calculatorを使えばブラウザ上でパーミッション文字列を作成・確認できます。マルチユーザーのDockerセットアップで適用前に数値を確認したい場合に役立ちます。

