Go REST API在使用docker-compose时无法访问。

huangapple go评论112阅读模式
英文:

Go REST API not reachable using docker-compose

问题

我正在尝试使用Gin Gonic和MySQL以及PHPMyAdmin创建一个简单的Go Rest API,并使用Docker运行。

尽管PHPMyAdmin正常运行,但当我尝试访问我的Go API时,出现以下错误消息:localhost没有发送任何数据。ERR_EMPTY_RESPONSE

如果我在没有使用Docker的情况下运行main.go文件,一切都按预期工作。

这是我的docker-compose文件:

version: '3'
services:
  app:
    container_name: full_app
    build: .
    ports:
      - 8080:8080
    expose:
      - 8080
    restart: on-failure
    environment:
      - PMA_HOST=fullstack-mysql
      - DB_NAME=${DB_NAME}
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PORT}
    volumes:
      - .:/usr/src/app/
    depends_on:
      - fullstack-mysql
    networks:
      - fullstack

  fullstack-mysql:
    image: mysql:5.7
    container_name: full_db_mysql
    ports:
      - 3306:3306
    environment:
      - MYSQL_ROOT_HOST=${DB_HOST}
      - MYSQL_USER=${DB_USER}
      - MYSQL_ROOT_USER=${DB_ROOT_USER}
      - MYSQL_PASSWORD=${DB_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
    volumes:
      - database_mysql:/var/lib/mysql
    networks:
      - fullstack

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin_container
    depends_on:
      - fullstack-mysql
    environment:
      - PMA_HOST=fullstack-mysql
      - PMA_USER=${DB_USER}
      - PMA_PORT=${DB_PORT}
      - PMA_PASSWORD=${DB_PASSWORD}
    ports:
      - 9090:80
    restart: always
    networks:
      - fullstack

volumes:
  api:
  database_mysql:

# Networks to be created to facilitate communication between containers
networks:
  fullstack:
    driver: bridge

这是我的Dockerfile

# Start from golang base image
FROM golang:alpine as builder

# ENV GO111MODULE=on

# Install git.
# Git is required for fetching the dependencies.
RUN apk update && apk add --no-cache git

# Set the current working directory inside the container
WORKDIR /app

# Copy go mod and sum files
COPY go.mod go.sum ./

# Download all dependencies. Dependencies will be cached if the go.mod and the go.sum files are not changed
RUN go mod download

# Copy the source from the current directory to the working Directory inside the container
COPY . .

# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Start a new stage from scratch
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy the Pre-built binary file from the previous stage. Observe we also copied the .env file
COPY --from=builder /app/main .
COPY --from=builder /app/.env .

# Expose port 8080 to the outside world
EXPOSE 8080

#Command to run the executable
CMD ["./main"]

这是我的Go main.go文件(目前):

package main

import (
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)

func main() {
	router := gin.Default()

	router.GET("/", func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"data": "Hello World !"})
	})

	router.Run("localhost:8080")
}

如果我访问http://localhost:9090,PhpMyAdmin正在加载(正如我所期望的)。
如果我访问http://localhost:8080,我会收到这个错误消息:localhost没有发送任何数据。ERR_EMPTY_RESPONSE

我使用docker-compose up --build运行这个。
显然我做错了什么,但我不确定是什么。

英文:

I am trying to run a simple go Rest API created with Gin Gonic and MySQL and PHPMyAdmin with docker.

While the PHPMyAdmin is running fine, when I try to access my go API I get the following error message: localhost didn’t send any data. ERR_EMPTY_RESPONSE

If I run my main.go file without docker, everything is working as expected

here is my docker-compose file

