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
# COPY go.mod .
# COPY go.sum .
RUN pwd && sleep 5
RUN ls && sleep 10
RUN ls .. && sleep 10
RUN go mod download

# WORKDIR /go/github.com/sis-shen/sup-iam/${PKG_PATH}

# COPY ${PKG_PATH}/jwt .
# COPY ${PKG_PATH}/keys .
# COPY ${PKG_PATH}/log .
# COPY ${PKG_PATH}/middleware .
# COPY ${PKG_PATH}/proto .


WORKDIR /go/github.com/sis-shen/sup-iam/${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 -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的惩罚