英文:
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.
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论