1.前期准备
目录结构
main.go
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
fmt.Println("\n .::::.\n .::::::::.\n :::::::::::\n ..:::::::::::'\n '::::::::::::'\n .::::::::::\n '::::::::::::::..\n ..::::::::::::.\n ``::::::::::::::::\n ::::``:::::::::' .:::.\n ::::' ':::::' .::::::::.\n .::::' :::: .:::::::'::::.\n .:::' ::::: .:::::::::' ':::::.\n .::' :::::.:::::::::' ':::::.\n .::' ::::::::::::::' ``::::.\n ...::: ::::::::::::' ``::.\n ```` ':. ':::::::::' ::::..\n '.:::::' ':'````..\n")
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "hello World!")
})
r.GET("/test", func(c *gin.Context) {
c.String(http.StatusOK, "测试成功!")
})
list := []string{"篮球", "唱歌", "跳舞", "背带裤"}
r.GET("/list", func(c *gin.Context) {
c.JSON(http.StatusOK, list)
})
//Run("里面不指定端口号默认为8080")
r.Run(":8000")
}
Dockerfile
#FROM:定制的镜像都是基于FROM的镜像,这里的golang:1.23.0就是定制需要的基础镜像
FROM golang:1.23.0
#设置后续指令的工作目录为 /webapp
WORKDIR /webapp
#将当前项目的所有文件拷贝到镜像的 /webapp目录中
COPY . .
#RUN在构建过程中在镜像中执行的命令
#设置Go模块代理为https://goproxy.cn,并下载项目的依赖
RUN go env -w GOPROXY=https://goproxy.cn,direct && go mod tidy
#编译Go项目,生成可执行文件 web-app
RUN go build -o web-app
#设置容器启动时运行的命令
CMD ["/webapp/web-app"]
2.制作镜像
把代码上传到服务器如图所示:
进入项目根目录 cd DockerBuildWeb
构建自己的镜像
docker build -t goweb:v1.0 .
docker images 查看镜像
启动容器
docker run -d -p 8181:8000 --name gowebapp goweb:v1.0
查看容器情况
3.多阶段构建
不知道你有没有发现,上面制作的镜像1.22G,为啥那么大妮!!!
原因:在构建Go程序是,需要Go打包的依赖,但是生产中不需要打包依赖。
解决方案:多阶段构建可以将打包依赖和运行时依赖分开,减小image文件大小。
#这里使用Go 1.23.0版本的Alpine Linux镜像 AS bulider 指定镜像的阶段名称
FROM golang:1.23.0-alpine AS bulider
WORKDIR /webapp
COPY . .
RUN go env -w GOPROXY=https://goproxy.cn,direct && go mod download
RUN go build -o web-app
#使用一个更小基础镜像Alpine来运行程序
#Alpine是一个极简的Linux发行版,适合部署阶段
FROM alpine:latest
#设置工作目录/build
WORKDIR /build
#从编译阶段的镜像中拷贝编译后的二进制文件到运行镜像中
#--from=bulider 是第一阶段编译的镜像
COPY --from=bulider /webapp/web-app /build/web-app
CMD ["/build/web-app"]
由上图可以看出多阶段打包制作的镜像确实小了不少。