docker部署go程序实现极小镜像占用
1.交叉编译
通常我们编写代码会在linux的环境中,一般开发环境就是win里面装个linux虚拟机,有的时候在虚机里安装相关IDE,这就使得本来资源有限的虚机进一步压缩,go恰好可以交叉编译,这为编码带来了极大的好处。
根据go的编译逻辑,我们在编译前更改go env后可实现win平台build linux平台运行的程序。
通过cmd或者powershell或者其他终端查看go env,然后调整env: GOOS,具体来说如以下命令:
# 1.windows平台
$ go env | grep GOOS
set GOOS=windows
# win -> linux
$ go env -w GOOS=linux
# 查看GOOS,确认env生效
$ go env| grep GOOS
set GOOS=linux
# 查看arch,确认是否需要更改,通常都是amd64,通常较少是arm架构的
$ go env | grep GOARCH
set GOARCH=amd64
# 2.linux平台,如果需要在linux上编译win上运行的exe可执行文件,参考更改,GOOS: linux -> windows
2.镜像准备
参考文章:golang 打包到docker运行,最小镜像,考虑go编译后的就是一个可执行文件,我们可以将二进制运用和配置打到容器里面,就不用在容器里也要求配置go的运行环境,那种考虑的是在build镜像时,在Dockerfile中go build出来,那样的话,镜像大小在G级别了,换种思路,在apline中打入二进制应用加配置,镜像大小会小很多,是不是在20M级别呢。
确认好运行后编辑Dockerfile:
# cat Dockerfile
# 表示依赖 alpine 最新版
FROM alpine:latest
ENV VERSION 1.0
# 在容器根目录 创建一个 apps 目录
WORKDIR /apps
# 挂载容器目录
# VOLUME ["/apps/conf"]
# 拷贝当前目录下 go_docker_demo1 可以执行文件
COPY main /apps/golang_app
# 拷贝配置文件到容器中
# COPY conf/config.toml /apps/conf/config.toml
# 设置时区为上海
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
# 设置编码
ENV LANG C.UTF-8
# 暴露端口
EXPOSE 8090
# 运行golang程序的命令
ENTRYPOINT ["/apps/golang_app"]
构建镜像:
docker build -t go-apline:v1.0 .
# 查看镜像
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
go-apline v1.0 5a81dd4bb076 16 hours ago 18.9MB
alpine latest b2aa39c304c2 4 weeks ago 7.05MB
# 可以看到构建后的容器也仅在20M内了,确实很省空间了
注:相关源码
pwd
# /root/ngx-go-web/apline
ls
---
.:
conf Dockerfile go.mod go.sum main main.go
./conf:
config.toml
---
# mai为win平台编译后的linux下可运行的二进制应用,go build即可,cp到linux上时,由于win上的权限问题,需要通过chomod调整,chmod 777 main
main.go
package main
import (
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"log"
"strconv"
"strings"
)
func main() {
r := gin.Default()
r.Any("/", any)
appAddrPort := strings.Join([]string{":", strconv.Itoa(conf.Port)}, "")
r.Run(appAddrPort)
}
func any(c *gin.Context) {
message := strings.Join([]string{"Hello", conf.AppName, conf.Description}, " ")
c.JSON(200, gin.H{
"message": message,
})
}
type AppConfig struct {
AppName string `json:"appName"`
Port int `json:"port"`
Description string `json:"description"`
}
var conf AppConfig
func init() {
log.Println("loading config ...")
viper.SetConfigName("config")
viper.SetConfigType("toml")
viper.AddConfigPath("./conf")
if err := viper.ReadInConfig(); err != nil {
log.Println(err)
}
if err := viper.Unmarshal(&conf); err != nil {
log.Println(err)
}
log.Println("loading config completed.")
}
config.toml
appName = "go docker demo1"
port = 8090
description = "这是一个go-gin demo"
go.mod
module go-crossBuild
go 1.19
require (
github.com/gin-gonic/gin v1.9.0
github.com/spf13/viper v1.15.0
)
3.部署
go运行容器的镜像也准备好了,接下来直接运行容器:
docker run -d --name my-go-gin \
-p 8090:8090 \ # 映射端口出来,通过host:hostPort即可访问
-v /root/ngx-go-web/apline/conf/config.toml:/apps/conf/config.toml \ # 挂载配置
-v /etc/localtime:/etc/localtime:ro \ # 调整时间
go-apline:v1.0
docker ps | grep my-go
# 11dc135c63e2 go-apline:v1.0 "/apps/golang_app" 16 hours ago Up 16 hours 0.0.0.0:8090->8090/tcp, :::8090->8090/tcp my-go-gin
接下来看看测试效果。

改下配置,再看看效果:
cat config.toml
---
appName = "go docker demo22222222222222222222222222222"
port = 8090
description = "这是一个go-gin demo"
---
重启docker:docker restart my-go-gin
再看看效果:

说明确实起作用了,更改配置的appname后,也看到更改了。
浙公网安备 33010602011771号