Docker 实战打包 Go 项目镜像

Hello Docker

先来打包把项目跑起来

 package main
 
 import (
     "fmt"
     "net/http"
 )

 func handler(w http.ResponseWriter, r *http.Request) {
     fmt.Fprintln(w, ">>> Hi docker")
 }

 func main() {
     http.HandleFunc("/", handler)
     fmt.Println("Server is running on port 8080...")
     http.ListenAndServe(":8080", nil)
 }

保存在 main.go 文件中,同样在当前目录下创建 Dockerfile 文件内容如下:

FROM golang:latest
WORKDIR /app
COPY . .

RUN go mod tidy
RUN go build -o main .

EXPOSE 8080
CMD ["./main"]

构建镜像

docker build -t go-web-app:v1 .
[+] Building 25.5s (10/10) FINISHED                                                                                                docker:default
 => [internal] load build definition from Dockerfile                                                                                         0.0s
 => => transferring dockerfile: 466B                                                                                                         0.0s
 => [internal] load metadata for docker.io/library/golang:latest                                                                             0.0s
 => [internal] load .dockerignore                                                                                                            0.0s
 => => transferring context: 2B                                                                                                              0.0s
 => [1/5] FROM docker.io/library/golang:latest                                                                                               0.0s
 => [internal] load build context                                                                                                            0.0s
 => => transferring context: 638B                                                                                                            0.0s
 => CACHED [2/5] WORKDIR /app                                                                                                                0.0s
 => [3/5] COPY . .                                                                                                                           0.1s
 => [4/5] RUN go mod tidy                                                                                                                    2.4s
 => [5/5] RUN go build -o main .                                                                                                            22.3s
 => exporting to image                                                                                                                       0.5s
 => => exporting layers                                                                                                                      0.5s
 => => writing image sha256:06fce7d285dd2c49204846afcfabe099957f9f7f4e00a9b3abc9a127c41adc53                                                 0.0s
 => => naming to docker.io/library/go-web-app:v1                                                                                             0.0s

查看下构建出来的镜像

docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
go-web-app    v1        06fce7d285dd   2 minutes ago   918MB

构建出来的镜像大小是 918M,卧槽这么大。。。先跑起来再来处理镜像大小的问题!

启动镜像

docker run -id --name go-web-app-v1 \
-p 8800:8080 \
go-web-app:v1

访问一下:

curl 127.1:8800
>>> Hi docker

搞定!

官方 alpine 镜像

上边存在的一个大问题就是镜像大小,官网有个镜像是 alpine 明显比常规镜像小很多,尝试一下吧

FROM golang:alpine
WORKDIR /app
COPY . .

RUN go mod tidy
RUN go build -o main .

EXPOSE 8080
CMD ["./main"]

构建镜像

docker build -t go-web-app:v2 .
[+] Building 20.0s (10/10) FINISHED                                                                                                docker:default
 => [internal] load build definition from Dockerfile                                                                                         0.0s
 => => transferring dockerfile: 466B                                                                                                         0.0s
 => [internal] load metadata for docker.io/library/golang:alpine                                                                             0.0s
 => [internal] load .dockerignore                                                                                                            0.0s
 => => transferring context: 2B                                                                                                              0.0s
 => [1/5] FROM docker.io/library/golang:alpine                                                                                               0.1s
 => [internal] load build context                                                                                                            0.1s
 => => transferring context: 638B                                                                                                            0.0s
 => [2/5] WORKDIR /app                                                                                                                       0.0s
 => [3/5] COPY . .                                                                                                                           0.1s
 => [4/5] RUN go mod tidy                                                                                                                    0.9s
 => [5/5] RUN go build -o main .                                                                                                            18.2s
 => exporting to image                                                                                                                       0.6s
 => => exporting layers                                                                                                                      0.6s
 => => writing image sha256:46af5d3a3872fde3f90c98657eb70e1c9fc75b8127bbdce4a7c75797dafd5a17                                                 0.0s
 => => naming to docker.io/library/go-web-app:v2

查看镜像大小

docker images
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
go-web-app    v2        46af5d3a3872   7 seconds ago    326MB
go-web-app    v1        06fce7d285dd   26 minutes ago   918MB

果然对比很明显,不过还是大了点,没有达到预期!

多阶段构建

