为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Docker 中部署包含静态文件的 Web 应用?

如何在 Docker 中部署包含静态文件的 Web 应用?

Go
海绵宝宝撒 2022-08-15 10:09:35
我构建了一个带有回声的Web应用程序。一些来源是server.gopackage mainimport ...type TemplateRenderer struct {    templates *template.Template}func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {    if viewContext, isMap := data.(map[string]interface{}); isMap {        viewContext["reverse"] = c.Echo().Reverse    }    return t.templates.ExecuteTemplate(w, name, data)}func main() {    e := echo.New()    e.Static("/static", "static")    renderer := &TemplateRenderer{        templates: template.Must(template.ParseGlob("public/views/*.html")),    }    e.Renderer = renderer    e.GET("/", func(c echo.Context) error {        return c.Render(http.StatusOK, "index.html", map[string]interface{}{})    })    e.Logger.Fatal(e.Start(":8080"))}项目树├── helper│   └── string.go└─── site    ├── Dockerfile    ├── go.mod    ├── go.sum    ├── server.go    ├── public    │   └── views    │       └── index.html    └── static我可以运行启动服务器,一切正常。但是如果用docker运行它,就会出错。go run server.goDockerfileFROM golang:1.15.2-alpine3.12 AS builderWORKDIR /appCOPY . .WORKDIR /app/siteRUN CGO_ENABLED=0 GOOS=linux go build -o serverFROM alpine:3.12COPY --from=builder /app/site /bin/.ENTRYPOINT [ "server" ]通过以下方式构建了一个 docker 映像docker build -t gcr.io/${PROJECT_ID}/myapp -f site/Dockerfile .在泊坞窗中运行应用docker run --rm -p 8080:8080 gcr.io/${PROJECT_ID}/myapppanic: html/template: pattern matches no files: `public/views/*.html`goroutine 1 [running]:html/template.Must(...)    /usr/local/go/src/html/template/template.go:372main.main()    /app/site/server.go:76 +0x2af该文件夹似乎未复制到映像中。但是在构建映像时没有任何错误。怎么了?public
查看完整描述

2 回答

?
心有法竹

TA贡献1866条经验 获得超5个赞

首先,您使用的是多阶段 Docker 构建,它非常适合仅将编译的二进制文件复制到最终映像。但是,在 Dockerfile 中,您将复制整个构建目录 - 二进制文件以及所有源代码。server


其次,您的主要问题是当图像作为容器运行时,默认工作目录是 - 因此服务器中的任何路径都找不到中的html文件。//bin/public


如果你需要调试一个 docker 镜像 - 特别是如果它是一个基于 linux 发行版(如 alpine)的镜像 - 只需:


docker run -it myimage /bin/sh

无论如何,对您的docker的2个简单修复:


FROM golang:1.15.2-alpine3.12 AS builder

WORKDIR /app

COPY . .

WORKDIR /app/site

RUN CGO_ENABLED=0 GOOS=linux go build -o server


FROM alpine:3.12

COPY --from=builder /app/site/server /bin

COPY --from=builder /app/site/public /public

ENTRYPOINT [ "/bin/server" ]


查看完整回答
反对 回复 2022-08-15
?
慕沐林林

TA贡献2016条经验 获得超9个赞

在Go 1.16中,您可以将这些文件编译成二进制文件本身。因此,您需要升级主机系统上的 Go 工具链,以及 Dockerfile 中构建阶段的行。Go 1.16 添加了嵌入包和一个新指令来支持这一点。FROM//go:embed


首先,您需要告诉编译器嵌入模板文件,构建一个文件系统对象:


import "embed"


// templateFiles contains the raw text of the template files.

//go:embed public/views/*.html

var templateFiles embed.FS

然后,当你去使用它时,Go 1.16还会添加一个相应的(“html/template”)。解析FS函数:


renderer := &TemplateRenderer{

    templates: template.Must(template.ParseFS(templateFiles)),

}

现在所有文件都嵌入在二进制文件本身中,您不应该收到“找不到文件”类型错误。您可以考虑仅将已编译的二进制文件复制到最终映像中,而不将任何其他内容复制到最终映像中。


# Upgrade to Go 1.16

FROM golang:1.16-alpine3.12 AS builder

# Unchanged from original

WORKDIR /app

COPY . .

WORKDIR /app/site

RUN CGO_ENABLED=0 GOOS=linux go build -o server


FROM alpine:3.12

# Only copy the compiled binary and not the source tree

COPY --from=builder /app/site/server /bin

# Generally prefer CMD to ENTRYPOINT

CMD [ "server" ]


查看完整回答
反对 回复 2022-08-15
  • 2 回答
  • 0 关注
  • 131 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信