go项目想运行在docker中,需要先制作镜像。主要有两种方式!
1.在 https://hub.docker.com/ 中 搜索 golang ,Dockerfile 中 依赖 golang 镜像 (大概100M左右)
这种方式 如下,是在容器里,将 golang 程序编译的。所以需要依赖 golang sdk 进行编译
FROM golang:alpine
WORKDIR $GOPATH/src/gin_docker
ADD . ./
ENV GO111MODULE=on
ENV GOPROXY="https://goproxy.io"
RUN go build -o gin_docker .
EXPOSE 8080
ENTRYPOINT ["./gin_docker"]
这种方式,我不太喜欢,打包的镜像文件太大了 。 最少也是100M,也浪费了golang 的交叉编译的功能
2.在本地使用交叉编译,将go程序编译成 Linux 可以执行文件,然后只需要依赖一个非常小的操作系统就可以了。如: alpine 只有 3M 左右的大小。再加上go可执行文件的大小。也就是十几MB
下面我们使用第2种方式,将go程序使用docker运行。
随便编写一个 go 程序,如下
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"strconv"
"strings"
)
//项目配置
type AppConfig struct {
AppName string
Port int
Description string
}
var conf AppConfig
// 初始化配置文件
func init() {
viper.SetConfigName("config")
viper.SetConfigType("toml")
viper.AddConfigPath("/etc/appname/") // 查找配置文件所在路径
viper.AddConfigPath("$HOME/.appname") // 多次调用AddConfigPath,可以添加多个搜索路径
viper.AddConfigPath(".") // 还可以在工作目录中搜索配置文件
viper.AddConfigPath("./conf") // 还可以在工作目录中搜索配置文件
if err := viper.ReadInConfig(); err != nil {
fmt.Printf("read config failed: %v \r", err)
}
if err := viper.Unmarshal(&conf); err != nil {
fmt.Println(err)
}
}
// 使用 gin 创建一个 http 服务
func main() {
r := gin.Default()
r.Any("/", func(c *gin.Context) {
message := strings.Join([]string{"Hello", conf.AppName, conf.Description}, " ")
c.JSON(200, gin.H{
"message": message,
})
})
appPort := strings.Join([]string{":", strconv.Itoa(conf.Port)}, "")
r.Run(appPort)
}
config.toml 配置文件,如下
appName = "go docker demo1"
port = 8089
description = "这是一个非常牛逼的app"
我这边是使用了 goreleaser 插件,
goreleaser --rm-dist --snapshot
当然也可以手动去交叉编译
SET CGO_ENABLED=0
# 设置 操作系统的类型
SET GOOS=linux
# 设置 cpu 架构
SET GOARCH=amd64
go build
切记一定要先把项目编译了,然后才能 构建 docker 镜像
编写 Dockerfile
# 表示依赖 alpine 最新版
FROM alpine:latest
MAINTAINER Wang Chen Chen<932560435@qq.com>
ENV VERSION 1.0
# 在容器根目录 创建一个 apps 目录
WORKDIR /apps
# 挂载容器目录
VOLUME ["/apps/conf"]
# 拷贝当前目录下 go_docker_demo1 可以执行文件
COPY dist/go_docker_demo1_linux_amd64/go_docker_demo1 /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 8089
# 运行golang程序的命令
ENTRYPOINT ["/apps/golang_app"]
需要注意 这条命令 ! 如果你是用手动编译的方式,那么可执行文件就在当前目录下
# goreleaser 插件编译的方式
COPY dist/go_docker_demo1_linux_amd64/go_docker_demo1 /apps/golang_app
# 手动编译的方式
COPY go_docker_demo1 /apps/golang_app
拷贝当前项目下编译好的可执行文件,到容器中的 apps 目录下,并且修改名称为 “golang_app”
前置条件就已经ok了!
构建docker镜像
docker build -t go_docker_demo1:v1.1 .
我们构建的镜像大小只有 17MB 真的很小
启动 构建的镜像
docker run -d --name my-go_docker_demo1 -p 8089:8089 go_docker_demo1:v1.1
浏览器 打开 http://localhost:8089/
带挂载目录的启动,意思:将当前操作系统的目录
D盘 go_docker_demo1/conf 挂在到容器中 /apps/conf 目录。
这样 conf/config.toml 的配置文件,就可以在宿主机中修改了。
容器重启后,就会加载新的配置文件。目的是为了解决,有时候无需要重新构建项目,
只需要修改配置文件 的情况!
Windows docker 容器的挂载方式
docker run -d --name my-go_docker_demo1 -p 8089:8089 -v /d/go_docker_demo1/conf:/apps/conf go_docker_demo1:v1.1
Linux docker 容器的挂载方式,任意选一个都可以
docker run -d --name my-go_docker_demo1 -p 8089:8089 -v /home/go_docker_demo1/conf:/apps/conf go_docker_demo1:v1.1
docker run -d --name my-go_docker_demo1 -p 8089:8089 -v $PWD/conf:/apps/conf go_docker_demo1:v1.1
确保宿主机中有配置文件,否则程序读不到配置文件,就没法启动了
Windows d:\go_docker_demo1\conf\config.toml
Linux /home/go_docker_demo1/conf/config.toml
我只是修改了,d:\go_docker_demo1\conf\config.toml 中的文件,然后重启容器后,就重新加载配置文件; 这种方式更灵活一些!