使用 Docker 打包 Go 程序(学习笔记) 2024-04-23
文章摘要
docker 部署 go 项目
使用 docker 部署 go 项目有一个通用的范式
那就是分阶段构建
一、分阶段构建
go 的部署只需要编译后的可执行文件就可以了,并不需要 go 的环境
那么我们可以先在有 go 环境的容器中对项目进行构建,得到构建后的可执行文件
然后再把这个可执行文件放到一个比较小的镜像容器里面
1、新建一个 go
项目
go mod init gotest
2、新建 main.go
,写入下面的举例代码
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run()
}
3、安装依赖
go mod tidy
4、新建 Dockerfile
FROM golang:alpine AS builder
#构建可执行文件
#关闭CGO
ENV CGO_ENABLED=0
#设置国内代理
ENV GOPROXY=https://goproxy.cn,direct
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
#设置工作目录
WORKDIR /build
ADD go.mod .
ADD go.sum .
ADD main.go .
#开始打包,放在/build
RUN go build -o mian
#一个新的小镜像(非常小,10m)
FROM scratch
#新建工作目录/app
WORKDIR /app
#将/build/main可执行文件复制到/app
COPY --from=builder /build/mian /app
#运行
CMD ["./mian"]
5、开始打包
sudo docker build -t gotest .
6、使用 docker images
查看所有镜像
7、如果 gotest
镜像存在,开始运行
docker run -itd --name gotest -p 8080:8080 gotest
这里写的是最简单的 go 项目
没有使用配置文件,也没有连数据库等这些外部服务
二、使用配置文件映射
package main
import (
"github.com/gin-gonic/gin"
"gopkg.in/yaml.v3"
"log"
"os"
)
type Conf struct {
System struct {
Name string `yaml:"name"`
} `yaml:"system"`
}
func main() {
r := gin.Default()
byteData, err := os.ReadFile("settings.yaml")
if err != nil {
log.Fatal(err)
}
var conf Conf
err = yaml.Unmarshal(byteData, &conf)
if err != nil {
log.Fatal(err)
}
r.GET("/", func(context *gin.Context) {
context.JSON(200, gin.H{"code": 0, "msg": "看到消息就说明部署成功了", "data": gin.H{"name": conf.System.Name}})
})
r.Run(":5000")
}
修改 Dockerfile
文件
FROM golang:alpine AS builder
#构建可执行文件
ENV CGO_ENABLED=0
ENV GOPROXY=https://goproxy.cn,direct
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
WORKDIR /build
ADD go.mod .
ADD go.sum .
ADD main.go .
RUN go build -o mian
FROM scratch
WORKDIR /app
COPY settings.yml .
COPY --from=builder /build/mian /app
CMD ["./mian"]
运行容器
docker run -itd --name go1 -p 5000:5000 -v G:\\IT\\go_pro\\go_study\\go_study\\31.部署\\settings.yaml:/app/settings.yaml go1
三、连接外部服务
以 mysql 为例,mysql 可能在我们的内网服务器上
也可能单独起一个 mysql 容器
面对第一种情况,因为 Docker 默认会将容器连接到宿主机的 Docker0 网桥上,容器和宿主机是可以直接通信的,所以直接连就行了
面对第二种情况,单独起的 mysql 容器和我们的项目容器是可以互相连接的
一般不会使用默认网络的
而是使用自建网络,创建容器的时候指定容器的 ip 地址
创建网络(子网是 10.1.0.0,子网掩码是 24)
docker network create --subnet=10.1.0.0/24 my-network
创建容器用自建网络
这里我用之前的 centos 容器测试
docker run -itd --name c2 --ip 10.1.0.2 --network my-network fengfengzhidao/centos7-ssh:v1
docker run -itd --name c3 --ip 10.1.0.3 --network my-network fengfengzhidao/centos7-ssh:v1
注意:在 settings.yaml
中设置mysql
的host
,必须写内网ip
,而不是 127.0.0.1
mysql:
host: 192.168.0.111