使用 Dockerfile 来制作你的 Go 项目镜像

使用 Dockerfile 来制作你的 Go 项目镜像

1
2
3
4
5
1、项目搭建
2、编写自己的Dockerfile
3、构建Docker镜像
4、在容器里运行自己的项目
5、小结

1、项目搭建

如果你打算跟着本文进行实操,你需要准备好相应的开发环境,首先是Go 环境、其次是 Docker 的环境配置;
本文不会详细介绍如何安装Golang和配置Docker相关教程;

1.1、创建项目

以一个简单的 web 应用为例:打开终端

1
2
cd ~/gocode 
mkdir go-blog && cd go-blog
1.2、使用 go mod 管理第三方包

使用Go Modules初始化项目,这个操作将创建一个go.mod文件用于管理包依赖,Golang1.11版本开始支持;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 如果没开启 Go Modules 模式,使用以下命令开启
go env -w GO111MODULE=on

go mod init go-blog
go: creating new go.mod: module go-blog

这样我们就初始化好了 go-blog 项目了,项目目录结构如下所示:
│  ── go-blog
│   └── go.mod

go.mod 文件内容如下所示:

module go-blog
go 1.22.9
1.3、编写实例项目文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import (
"encoding/json"
"fmt"
"log"
"net/http"
)

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
type response struct {
Message string `json:"message"`
Author string `json:"author"`
Email string `json:"email"`
}

resp := &response{
Message: "say hello!",
Author: "hqd8080",
Email: "hanquanding@163.com",
}

bs, err := json.Marshal(resp)
if err != nil {
log.Printf("failed to marshal response: %v", err)
}

result := fmt.Sprintf(`{"errcode":0, "errmsg":"", "data":%s}`, string(bs))
fmt.Fprint(w, result)
})

fmt.Println("Starting server at http://localhost:8888")

if err := http.ListenAndServe(":8888", nil); err != nil {
panic(err)
}
}

然后, 执行 go run main.go 命令来运行代码、 并且在浏览器中访问 127.0.0.1:8888

1
2
3
4
5
6
7
8
9
{
"errcode": 0,
"errmsg": "",
"data": {
"message": "say hello!",
"author": "hqd8080",
"email": "hanquanding@163.com"
}
}

2、编写自己的Dockerfile

Dockerfile 是一个用于定义 Docker 容器镜像构建过程的命令配置文件;它包含了一组指令,告诉 Docker 如何创建镜像;
接下来我们需要在 go-blog 项目根目录下创建并编写 Dockerfile 文件,以帮助我们实现自动化构建和高效部署;

这里我们使用多阶段构建、这样创建出来的镜像文件更小、方便传输和节省磁盘空间;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 使用的基础镜像  golang:1.23.0-alpine
FROM golang:1.23.0-alpine AS builder

# 设置镜像的元数据信息
LABEL author="hqd8080"
LABEL email="hanquanding@163.com"

# 设置容器的工作目录、所有后续操作都会在这个目录下进行
WORKDIR /app

# 将当前项目目录的所有文件拷贝到容器的 /app 目录中
COPY . .

# 设置 Go 模块代理为,并下载项目的依赖
#RUN go env -w GOPROXY=https://goproxy.cn,direct && go mod download

# 编译 Go 项目,生成可执行文件
RUN GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o myblog

# 使用的基础镜像(alpine)来运行应用程序
FROM alpine:latest

# 时区的配置
#RUN apk add --no-cache tzdata

# 设置容器的工作目录 /app
WORKDIR /app

# 从编译阶段的镜像中拷贝编译后的二进制文件到运行镜像中
COPY --from=builder /app/myblog .

# 对外开放端口 8080
EXPOSE 8080

# 容器启动时运行的命令
ENTRYPOINT ["/app/myblog"]

3、构建Docker镜像

Dockerfile所在的目录运行以下命令来构建Docker容器

1
2
3
4
5
6
7
8
9
10
11
# 先拉取使用到的基础镜像到本地
# docker pull golang:1.23.0-alpine
# docker pull alpine:latest

# 开启构建
docker build -t myblog-image:v1 .

说明:
1、docker build:这是 Docker 用于构建镜像的命令
2、-t myblog-image:v1:t 是 --tag 的缩写,用来给构建的 Docker 镜像命名,v1是镜像的版本号,默认是 latest
3、.:指定了构建上下文的路径,. 表示当前目录,Docker 引擎会从当前目录读取 Dockerfile 以及所有相关的项目文件并打包进镜像中

4、在容器里运行自己的项目

使用以下命令运行刚刚构建的镜像

1
2
3
4
5
6
7
docker run -d -p 8080:8888 -d myblog-image:v1

说明:
1、docker run: 根据指定的镜像运行一个容器实例
2、p:端口映射,前者为本地端口,后者为 docker 容器端口;本地的 8080 端口映射到容器里的 8080 端口,
3、myblog-image:指定使用的镜像
4、-d:设置 docker 容器在后台运行

5、小结

本文通过自己写的一个小例子,然后通过编写 Dockerfile 文件来构建自己的项目镜像;

具体包括:项目的搭建、Dockerfile 文件的编写、构建项目镜像、以及在镜像中运行自己的项目;

完整的演示了Dockerfile的使用流程和Dockerfile文件中的常用命令;在微服务架构的项目中也是一样的、每个独立的微服务可以自己用Dockerfile来制作自己项目项目镜像,然后具体是在K8s中部署还是在docker-compose中部署都是一样的流程;

值得一提的是,对于单体应用或个人项目,Docker已足够应对开发和部署需求;然而,随着项目规模扩大,尤其是微服务架构中;
单靠Docker难以满足复杂的服务编排需求; 这个时候,引入 Kubernetes(K8s)这种编排工具能更有效地管理多服务、扩展和自动化运维,特别适用于高可用性和动态扩展的分布式系统;