Gopher Sketch. 图片来源于 gophers 仓库
使用 Golang,可以构建从简单的可执行工具到完整的 Web 服务器的任何应用程序。为了交付这样的应用程序,Docker 是我们使用的工具,它允许我们创建自包含的环境,其中包含项目运行所需的所有内容。值得一提的是,Docker 命令行接口本身是用 GO 开发的。
为任何 GO 应用程序编写 Docker 镜像
通常最好从尽可能简洁且具有所需基本依赖项的基本映像开始。通常情况下,alpine 映像是一个很好的选择,因为它们仅包含操作系统所需的最少内容。
因此,我们可以从以下内容开始编写我们的 Dockerfile
:
FROM golang:alpine3.15
在镜像内部,我们可以指定下一步,就像在任何其他环境中一样构建应用程序。
FROM golang:alpine3.15WORKDIR /pathCOPY . .RUN go mod download
RUN go build -o "app" .
然后,我们必须为生成的二进制文件添加执行权限,以便可以运行它:
RUN chmod +x /path/app
然而,使用这样的映像运行 GO 应用程序存在一个小问题。事实证明,在构建和生成二进制文件之后,我们不再需要在容器中安装 GO 以运行它。这是可以省略的依赖项,以优化映像大小。解决此问题的方法是使用 Docker 多阶段构建。
使用多阶段构建
多阶段构建允许将构建映像的过程分成不同的部分,并从中收集不同的工件。常见的模式被称为构建器模式,其中我们从构建器阶段开始 Dockerfile
。它负责使用其构建时依赖项组装应用程序,然后我们只从中取出严格必要的工件。
FROM golang:alpine3.15 as builder
WORKDIR /path
COPY . .
RUN go mod download
RUN go build -o "app" .
FROM alpine:3.15.5
WORKDIR /path
RUN apk update \
&& apk -U upgrade \
&& apk add --no-cache ca-certificates bash gcc \
&& update-ca-certificates --fresh \
&& rm -rf /var/cache/apk/*
COPY --from=builder /path/app .
RUN chmod +x /path/app
ENTRYPOINT ["/path/app"]
在上面的 Dockerfile
中,我们已经指定了构建器映像步骤。它将构建用于运行应用程序的二进制文件。然后,它将被传输到最终映像。请注意,最终映像只是一个普通的 alpine 映像,无需包含任何 GO 依赖项,因为应用程序已经构建完成。
作为非 root 用户运行
为了完成我们的映像,我们应该作为专用用户运行容器。默认情况下,Docker 容器内的进程将以 root 用户身份运行。相反,将容器作为非 root 用户运行被认为是安全最佳实践。在某个进程突破容器时,如果某些进程突破了容器,则它将不具有底层操作系统的任何特权权限。
因此,我们可以将以下行添加到我们的 Dockerfile
中:
RUN addgroup app_user && adduser -S app_user -u 1000 -G app_userUSER app_user
最终结果
在遵循所有这些步骤之后,我们将得到以下 Dockerfile
:
FROM golang:alpine3.15 as builder
WORKDIR /path
COPY . .
RUN go mod download
RUN go build -o "app" .
FROM alpine:3.15.5
WORKDIR /path
RUN apk update \
&& apk -U upgrade \
&& apk add --no-cache ca-certificates bash gcc \
&& update-ca-certificates --fresh \
&& rm -rf /var/cache/apk/*
RUN addgroup app_user && adduser -S app_user -u 1000 -G app_user
COPY --chown=app_user:app_user --from=builder /path/app .
RUN chmod +x /path/app
USER app_user
ENTRYPOINT ["/path/app"]
结果,这是一个通用的镜像,可用于发布使用 GO 编写的应用程序。
结论
在本文中,我们看到了如何创建 GO 应用程序的容器映像。与之相关的一些最佳实践是:
- 使用基础映像,其中仅包含运行程序所需的最少内容。
- 多阶段构建作为优化映像大小的一种方式。
- 出于安全原因,将容器作为非 root 用户运行。
感谢你一直阅读到最后。希望这些技巧对你有用!
此外,请确保查看我有关如何将应用程序 Docker 化的其他文章:
译自:https://medium.com/@leonardo5621_66451/how-to-dockerize-a-go-application-d196ea292c34
评论(0)