Go Docker
最后修改时间 2024 年 4 月 11 日
在本文中,我们将介绍如何为 Golang 应用程序使用 Docker。
应用程序容器化是一种操作系统级别的虚拟化方法,用于部署和运行分布式应用程序,而无需为每个应用程序创建完整的虚拟机。通过容器,可以在单个主机上运行多个隔离的应用程序或服务,并访问相同的操作系统内核。容器可以在裸机系统、云实例或虚拟机上运行。
Docker
Docker 是一个供开发人员和系统管理员使用容器构建、运行和共享应用程序的平台。Docker 促进了应用程序的可移植性和可伸缩性。Docker 提供应用程序隔离,从而消除了许多由库和环境差异引起的问题。它有助于自动化开发和部署。借助预定义的社区镜像,开发人员可以节省时间并提高整体体验。
一个 Docker 镜像 是一个只读模板,其中包含创建 Docker 容器的说明。一个 Docker 容器 是镜像的一个可运行实例。
Docker 镜像存储在仓库中。 Docker Hub 是官方 Docker 仓库。 Docker Engine 是底层的客户端-服务器技术,它使用 Docker 的组件和服务来构建和运行容器。
一个 Dockerfile 是一个特殊的文件,其中包含构建 Docker 镜像所需的指令。
$ docker --version Docker version 20.10.17, build 100c701
这是我们使用的 Docker 版本。
Go Docker hello 示例
在下面的示例中,我们将创建并运行一个非常简单的 Docker 镜像。当我们运行镜像时,将执行一个简单的 Go 应用程序。
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("Hello there!")
osv := runtime.GOOS
fmt.Printf("The OS is: %s\n", osv)
}
这是一个简单的控制台应用程序,它会打印一条消息和底层操作系统的版本。
# syntax=docker/dockerfile:1 FROM golang:1.18 WORKDIR /app COPY go.mod . RUN go mod download COPY *.go . RUN go build -o /hello CMD [ "/hello" ]
Dockerfile 是一系列构建镜像的命令。
# syntax=docker/dockerfile:1
第一行是一个可选的语法解析器指令。该指令指示 Docker 构建器在解析 Dockerfile 时要使用的语法。
FROM golang:1.18
我们将镜像基于社区 `golang:1.18`。
WORKDIR /app
我们需要设置一个构建目录。 `WORKDIR` 命令指示 Docker 将指定目录用作所有后续命令的默认目标。
COPY go.mod .
我们使用 `COPY` 将 `go.mod` 文件复制到我们的项目目录 (/app)。
RUN go mod download
使用 `RUN` 指令,我们运行 `go mod download` 命令来下载我们的 Go 模块。
COPY *.go .
使用 `COPY` 命令,我们将 Go 源代码复制到构建目录。
RUN go build -o /hello
我们构建 Go 程序。我们将可执行文件放在文件系统的根目录。
CMD [ "/hello" ]
使用 `CMD` 命令,我们告诉 Docker 在使用我们的镜像启动容器时要执行什么命令。
$ docker build -t hello .
我们构建镜像并将其命名为 `hello`。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 1525ae981450 52 seconds ago 966MB docker/getting-started latest cb90f98fd791 8 weeks ago 28.8MB
我们使用 `docker image ls` 命令列出可用镜像。
$ docker run hello Hello there! The OS is: linux
我们运行 hello 镜像。
多阶段构建
多阶段构建允许我们使用多个镜像来构建最终产品。在多阶段构建中,我们在单个 Dockerfile 中拥有多个镜像。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 1525ae981450 52 seconds ago 966MB docker/getting-started latest cb90f98fd791 8 weeks ago 28.8MB
当我们查看 hello 镜像的大小,我们会发现它相当大。这是因为镜像包含了构建应用程序所需的所有 Go 工具和库。然而,一旦应用程序构建完成,这些可能就不再需要了。为了解决这个问题,我们使用多阶段构建。
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("multi-stage build")
osv := runtime.GOOS
fmt.Printf("The OS is: %s\n", osv)
}
我们有相同的控制台应用程序。
# syntax=docker/dockerfile:1 # Build FROM golang:1.18 AS build WORKDIR /app COPY go.mod . RUN go mod download COPY *.go . RUN go build -o /hello # Deploy FROM scratch WORKDIR / COPY --from=build /hello /hello CMD [ "/hello" ]
现在,我们有两个 `FROM` 命令,形成了两个阶段。
FROM golang:1.18 AS build
使用 `AS` 指令,我们创建了一个名为 `build` 的阶段。
FROM scratch
我们为下一个阶段使用了一个最小的 `scratch` 镜像。
COPY --from=build /hello /hello
我们从构建阶段复制构建程序。
CMD [ "/hello" ]
最后,我们设置要运行的程序。
$ docker build -t hello:multistage .
我们构建镜像并为其打上 `multistage` 标签。
$ docker run hello:multistage multi-stage build The OS is: linux
我们运行新镜像。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello multistage 28c2d0b534eb 6 minutes ago 1.77MB hello latest 1525ae981450 23 minutes ago 966MB docker/getting-started latest cb90f98fd791 8 weeks ago 28.8MB
大小有巨大差异。
Go Docker echo 示例
在下一个示例中,我们将使用 echo 框架创建一个简单的 Web 应用程序。
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello there!")
})
e.Logger.Fatal(e.Start(":8080"))
}
该应用程序有一个文本端点。它监听在 8080 端口。
# syntax=docker/dockerfile:1 # Build FROM golang:1.18 AS build WORKDIR /app COPY go.mod . COPY go.sum . RUN go mod download COPY *.go . RUN go build -o /hello # Deploy FROM debian:latest WORKDIR / COPY --from=build /hello /usr/local/bin/hello EXPOSE 8080 ENTRYPOINT [ "/usr/local/bin/hello" ]
`EXPOSE` 指令通知 Docker 容器在运行时监听指定的网络端口。
FROM debian:latest
我们将镜像基于 Debian 镜像。
$ docker build -t web .
Web 构建镜像。
$ docker run -p 8080:8080 web
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.7.2
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:8080
我们运行镜像。容器的 8080 端口映射到我们计算机的 8080 端口。
$ curl localhost:8080 Hello there!
我们使用 curl 发送一个 GET 请求。
来源
在本文中,我们学习了 Go 和 Docker。