知微坚果的拾光小镇 知微坚果的拾光小镇
首页
随笔
  • Golang

    • 基础
    • 第三方库
  • 前端

    • Vue
    • Flutter
  • 开发工具
  • 系统工具
  • Timer (opens new window)
  • 时间线
  • 关于
GitHub (opens new window)

知微坚果

行者常至,为者常成
首页
随笔
  • Golang

    • 基础
    • 第三方库
  • 前端

    • Vue
    • Flutter
  • 开发工具
  • 系统工具
  • Timer (opens new window)
  • 时间线
  • 关于
GitHub (opens new window)
  • 基础篇

    • Golang工程结构最佳实践
    • Golang容器化部署最佳实践
      • 前言
      • 一、最佳实践
      • 二、讲解
      • 2.1 添加时区
      • 2.2 服务名
      • 2.3 运行权限
        • 2.3.1 Linux /etc/passwd
      • 2.4 Docker分阶段构建
      • 三、Docker基础镜像(base image):scratch 、busybox、alpine
        • scratch:空镜像,基础镜像
        • busybox
        • Alpine
      • 参考资料
  • 《Golang微服务最佳实践专栏》
  • 基础篇
知微坚果
2022-11-30
目录

Golang容器化部署最佳实践优质

# 前言

相较于Java而言,Golang本身可以直接打包为各个平台的二进制文件,并不需要安装环境,所以直接采用虚拟机的方式部署也是非常方便的。

但是如今云原生时代,部署并不仅仅是跑起来这么简单,还包括动态扩缩容、状态监控、资源管控等能力,容器化基本上是最佳选择。

本文主要总结了Golang打包Docker的最佳实践,拥有非常小的体积,并且可以用于生产环境。

# 一、最佳实践

话不多说,先上可用域生产环境使用的Dockerfile文件:

FROM golang:1.19-alpine3.16 AS builder

#更新Alpine的软件源为国内源,提高下载速度
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.16/main/" > /etc/apk/repositories
RUN apk add --no-cache tzdata
 
WORKDIR /build
RUN adduser -u 10001 -D app-runner
 
ENV GOPROXY https://goproxy.cn
COPY go.mod .
COPY go.sum .
RUN go mod download
 
COPY . .
RUN CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -a -o httpserver .
 
FROM alpine:3.16 AS final
 
WORKDIR /app
COPY --from=builder /build/httpserver /app/
#COPY --from=builder /build/config /app/config
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# 设置时区
ENV TZ Asia/Shanghai
COPY --from=builder /usr/share/zoneinfo/${TZ} /usr/share/zoneinfo/${TZ}

USER app-runner
ENTRYPOINT ["/app/httpserver"]
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

提示

我们实际上使用的是分阶段打包镜像

其实我们也可以先打包为Linux二进制文件,Dockerfile只把二进制文件COPY到镜像,但是这种方式打包环境和容器基础镜像提供的环境有所不同,而且还要首先安装golang环境,所以并不推荐采用这种方式。

# 二、讲解

  1. Golang运行只需要Linux内核
  2. Docker分阶段构建
  3. 使用最小镜像alpha

# 2.1 添加时区

aplha镜像默认时区是UTC,如果我们需要改为中国的时区,需要安装tzdata

为了加速流水线下载速度,我添加镜像加速地址:

RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.16/main/" > /etc/apk/repositories
1

然后执行alpha镜像的安装命令:

RUN apk add --no-cache tzdata
1

由于我们是在第一阶段的构建镜像中安装的时区,我们在第二阶段构建最终竟像时,需要把安装好的时区拷贝过去:

ENV TZ Asia/Shanghai
COPY --from=builder /usr/share/zoneinfo/${TZ} /usr/share/zoneinfo/${TZ}
1
2

我们通过ENV TZ的方式声明我们使用上海的时区,也就是北京时间了

# 2.2 服务名

我们上面打包golang的二进制名字为httpserver,并且启动命令也是httpserver,我们实际上可以通过哦ARG命令把该名字传入进来

