Connection refused while accessing REST Api from Go client when both client and api are on same docker container

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

Connection refused while accessing REST Api from Go client when both client and api are on same docker container

问题

我对Docker和Go都非常陌生。我在Go中创建了一个客户端应用程序,用于测试一个REST API。该API作为Docker镜像的一部分提供。我应该在客户端应用程序中添加测试,并将我的客户端应用程序作为docker-compose.yml的一部分提供。

在本地,我可以运行go test -v ./... -cover,并且所有的测试都能够访问API http://localhost:8095/v1/organisation/accounts

当我运行docker compose up时,我得到了下面截图中的错误。

不知何故,客户端应用程序无法从容器内部访问API URL,但可以从我的主机笔记本电脑访问它。

关于如何完成此任务,任何建议都将非常有帮助。我的任务说明是,针对API端点在客户端应用程序中编写的测试应作为docker-compose.yml文件的一部分运行。

我为我的客户端应用程序添加了一个新的Dockerfile,如下所示,并将其包含在docker-compose.yml中。

Dockerfile:

FROM golang:alpine

ENV GO111MODULE=on \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

WORKDIR /build

# Copy and download dependency using go mod
COPY go.mod .
RUN go mod download

COPY . .

WORKDIR /build/accountsapi

RUN go test ./... -cover

docker-compose.yml

version: '3'

services:
  # App Service
  app:
    # Configuration for building the docker image for the service
    build:
      context: . 
      dockerfile: Dockerfile
    restart: unless-stopped
    depends_on: 
      - accountapi
  accountapi:
    image: cooltech/accountapi:v1.0.0-50-g48935
    restart: on-failure
    depends_on:
      - postgresql
      - vault
    environment:
  - PSQL_USER=root
  - PSQL_PASSWORD=password
  - PSQL_HOST=postgresql
  - PSQL_PORT=5432
  - STACK_NAME=accountapi
  - DATABASE-HOST=postgresql
  - DATABASE-SSL-MODE=disable
  - DATABASE-USERNAME=api_user
  - DATABASE-PASSWORD=XXX
ports:
  - 8095:8080
...more services

这是一个示例测试和实际方法

func TestGetAccountByIdExpectsNoAccount(t *testing.T) { 
    // act
	resp := GetAccountById(getUUID())

	defer resp.Body.Close()

	//assert
	if status := resp.StatusCode; status != http.StatusNotFound {
		t.Errorf("handler returned wrong status code: got %v want %v",
			status, http.StatusOK)
	}
}

const Baseurl = "http://localhost:8095/v1/organisation/accounts"
func GetAccountById(id string) *http.Response {

	var url = fmt.Sprintf("%s/%s", Baseurl, id)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
	}

	return resp
}
英文:

I am super new to docker and Go. I've created a client app in Go which test an REST API. The API is provided as part of docker image. I am supposed to add tests in client app and make my client app available as part of same docker-compose.yml.

On local I am able to run go test -v ./... -cover and all tests are able to access api http://localhost:8095/v1/organisation/accounts

When I run docker compose up I get error in below screenshot.

Somehow the client app is not able to access api url within container but its able to access it from my host laptop

Any advice will be very helpful on how to get this done. My instructions for this task are that test written in client app against the api endpoint should run as part of docker-compose.yml file.

Connection refused while accessing REST Api from Go client when both client and api are on same docker container

I added new Dockerfile for me client app as below and then included it in docker-compose.yml.

Dockerfile:

FROM golang:alpine

ENV GO111MODULE=on \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

WORKDIR /build

# Copy and download dependency using go mod
COPY go.mod .
RUN go mod download

COPY . .

WORKDIR /build/accountsapi

RUN go test ./... -cover

docker-compose.yml

version: '3'

services:
  # App Service
  app:
    # Configuration for building the docker image for the service
    build:
      context: . 
      dockerfile: Dockerfile
    restart: unless-stopped
    depends_on: 
      - accountapi
  accountapi:
    image: cooltech/accountapi:v1.0.0-50-g48935
    restart: on-failure
    depends_on:
      - postgresql
      - vault
    environment:
  - PSQL_USER=root
  - PSQL_PASSWORD=password
  - PSQL_HOST=postgresql
  - PSQL_PORT=5432
  - STACK_NAME=accountapi
  - DATABASE-HOST=postgresql
  - DATABASE-SSL-MODE=disable
  - DATABASE-USERNAME=api_user
  - DATABASE-PASSWORD=XXX
ports:
  - 8095:8080
...more services

Here is sample test and actual method

func TestGetAccountByIdExpectsNoAccount(t *testing.T) { 
    // act
	resp := GetAccountById(getUUID())

	defer resp.Body.Close()

	//assert
	if status := resp.StatusCode; status != http.StatusNotFound {
		t.Errorf("handler returned wrong status code: got %v want %v",
			status, http.StatusOK)
	}
}

const Baseurl = "http://localhost:8095/v1/organisation/accounts"
func GetAccountById(id string) *http.Response {

	var url = fmt.Sprintf("%s/%s", Baseurl, id)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
	}

	return resp
}

答案1

得分: 1

最后,我在评论中被**@Rengas**指出之后找到了问题,问题是我在尝试运行测试之前我的API服务还没有启动,而这是docker-compose的一部分。所以我从Dockerfile中移除了go test -v ./...,并将其作为docker-compose的一部分添加进去,现在看起来像下面这样:

accountapitesting:
    build:
      context: .
      dockerfile: Dockerfile
    restart: on-failure
    command: go test -v ./...
    depends_on:
      - accountapi
英文:

Finally, I found the issue after @Rengas pointed out in comments that I am trying to run the test before my API service is up which is part of docker-compose. So I removed the
go test -v ./... from my Dockerfile and added it as part of docker-compose which looks like below now

accountapitesting:
    build:
      context: . 
      dockerfile: Dockerfile
    restart: on-failure
    command: go test -v ./...
    depends_on: 
      - accountapi

huangapple
  • 本文由 发表于 2022年3月14日 02:39:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/71459738.html
匿名

发表评论

匿名网友

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

确定