【发布时间】:2021-06-24 16:20:15
【问题描述】:
我已经构建了一个使用 Golang 编写的 API 支持的 React 客户端应用程序。我想使用 Docker 来使用 docker run 来运行这两个应用程序。
我的项目结构如下:
zid
|
|-web/ (my react folder)
main.go
Dockerfile
|
我的目标是运行zid 文件夹中的main.go 文件并启动zid/web 文件夹中的Web 应用程序。 main.go 文件使用 Gin Gonic 启动一个 API,它将在端口 10000 上侦听和服务。
所以我尝试了以下方法:
# Build the Go API
FROM golang:latest as go_builder
RUN mkdir /zid
WORKDIR /zid
COPY . /zid
RUN GOOS=linux GOARCH=amd64 go build -a -ldflags "-linkmode external -extldflags '-static' -s -w" -o /go/bin/zid
# Build the React application
FROM node:alpine as node_builder
COPY --from=go_builder /zid/web ./
RUN npm install
RUN npm run build
# Final stage build, this will be the container with Go and React
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=go_builder /go/bin/zid /go/zid
COPY --from=go_builder /zid/ca /go/ca
COPY --from=node_builder /build ./web
EXPOSE 3000
WORKDIR /go
CMD ./zid
接下来我做了以下事情:
- 使用
docker build -t zid .构建它(没有错误) - 使用
docker run -p 3000:3000 --rm zid运行它
当我运行它时,它将启动 API,但是当我转到 http://localhost:3000/ 时,我得到一个 Page does not work ERR: ERR_EMPTY_RESPONSE。
所以 API 启动了,但 npm 构建没有。我不确定自己做错了什么,因为 Docker 容器都包含正确的文件夹(go 和 web)。
正如您在图片中看到的那样,我相信它就在那里。我错过了什么?
编辑:
我正在使用(*gin.Engine).Run() 函数在端口 10000 上设置监听和服务。在我的本地构建中,我的 React 应用程序正在向localhost:10000 发送请求。我总是在我的 React 应用程序 (localhost:3000) 一侧简单地使用 npm start。我的目标是做同样的事情,但所有这些都在一个 Dockerfile 中。
我仍然有点不确定是否应该在我的 Dockerfile 中 EXPOSE 端口 10000 和 3000。
我的 HandleRequest 函数:
//Start the router and listen/serve.
func HandleRequests() {
router := SetupRouter()
router.Run(":10000")
}
我的 SetupRouter 功能:
//Setup the gin router
func SetupRouter() *gin.Engine {
router := gin.Default()
router.Use(CORSMiddleware())
router.POST("/auth/login", login)
router.POST("/component/deploy", deployComponent)
router.POST("/project/create", createProject)
router.POST("/diagram/create", createDiagram)
router.PATCH("/diagram/update", updateDiagram)
router.DELETE("/diagram/delete/:id", deleteDiagram)
router.GET("/diagram/:id", getDiagram)
router.GET("/project/list", getProjectsByUsername)
router.GET("/project/:id", getProject)
router.GET("/project/diagrams/:id", getDiagramsOfProject)
router.DELETE("/project/delete/:id", deleteProject)
router.GET("/application/list", applicationList)
router.GET("/instance/status/:id", getInstanceStatus)
router.GET("/user", getUser)
return router
}
顺便说一句,我只想将 Docker 容器用于开发和学习目的。
【问题讨论】:
-
通常你只希望在每个 docker 容器中运行 1 个东西。如果这两件事需要相互通信,您可以使用两个容器的公共网络来实现。或者更简单,使用 docker-compose 将两个容器一起运行。
-
运行一个同时提供静态文件(React 应用程序)和 REST API 调用的服务器没有任何问题,imo。
-
@super 由于 React 应用程序被编译成静态文件,它不需要自己的服务器或自己的容器;问题中描述的高级方法是有道理的。
-
在 Go 应用程序中,你能显示设置网络监听器的代码吗? (是否使用端口 3000;是否监听所有接口?)
-
@DavidMaze 编辑了我的问题!