使用具体的具备业务含义的名字,这样的好处是查询对应的进程信息时,方便区分不同的服务容器

# 2.3 运行权限

USER app-runner
ENTRYPOINT ["/app/httpserver"]
1
2

在启动应用之前,先使用命令USER指定用户,这样后面运行的指令将只用指定用户的权限,可以增强安全性,避免应用漏洞导致服务器诶侵入。

# 2.3.1 Linux /etc/passwd

在Linux系统中,/etc/passwd是一个文件,存储基本用户信息,其中一行就代表一条用户信息。

我们通过cat /etc/passwd,可以查看到如下信息: 20221202193957

其中每一行被:分割为7个部分,对应的含义为:

用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell

# 2.4 Docker分阶段构建

Docker 17.05版本以后,官方就提供了一个新的特性:Multi-stage builds(多阶段构建)。

利用多阶段构建,我们可以在一个 Dockerfile 中使用多个 FROM 语句。每个 FROM 指令都可以使用不同的基础镜像,并表示开始一个新的构建阶段。

我们可以很方便的将一个阶段的文件复制到另外一个阶段,在最终的镜像只需要保留必要的内容。

通过这种方式,我们可以很容易实现Docker镜像的瘦身,最终镜像只保留运行时需要的内容,而构建期间用到的内容都可以不保存。

# 三、Docker基础镜像(base image):scratch 、busybox、alpine

# scratch:空镜像,基础镜像

scratch是Docker中预留的最小的基础镜像。bosybox 、 Go语言编译打包的镜像都可以基于scratch来构建。

scratch镜像不在镜像仓库中,但是可以在Dockerfile引用。

如:

FROM scratch
1

# busybox

busybox镜像只有几兆。

BusyBox是一个集成了一百多个最常用Linux命令和工具(如cat、echo、grep、mount、telnet等)的精简工具箱,它只有几MB的大小,很方便进行各种快速验证,被誉为“Linux系统的瑞士军刀”。BusyBox可运行于多款POSIX环境的操作系统中,如Linux(包括Android)、Hurd、FreeBSD等。

# Alpine

Alpine镜像比busybox大一点,也只有几兆。

Alpine操作系统是一个面向安全的轻型Linux发行版。它不同于通常的Linux发行版,Alpine采用了musl libc和BusyBox以减小系统的体积和运行时资源消耗,但功能上比BusyBox又完善得多。在保持瘦身的同时,Alpine还提供了自己的包管理工具apk,可以通过https://pkgs.alpinelinux.org/packages查询包信息,也可以通过apk命令直接查询和安装各种软件。

Alpine Docker镜像也继承了Alpine Linux发行版的这些优势。相比于其他Docker镜像,它的容量非常小,仅仅只有5MB左右(Ubuntu系列镜像接近200MB),且拥有非常友好的包管理机制。官方镜像来自docker-alpine项目。

目前Docker官方已开始推荐使用Alpine替代之前的Ubuntu作为基础镜像环境。这样会带来多个好处,包括镜像下载速度加快,镜像安全性提高,主机之间的切换更方便,占用更少磁盘空间等。

# 参考资料

  1. Golang Dockerfile的最佳实践 (opens new window)
  2. Golang - 如何使用Docker部署Go Web应用 (opens new window)
  3. 如何使用docker 部署 golang 编译环境最小版 (opens new window)
  4. docker基础镜像(base image):scratch 、 busybox 、 alpine (opens new window)
  5. Linux /etc/passwd (opens new window)
  6. Linux中/etc/passwd文件详细解析 (opens new window)
  7. Docker多阶段构建 (opens new window)
#Golang#微服务#后端
更新时间: 12/5/2022, 9:00:10 PM
Golang工程结构最佳实践

← Golang工程结构最佳实践

最近更新
01
SpringBoot3.0快速上手
12-07
02
Spring事务管理源码分析
12-06
03
Golang工程结构最佳实践
12-04
更多文章>
Theme by Vdoing | Copyright © 2022-2022 知微坚果 | 拾光小镇
蜀ICP备17001150号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式