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
v3
和 v2
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
v4
和 v3
版本缩小的不是太明显,但是优化力度够了,按照上边验证的方式重新验证就可以,到此打包镜像搞定!