英文:
Unable to get a response from a container on the same network, Docker compose, Mountebank
问题
我有一个Go应用程序和三个Docker容器,用于应用程序、数据库和Mountebank来模拟/存根HTTP响应。
我希望我的Mountebank容器在test_api(应用程序容器)发出请求时返回适当的响应。
当我使用Postman调用端点时,Mountebank容器返回正确的响应。
然而,当我的test_api容器内的代码发送如下的GET请求时,它总是收到以下错误信息:
> dial tcp 127.0.0.1:3000: connect: connection refused
以下是test_api发送请求给Mountebank容器的代码:
func getSuper(id string) (*float64, error) {
var url = "http://localhost:3000/ato/employee/?/balance"
url = strings.Replace(url, "?", id, 1)
log.Println("Sending request to this url: ", url)
resp, err := http.Get(url)
if err != nil {
return nil, &errorhandling.RequestError{Context: "getSuper calling ato api", Code: errorhandling.Internal, Message: err.Error()}
}
body, err := resposeToByte(resp)
if err != nil {
log.Println("err in coverting response to byte[]:", err)
return nil, &errorhandling.RequestError{Context: "getsuper resposeToByte", Code: errorhandling.Internal, Message: err.Error()}
}
superData, err := UnmarshalSuperDetails(body)
if err != nil {
return nil, &errorhandling.RequestError{Context: "UnmarshalSuperDetails())", Code: errorhandling.Internal, Message: err.Error()}
}
log.Println("super details ", superData)
return &superData.SuperBalance, nil
}
以下是我的docker-compose文件:
version: '3.7'
services:
db:
container_name: "test_db"
platform: linux/x86_64
build:
context: .
dockerfile: db.Dockerfile
networks:
- default
restart: always
ports:
- "3306:3306"
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "secret"
MYSQL_DATABASE: "IGD"
MYSQL_USER: "tester"
MYSQL_PASSWORD: "secret"
volumes:
- mysql_data:/var/lib/mysql
command: --default-authentication-plugin=mysql_native_password
api:
container_name: "test_api"
build:
context: .
dockerfile: api.Dockerfile
ports:
- "8080:8080"
depends_on:
- db
volumes:
- .:/app/
mountebank:
container_name: mountebank
image: jkris/mountebank:latest
build:
context: .
dockerfile: mb.Dockerfile
volumes:
- ./imposters:/imposters
ports:
- 2525:2525
- 3000:3000
command: --configfile /imposters/imposter.json --allowInjection
networks:
- default
networks:
default:
volumes:
mysql_data:
我的imposter配置如下:
{
"port": 3000,
"protocol": "http",
"stubs": [
{
"predicates": [
{
"equals": {"path":"/ato/employee/a/balance"}
}
],
"responses": [
{
"is": {
"statusCode": 404,
"headers": {
"Content-Type": "application/json"
},
"body": {"error": "value not available"}
}
}
]
},
{
"predicates": [
{
"equals": {"path":"/ato/employee/58957fc7-4e24-44e5-9eb1-a7fa0297613b/balance"}
}
],
"responses": [
{
"is": {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": { "employeeId":"50ccf5d6-2056-4e0c-a160-4e51638410c7",
"superBalance":1050.0}
}
},
continues...
以下是我的Mountebank的Dockerfile:
FROM alpine:3.14
ENV MOUNTEBANK_VERSION=2.4.0
RUN apk add --update nodejs-lts && \
apk add --update npm
RUN npm install -g mountebank@${MOUNTEBANK_VERSION} --production
EXPOSE 2525
ENTRYPOINT ["mb"]
CMD ["start"]
我应该如何更改我的代码,以便使test_api从Mountebank接收到正确的响应?
英文:
I have a Go application and three docker containers for the app, database and mountebank to mock/stub HTTP response.
I would like my mountebank container to return an appropriate response when the test_api (app container) makes a request.
The mountebank container returns a proper response when I call the endpoint using Postman.
However, when my code inside the test_api container send GET request like the code below It always receives
> dial tcp 127.0.0.1:3000: connect: connection refused
Here is how test_api send a request to mountebank container
func getSuper(id string) (*float64, error) {
var url = "http://localhost:3000/ato/employee/?/balance"
url = strings.Replace(url, "?", id, 1)
log.Println("Sending request to this url: ", url)
resp, err := http.Get(url)
if err != nil {
return nil, &errorhandling.RequestError{Context: "getSuper calling ato api", Code: errorhandling.Internal, Message: err.Error()}
}
body, err := resposeToByte(resp)
if err != nil {
log.Println("err in coverting response to byte[]:", err)
return nil, &errorhandling.RequestError{Context: "getsuper resposeToByte", Code: errorhandling.Internal, Message: err.Error()}
}
superData, err := UnmarshalSuperDetails(body)
if err != nil {
return nil, &errorhandling.RequestError{Context: "UnmarshalSuperDetails())", Code: errorhandling.Internal, Message: err.Error()}
}
log.Println("super details ", superData)
return &superData.SuperBalance, nil
}
here is my docker-compose
version: '3.7'
services:
db:
container_name: "test_db"
platform: linux/x86_64
build:
context: .
dockerfile: db.Dockerfile
networks:
- default
restart: always
ports:
# <Port exposed> : < MySQL Port running inside container>
- "3306:3306"
# setting some env vars to create the DB
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "secret"
MYSQL_DATABASE: "IGD"
MYSQL_USER: "tester"
MYSQL_PASSWORD: "secret"
# OR if you want to use "root" as the user, just these two lines
# MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
# MYSQL_DATABASE: ${DATABASE_NAME}
# we mount a data volume to make sure we don't lose data
volumes:
- mysql_data:/var/lib/mysql
command: --default-authentication-plugin=mysql_native_password
api:
container_name: "test_api"
# we want to use the image which is build from our Dockerfile
build:
context: .
dockerfile: api.Dockerfile
ports:
- "8080:8080"
# we are depending on the mysql backend
depends_on:
- db
# We mount the working dir into the container, handy for development
# This is what makes the hot reloading work inside of a Docker container
volumes:
- .:/app/
mountebank:
container_name: mountebank
image: jkris/mountebank:latest
build:
context: .
dockerfile: mb.Dockerfile
volumes:
- ./imposters:/imposters
ports:
- 2525:2525
- 3000:3000
#- 8090:8090
command: --configfile /imposters/imposter.json --allowInjection
networks:
- default
networks:
default:
volumes:
mysql_data:
my imposter:
{ "port": 3000,
"protocol": "http",
"stubs": [
{
"predicates": [
{
"equals": {"path":"/ato/employee/a/balance"}
}
],
"responses": [
{
"is": {
"statusCode": 404,
"headers": {
"Content-Type": "application/json"
},
"body": {"error": "value not available"}
}
}
]
},
{
"predicates": [
{
"equals": {"path":"/ato/employee/58957fc7-4e24-44e5-9eb1-a7fa0297613b/balance"}
}
],
"responses": [
{
"is": {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": { "employeeId":"50ccf5d6-2056-4e0c-a160-4e51638410c7",
"superBalance":1050.0}
}
},
continues...
Here is my docker file for mountebank
FROM alpine:3.14
ENV MOUNTEBANK_VERSION=2.4.0
RUN apk add --update nodejs-lts && \
apk add --update npm
RUN npm install -g mountebank@${MOUNTEBANK_VERSION} --production
EXPOSE 2525
ENTRYPOINT ["mb"]
CMD ["start"]
How can I make a change in my code in order to make test_api receive a proper response from the mountebank?
答案1
得分: 1
你应该将test_api中的以下行更改为:
var url = "http://mountebank:3000/ato/employee/?/balance"
因为这些是不同的容器,你应该在Docker环境中指定它们的名称或IP。你的test_api请求到了它的本地主机,但是没有打开3000端口,所以会出现连接被拒绝的错误。你可以参考Docker网络获取更多信息。
英文:
You should change following line in your test_api;
var url = "http://localhost:3000/ato/employee/?/balance"
With the following one;
var url = "http://mountebank:3000/ato/employee/?/balance"
Since these are different container and you should specify their name or IPs in Docker environment. Your test_api requests to its localhost and there is no open port for 3000 and you would get connection refused error. You can take a look Docker Networking for further information.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论