使用docker部署go项目有一个通用的范式
那就是分阶段构建
分阶段构建
简单讲一下分阶段构建
我们都知道,go的部署只需要编译后的可执行文件就可以了,并不需要go的环境
那么我们可以先在有go环境的容器中对项目进行构建,得到构建后的可执行文件
然后再把这个可执行文件放到一个比较小的镜像容器里面
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/", func(context *gin.Context) {
context.String(200, "看到消息就说明部署成功了")
})
r.Run(":5000")
}
好在docker支持分阶段构建
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 main
FROM scratch
WORKDIR /app
COPY --from=builder /build/main /app
CMD ["./main"]
docker build -t go1 .
docker run -itd --name go1 -p 5000:5000 go1
当然,我这里写的是最简单的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")
}
运行容器
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地址
使用一般不会使用默认网络的
而是使用自建网络,创建容器的时候指定容器的ip地址
创建网络
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
然后再把这个知识和上面的项目部署结合起来,什么问题都可以搞定