从构建日志来看,一个Go 项目打包份构建阶段和启动阶段,那么启动阶段是不需要构建阶段依赖的环境这也是一个思路,那就尝试一下,修改后的 Dcokerfile 如下

最终的 Dockerfile

# 使用官方Go镜像作为基础镜像
FROM golang:alpine AS builder

# 设置工作目录
WORKDIR /app
COPY . .

RUN go mod tidy
COPY . .
RUN GOOS=linux CGO_ENABLED=0 go build -o main .


FROM alpine AS runner
WORKDIR /app
COPY --from=builder /app/main /app/main
EXPOSE 8080

# 运行生成的可执行文件
CMD ["./main"]

优化后的镜像

查看下生成的镜像

docker images | grep go-web-app
go-web-app    v3        44ff1f7de83f   14 seconds ago   15.2MB
go-web-app    v2        46af5d3a3872   1 hours ago      326MB
go-web-app    v1        06fce7d285dd   1 hours ago      918MB

v3v2 v1 版本对比镜像大小太给力了

验证镜像是否可用

# 后台启动
docker run -id --name go-web-app-v3 \
-p 8803:8080 \
go-web-app:v3

# 查看进程
docker ps
CONTAINER ID   IMAGE               COMMAND     CREATED         STATUS         PORTS                                       NAMES
96913118b290   go-web-app:v3       "./main"    8 seconds ago   Up 7 seconds   0.0.0.0:8803->8080/tcp, :::8803->8080/tcp   go-web-app-v3

# 访问验证
curl 127.1:8803
>>> Hi docker

搞定!

继续优化

把程序编译过程中输出日志的功能也删掉,修改的Dockerfile文件如下

# 使用官方Go镜像作为基础镜像
FROM golang:alpine AS builder

# 设置工作目录
WORKDIR /app
COPY . .

RUN go mod tidy
COPY . .
RUN GOOS=linux CGO_ENABLED=0 go build -ldflags="-w -s" -o main .


FROM alpine AS runner
WORKDIR /app
COPY --from=builder /app/main /app/main
EXPOSE 8080

# 运行生成的可执行文件
CMD ["./main"]

构建镜像

docker build -t go-web-app:v4 .
[+] Building 18.7s (15/15) FINISHED                                                                                                    docker:default
 => [internal] load build definition from Dockerfile                                                                                             0.0s
 => => transferring dockerfile: 444B                                                                                                             0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                 0.0s
 => [internal] load metadata for docker.io/library/golang:alpine                                                                                 0.0s
 => [internal] load .dockerignore                                                                                                                0.0s
 => => transferring context: 2B                                                                                                                  0.0s
 => [builder 1/6] FROM docker.io/library/golang:alpine                                                                                           0.0s
 => [runner 1/3] FROM docker.io/library/alpine:latest                                                                                            0.0s
 => [internal] load build context                                                                                                                0.0s
 => => transferring context: 710B                                                                                                                0.0s
 => CACHED [builder 2/6] WORKDIR /app                                                                                                            0.0s
 => [builder 3/6] COPY . .                                                                                                                       0.0s
 => [builder 4/6] RUN go mod tidy                                                                                                                0.9s
 => [builder 5/6] COPY . .                                                                                                                       0.1s
 => [builder 6/6] RUN GOOS=linux CGO_ENABLED=0 go build -ldflags="-w -s" -o main .                                                              17.2s
 => CACHED [runner 2/3] WORKDIR /app                                                                                                             0.0s
 => [runner 3/3] COPY --from=builder /app/main /app/main                                                                                         0.1s
 => exporting to image                                                                                                                           0.1s
 => => exporting layers                                                                                                                          0.1s
 => => writing image sha256:29c99a6f84dbe57693770dd6c92e1493b37a26519994e14d2253942211d3077d                                                     0.0s
 => => naming to docker.io/library/go-web-app:v4

查看镜像大小

docker images | grep go-web-app
go-web-app    v4        29c99a6f84db   6 seconds ago    12.9MB
go-web-app    v3        44ff1f7de83f   23 minutes ago   15.2MB
go-web-app    v2        46af5d3a3872   1 hours ago      326MB
go-web-app    v1        06fce7d285dd   1 hours ago      918MB

v4v3 版本缩小的不是太明显,但是优化力度够了,按照上边验证的方式重新验证就可以,到此打包镜像搞定!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值