php小编百草将为大家介绍如何解决在Docker容器中提供静态ReactJS文件时出现的404页面未找到的问题。在使用Docker部署应用程序时,有时会遇到这个问题,但不用担心,我们可以通过一些简单的步骤来解决。在本文中,我将分享如何正确配置Docker容器以提供静态ReactJS文件,以及如何避免404页面未找到的错误。让我们一起来看看吧!
问题内容
我正在尝试容器化一个在端口 8000 上提供静态文件的 Go 应用程序。我查看了有关此主题的其他帖子,许多人似乎都说使用 router.Run("0.0.0.0:8000")
或 router .运行(“:8000”)
。我已经尝试过两者但仍然没有成功。我的 main.go 看起来像这样:
package main
// required packages
import (
"fmt"
"log"
"os"
"github.com/gin-gonic/gin"
"github.com/gin-contrib/cors
"net/http"
)
func main() {
// start the server
serveApplication()
}
func serveApplication() {
corsConfig := cors.Config {
AllowOrigins: []string{"*"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Origin", "Content-Type", "Authorization"},
AllowCredentials: true,
}
router := gin.Default()
router.Use(cors.New(corsConfig))
router.StaticFS("/static", http.Dir("./frontend/build/static"))
router.StaticFile("/", "./frontend/build/index.html")
router.Run(":8000")
fmt.Println("Server running on port 8000")
}
以及以下 Dockerfile:
FROM node:16-alpine3.11 as build-node
WORKDIR /workdir
COPY frontend/ .
RUN yarn install
RUN yarn build
COPY .env /workdir/
FROM golang:1.21-rc-alpine3.18 as build-go
#FROM golang:1.17rc2-alpine3.14 as build-go
ENV GOPATH ""
RUN go env -w GOPROXY=direct
RUN apk add git
ADD go.mod go.sum ./
RUN go mod download
ADD . .
COPY --from=build-node /workdir/build ./frontend/build
RUN go build -o /main
FROM alpine:3.13
COPY --from=build-go /main /main
COPY --from=build-node /workdir/.env .env
EXPOSE 8000
ENTRYPOINT [ "/main" ]
我的文件夹结构如下所示;
portal
- frontend (here the react app is stored)
- backend (all my backend logic)
- Dockerfile
- main.go
- go.mod
当我使用 go run main.go
在本地运行它时,前端在端口 8000 上正确运行,并且加载 http://localhost:8000 工作正常。当我使用 docker build -t Portal .
构建 docker 映像,然后使用 docker run -p 8000:8000 --name Portal Portal
运行它时,我可以在终端中看到服务器启动并表示它正在端口 8000 上运行,但我总是收到 404 页面未找到错误。
我尝试使用 router.Run("0.0.0.0:8000")
、router.run("localhost:8000")
或 docker run --network host --name Portal Portal
。
我有什么遗漏的吗?我是否将前端构建复制到错误的位置?
解决方法
最终图像中唯一的内容是您在最后 FROM
行之后 COPY
的内容;即 main
二进制文件和 .env
文件。您正在尝试从 ./frontend/...
提供文件,但这不在最终图像中。只需将相关的 COPY
行移动到最后阶段就可以了。
FROM alpine:3.13
COPY --from=build-go /main /main
COPY --from=build-node /workdir/.env .env
COPY --from=build-node /workdir/build ./frontend/build # <-- move from above
...
相反,由于您没有使用 embed
包来直接将构建的前端代码嵌入到二进制文件中,因此在(Go)构建阶段不需要它。
使用 embed
也可能有效,而不需要重新排列 Dockerfile。这看起来大致类似于
//go:embed frontend/build/*
var content embed.FS
router.StaticFS("/static", http.FS(fs.Sub(content, "frontend/build/static"))
router.StaticFileFS("/", "frontend/build/index.html", http.FS(content))
通过此设置,前端确实需要成为 Go 构建步骤的一部分,但现在它完全包含在二进制文件中,不需要单独复制到最终图像中。