version: '3'
services:
  app:
    container_name: full_app
    build: .
    ports:
      - 8080:8080
    expose:
      - 8080
    restart: on-failure
    environment:
      - PMA_HOST=fullstack-mysql
      - DB_NAME=${DB_NAME}
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PORT}
    volumes:
      - .:/usr/src/app/
    depends_on:
      - fullstack-mysql
    networks:
      - fullstack

  fullstack-mysql:
    image: mysql:5.7
    container_name: full_db_mysql
    ports:
      - 3306:3306
    environment:
      - MYSQL_ROOT_HOST=${DB_HOST}
      - MYSQL_USER=${DB_USER}
      - MYSQL_ROOT_USER=${DB_ROOT_USER}
      - MYSQL_PASSWORD=${DB_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
    volumes:
      - database_mysql:/var/lib/mysql
    networks:
      - fullstack

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin_container
    depends_on:
      - fullstack-mysql
    environment:
      - PMA_HOST=fullstack-mysql
      - PMA_USER=${DB_USER}
      - PMA_PORT=${DB_PORT}
      - PMA_PASSWORD=${DB_PASSWORD}
    ports:
      - 9090:80
    restart: always
    networks:
      - fullstack

volumes:
  api:
  database_mysql:

# Networks to be created to facilitate communication between containers
networks:
  fullstack:
    driver: bridge

Here is my Dockerfile:

# Start from golang base image
FROM golang:alpine as builder

# ENV GO111MODULE=on

# Install git.
# Git is required for fetching the dependencies.
RUN apk update && apk add --no-cache git

# Set the current working directory inside the container
WORKDIR /app

# Copy go mod and sum files
COPY go.mod go.sum ./

# Download all dependencies. Dependencies will be cached if the go.mod and the go.sum files are not changed
RUN go mod download

# Copy the source from the current directory to the working Directory inside the container
COPY . .

# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Start a new stage from scratch
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy the Pre-built binary file from the previous stage. Observe we also copied the .env file
COPY --from=builder /app/main .
COPY --from=builder /app/.env .

# Expose port 8080 to the outside world
EXPOSE 8080

#Command to run the executable
CMD ["./main"]

And here is my go main.go file (for now):

package main

import (
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)

func main() {
	router := gin.Default()

	router.GET("/", func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"data": "Hello World !"})
	})

	router.Run("localhost:8080")
}

If I access http://localhost:9090 PhpMyAdmin is loading (exactly what I am expecting)
If I access http://localhost:8080 I get this error message: localhost didn’t send any data. ERR_EMPTY_RESPONSE

I run docker-compose up --build for this.
I am obviously doing something wrong, but I am not sure what.

答案1

得分: 1

似乎问题出在你的Go代码和我指定API监听主机的方式上。在我的main.go文件中,我当前将主机设置为"localhost:8080",但是当在Docker容器中运行应用程序时,我应该监听"0.0.0.0:8080"。这样可以使容器绑定到所有网络接口。

为了解决这个问题,我需要修改main.go文件中的router.Run行,如下所示:

router.Run("0.0.0.0:8080")

在进行了这个更改之后,我重新构建了Docker镜像,并使用docker-compose up --build命令再次运行了容器。这样应该可以使我的Go REST API在Docker容器外部通过http://localhost:8080访问。

注意:容器内部的localhost指的是容器本身,而不是主机机器。通过使用"0.0.0.0",我指示容器绑定到所有可用的网络接口,从而允许我从主机机器访问API。

英文:

It seems that the issue lies in your Go code and the way I am specifying the host for my API to listen on. In my main.go file, I am currently setting the host as "localhost:8080", but when running my application inside a Docker container, I should listen on "0.0.0.0:8080" instead. This allows the container to bind to all network interfaces.

To fix the issue, I had to modify the router.Run line in my main.go file as follows:

router.Run("0.0.0.0:8080")

After making this change, I rebuilt my Docker image and run my containers again using docker-compose up --build. This should allow my Go REST API to be accessible on http://localhost:8080 outside of the Docker container.

Note: The localhost inside the container refers to the container itself, not the host machine. By using "0.0.0.0", I am instructing the container to bind to all available network interfaces, allowing me to access the API from my host machine.

huangapple
  • 本文由 发表于 2023年6月20日 20:30:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76514713.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定