我根据一个YouTube教程创建了一个简单的API,在本地正常运行。但是一旦我将应用程序容器化并运行容器,就无法访问http://localhost:8080上的API。我猜想这与我在dockerfile中使用的端口设置有关,但我不确定。
main.go文件:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"errors"
)
type phone struct{
ID string `json:"id"`
Model string `json:"model"`
Year string `json:"year"`
Quantity int `json:"quantity"`
}
var phones = []phone{
{ID: "1", Model: "iPhone 11", Year: "2019", Quantity: 4},
{ID: "2", Model: "iPhone 6", Year: "2014", Quantity: 9},
{ID: "3", Model: "iPhone X", Year: "2017", Quantity: 2},
}
func phoneById(c *gin.Context) {
id := c.Param("id")
phone, err := getPhoneById(id)
if err != nil {
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "Phone not found."})
return
}
c.IndentedJSON(http.StatusOK, phone)
}
func checkoutPhone(c *gin.Context) {
id, ok := c.GetQuery("id")
if !ok {
c.IndentedJSON(http.StatusBadRequest, gin.H{"Message": "Missing id query paramater"})
return
}
phone, err := getPhoneById(id)
if err != nil {
c.IndentedJSON(http.StatusBadRequest, gin.H{"Message": "Phone not found"})
return
}
if phone.Quantity <= 0 {
c.IndentedJSON(http.StatusBadRequest, gin.H{"Message": "Phone not available."})
return
}
phone.Quantity -= 1
c.IndentedJSON(http.StatusOK, phone)
}
func returnPhone(c *gin.Context) {
id, ok := c.GetQuery("id")
if !ok {
c.IndentedJSON(http.StatusBadRequest, gin.H{"Message": "Missing id query paramater"})
return
}
phone, err := getPhoneById(id)
if err != nil {
c.IndentedJSON(http.StatusBadRequest, gin.H{"Message": "Phone not found"})
return
}
if phone.Quantity <= 0 {
c.IndentedJSON(http.StatusBadRequest, gin.H{"Message": "Phone not available."})
return
}
phone.Quantity += 1
c.IndentedJSON(http.StatusOK, phone)
}
func getPhoneById(id string) (*phone, error) {
for i, p := range phones {
if p.ID == id {
return &phones[i], nil
}
}
return nil, errors.New("Phone not found.")
}
func getPhones(c *gin.Context) {
c.IndentedJSON(http.StatusOK, phones)
}
func createPhone(c *gin.Context) {
var newPhone phone
if err := c.BindJSON(&newPhone); err != nil {
return
}
phones = append(phones, newPhone)
c.IndentedJSON(http.StatusCreated, newPhone)
}
func main(){
router := gin.Default()
router.GET("/phones", getPhones)
router.GET("/phones/:id", phoneById)
router.POST("/phones", createPhone)
router.PATCH("/checkout", checkoutPhone)
router.PATCH("/return", returnPhone)
router.Run("localhost:8080")
}
我的Dockerfile:
#The standard golang image contains all of the resources to build
#But is very large. So build on it, then copy the output to the
#final runtime container
FROM golang:latest AS buildContainer
WORKDIR /go/src/app
COPY . .
#flags: -s -w to remove symbol table and debug info
#CGO_ENALBED=0 is required for the code to run properly when copied alpine
RUN CGO_ENABLED=0 GOOS=linux go build -v -mod mod -ldflags "-s -w" -o restapi .
#Now build the runtime container, just a stripped down linux and copy the
#binary to it.
FROM alpine:latest
WORKDIR /app
COPY --from=buildContainer /go/src/app/restapi .
ENV GIN_MODE release
ENV HOST 0.0.0.0
ENV PORT 8080
EXPOSE 8080
CMD ["./restapi"]
我尝试了在Google上找到的不同的Dockerfile,也试着从头开始创建我的自己的Dockerfile。
gcr.io/distroless/static:nonroot
。但是这时你需要运行go build以禁用cgo。 - The Fool