Dockerfile内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| FROM golang:1.25.0 AS build
WORKDIR /go/src/
RUN go env -w GOPROXY=https://goproxy.cn,direct COPY go.mod go.sum . RUN go mod tidy
ARG SERVICE_PATH=internal/iam-api-server/v1
WORKDIR /go/src/${SERVICE_PATH}
COPY ${SERVICE_PATH}/model . COPY ${SERVICE_PATH}/rpc . COPY ${SERVICE_PATH}/repository . COPY ${SERVICE_PATH}/service . COPY ${SERVICE_PATH}/config . COPY ${SERVICE_PATH}/cache . COPY ${SERVICE_PATH}/main.go . COPY ${SERVICE_PATH}/iamapiserver .
RUN CGO_ENABLED=0 GOOS=linux go build -o /tmp/iam-api-server .
FROM scratch AS runtime ENV GIN_MODE=release COPY --from=build /tmp/iam-api-server ./iamapiserver EXPOSE 8080/tcp ENTRYPOINT ["./iamapiserver"]
|
当我在试图构建apiserver的镜像时,遇到了如下报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| supdriver@m700:~/sup-iam$ sudo make docker-build 🐳 构建 Docker 镜像 iam-api-server... make[1]: Entering directory '/home/supdriver/sup-iam/cmd/iam-api-server' cd /home/supdriver/sup-iam/cmd/iam-api-server/../.. && \ docker build \ -t ghcr.io/sis-shen/supdriver/iam-api-server:1.0.0 \ -f internal/iam-api-server/v1/Dockerfile \ . [+] Building 2.3s (19/20) docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 738B 0.0s => [internal] load metadata for docker.io/library/golang:1.25.0 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [build 1/15] FROM docker.io/library/golang:1.25.0 0.1s => [internal] load build context 0.1s => => transferring context: 187.14kB 0.0s => [build 2/15] WORKDIR /go/src/ 0.0s => [build 3/15] RUN go env -w GOPROXY=https://goproxy.cn,direct 0.3s => [build 4/15] COPY go.mod go.sum . 0.1s => [build 5/15] RUN go mod tidy 0.4s => [build 6/15] WORKDIR /go/src/internal/iam-api-server/v1 0.1s => [build 7/15] COPY internal/iam-api-server/v1/model . 0.0s => [build 8/15] COPY internal/iam-api-server/v1/rpc . 0.0s => [build 9/15] COPY internal/iam-api-server/v1/repository . 0.1s => [build 10/15] COPY internal/iam-api-server/v1/service . 0.1s => [build 11/15] COPY internal/iam-api-server/v1/config . 0.0s => [build 12/15] COPY internal/iam-api-server/v1/cache . 0.0s => [build 13/15] COPY internal/iam-api-server/v1/main.go . 0.1s => [build 14/15] COPY internal/iam-api-server/v1/iamapiserver . 0.1s => ERROR [build 15/15] RUN CGO_ENABLED=0 GOOS=linux go build -o /tmp/iam-api-server . 0.6s ------ > [build 15/15] RUN CGO_ENABLED=0 GOOS=linux go build -o /tmp/iam-api-server .: 0.574 api_audit.go:13:2: no required module provides package github.com/gin-gonic/gin; to add it: 0.574 go get github.com/gin-gonic/gin 0.574 api_auth.go:14:2: no required module provides package github.com/gin-gonic/gin/binding; to add it: 0.574 go get github.com/gin-gonic/gin/binding 0.574 interface.go:5:2: no required module provides package github.com/redis/go-redis/v9; to add it: 0.574 go get github.com/redis/go-redis/v9 0.574 auth.go:7:2: no required module provides package github.com/sis-shen/sup-iam/internal/iam-api-server/v1/cache; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/iam-api-server/v1/cache 0.574 main.go:34:2: no required module provides package github.com/sis-shen/sup-iam/internal/iam-api-server/v1/config; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/iam-api-server/v1/config 0.574 main.go:35:2: no required module provides package github.com/sis-shen/sup-iam/internal/iam-api-server/v1/iamapiserver; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/iam-api-server/v1/iamapiserver 0.574 api_auth.go:15:2: no required module provides package github.com/sis-shen/sup-iam/internal/iam-api-server/v1/model; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/iam-api-server/v1/model 0.574 adpter.go:5:2: no required module provides package github.com/sis-shen/sup-iam/internal/iam-api-server/v1/repository; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/iam-api-server/v1/repository 0.574 main.go:36:2: no required module provides package github.com/sis-shen/sup-iam/internal/iam-api-server/v1/repository/mysql; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/iam-api-server/v1/repository/mysql 0.574 main.go:17:2: no required module provides package github.com/sis-shen/sup-iam/internal/iam-api-server/v1/rpc; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/iam-api-server/v1/rpc 0.574 adpter.go:6:2: no required module provides package github.com/sis-shen/sup-iam/internal/iam-api-server/v1/service; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/iam-api-server/v1/service 0.574 api_auth.go:17:2: no required module provides package github.com/sis-shen/sup-iam/internal/pkg/jwt; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/pkg/jwt 0.574 secret.go:7:2: no required module provides package github.com/sis-shen/sup-iam/internal/pkg/keys; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/pkg/keys 0.574 api_auth.go:18:2: no required module provides package github.com/sis-shen/sup-iam/internal/pkg/log; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/pkg/log 0.574 main.go:20:2: no required module provides package github.com/sis-shen/sup-iam/internal/pkg/middleware; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/pkg/middleware 0.574 adpter.go:7:2: no required module provides package github.com/sis-shen/sup-iam/internal/pkg/proto/rpc/v1; to add it: 0.574 go get github.com/sis-shen/sup-iam/internal/pkg/proto/rpc/v1 0.574 loader.go:9:2: no required module provides package github.com/spf13/viper; to add it: 0.574 go get github.com/spf13/viper 0.574 password_haher.go:4:2: no required module provides package golang.org/x/crypto/bcrypt; to add it: 0.574 go get golang.org/x/crypto/bcrypt 0.574 main.go:22:2: no required module provides package golang.org/x/sync/errgroup; to add it: 0.574 go get golang.org/x/sync/errgroup 0.574 main.go:23:2: no required module provides package google.golang.org/grpc; to add it: 0.574 go get google.golang.org/grpc 0.574 main.go:24:2: no required module provides package gorm.io/driver/mysql; to add it: 0.574 go get gorm.io/driver/mysql 0.574 main.go:25:2: no required module provides package gorm.io/gorm; to add it: 0.574 go get gorm.io/gorm 0.574 main.go:26:2: no required module provides package gorm.io/gorm/logger; to add it: 0.574 go get gorm.io/gorm/logger 0.574 found packages rpc (adpter.go) and iamapiserver (api_audit.go) in /go/src/internal/iam-api-server/v1 ------ Dockerfile:25 -------------------- 23 | 24 | 25 | >>> RUN CGO_ENABLED=0 GOOS=linux go build -o /tmp/iam-api-server . 26 | 27 | FROM scratch AS runtime -------------------- ERROR: failed to build: failed to solve: process "/bin/sh -c CGO_ENABLED=0 GOOS=linux go build -o /tmp/iam-api-server ." did not complete successfully: exit code: 1 make[1]: *** [Makefile:25: docker-build] Error 1 make[1]: Leaving directory '/home/supdriver/sup-iam/cmd/iam-api-server' make: *** [Makefile:40: docker-build-iam-api-server] Error 2 supdriver@m700:~/sup-iam$
|
很明显是Dockerfile里的go mod tidy位置出错导致的,原因是对指令原理理解不深,需要有完整的源码才能正确执行go mod tidy
但是我们也可以选择改用go mod download,这个只依据go.mod,不需要完整源码,可以做到提前执行,提高docker缓存利用率
发现文件拷贝存在问题
我们利用调试的思想,通过逐步运行和观察的方式来探究每一步究竟都发生了什么
确认docker build的工作目录
通过在Makefile的指令里加入pwd来确认路径
1 2 3 4 5 6 7 8 9
| .PHONY: docker-build docker-build: ## 构建 Docker 镜像 cd $(CURDIR)/../.. && \ pwd && \ docker build \ -t $(DOCKER_IMAGE):$(DOCKER_TAG) \ -f $(SERVICE_PATH)/Dockerfile \ .
|
运行时输出如下
1 2 3 4 5 6 7 8 9 10 11
| supdriver@m700:~/sup-iam$ sudo make docker-build 🐳 构建 Docker 镜像 iam-api-server... make[1]: Entering directory '/home/supdriver/sup-iam/cmd/iam-api-server' cd /home/supdriver/sup-iam/cmd/iam-api-server/../.. && \ pwd && \ docker build \ -t ghcr.io/sis-shen/supdriver/iam-api-server:1.0.0 \ -f internal/iam-api-server/v1/Dockerfile \ /home/supdriver/sup-iam/cmd/iam-api-server/../.. /home/supdriver/sup-iam [+] Building 15.0s (10/15)
|
可以看到倒数第二行是我们的根目录,是没有问题的。那么我们去调试一下Dockerfile
查看文件是否正确复制
为了排除部分拷贝造成的问题,我们修改Dockerfile直接把整个仓库都拷贝进去
然后我们在想要观察目录的地方执行命令ls && sleep 10,这样我们就可以强制它在这一层构建花费10s,然后直接观察ls的输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| FROM golang:1.25.0 AS build
ARG SERVICE_PATH=internal/iam-api-server/v1 ARG PKG_PATH=internal/pkg
WORKDIR /go/github.com/sis-shen/sup-iam COPY pkg . RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN pwd && sleep 5 RUN ls && sleep 10 RUN ls .. && sleep 10 RUN go mod download
WORKDIR /go/github.com/sis-shen/sup-iam/${SERVICE_PATH}
RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -o /tmp/iam-api-server .
FROM scratch AS runtime ENV GIN_MODE=release COPY --from=build /tmp/iam-api-server ./iamapiserver EXPOSE 8080/tcp ENTRYPOINT ["./iamapiserver"]
|
可以看到输出如下

对比发现里面居然是.git里的内容,居然被错误的展开了。
然后我搜索了一圈可能出现的问题,到最后我终于灵光一闪,忽然想起来Dockerfile的COPY和linux shell里的copy -r不一样,它会自动展开源目录里的内容
真的是基础不牢,地动山摇!!,这简直是对我太久不用docker的惩罚