I'm trying to deploy SpringBoot microservices using docker-compose but I'm having a problem with API Gateway.
If I run the project locally it works ok, even if I deploy project using docker-compose but API Gateway locally, it works ok, so problem has to be "dockerizing" the API Gateway service.
Doing docker logs <container> it shows:
io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused: localhost/127.0.0.1:8083
Is obvious there is a problem on host localhost/127.0.0.1. Why Gateway is trying to point a "repeated" address?.
docker-compose.yml looks like this:
version: '3.8'
services:
# more services
api-gateway:
build: ./path_to_dockerfile
depends_on:
- eureka-server
environment:
- eureka.client.serviceUrl.defaultZone=http://eureka-server:8761/eureka/
restart: always
container_name: gateway
ports:
- '9000:9000'
Dockerfile is as simple as this
FROM openjdk:8-jdk-alpine
ADD target/apigateway-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
And application.yml:
server:
port: 9000
spring:
application:
name: Api-Gateway-Service
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_UNIQUE
globalcors:
# cors config
routes:
- id: <name>-microservice
uri: http://localhost:8083
predicates:
- Path=/<path>/**
- Method=GET,POST,DELETE,PUT,OPTIONS
# more routes on different ports
eureka:
# eureka config
So, why is adding "localhost" or "127.0.0.1" and calling twice?
Thanks in advance.
I don't think Connection refused: localhost/127.0.0.1:8083 means that it was trying to add or call localhost twice. It is just the way it shows the error.
In your application.yml, try changing uri to the name you used for your microservice inside docker-compose file.
routes:
- id: <name>-microservice
uri: <YOUR_SERVICE_NAME>
I guess the problem is that docker doesn't support network communication between containers by default. You can connect to the 8083 port from your host but not another container. If so, you should create a network and contact the container and network.
Related
In my production environment I have an Eureka Server running inside a docker container.
I can register to it other basic microservices with this kind of Application.yml
Application.yml:
server:
port: '8095'
spring:
application:
name: sap-listener
eureka:
instance:
preferIpAddress: true
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://172.17.0.2:8761/eureka
I create a DockerImage with this Dockerfile:
Dockerfile
FROM openjdk:17-jdk
ARG JAR_FILE=target/*.jar
COPY target/sap-listener-*.jar /sap-listener.jar
ENTRYPOINT ["java", "-jar", "/sap-listener.jar" ]
EXPOSE 8095
and then I run it in production with this command:
docker run -d -p 8095:8095 --name sap myrepo/sap-listener1.0:latest
The service is successfully registered to the Eureka server.
I came across to some problems when I try to run a bigger microservice which have a docker-compose file.
I send directly this docker-compose file in production:
Docker-compose
version: "3.3"
services:
docker-mysql:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 'password'
MYSQL_DATABASE: 'db'
ports:
- "3007:3306"
phpmyadmin:
image: phpmyadmin
restart: always
container_name: php-my-admin-users
ports:
- "8081:80"
ldap-app:
image: myRepo/service1:latest
ports:
- "8090:8090"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://docker-mysql:3306/db
depends_on:
- docker-mysql
And I run it with docker-compose -f docker-compose.yml up -d
service1 application.yml have the same type of connection with Eureka server of the previous microservice.
service1 is correctly deployed but It can't register himself to the Eureka server, if I log out the container output I have this error:
2022-06-29 15:45:20.551 INFO 1 --- [ main] c.n.d.s.t.d.RedirectingEurekaHttpClient : Request execution error. endpoint=DefaultEndpoint{ serviceUrl='http://172.17.0.2:8761/eureka/}, exception=I/O error on GET request for "http://172.17.0.2:8761/eureka/apps/": Connect to 172.17.0.2:8761 [/172.17.0.2] failed: Connection timed out; nested exception is org.apache.http.conn.ConnectTimeoutException: Connect to 172.17.0.2:8761 [/172.17.0.2] failed: Connection timed out stacktrace=org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://172.17.0.2:8761/eureka/apps/": Connect to 172.17.0.2:8761 [/172.17.0.2] failed: Connection timed out; nested exception is org.apache.http.conn.ConnectTimeoutException: Connect to 172.17.0.2:8761 [/172.17.0.2] failed: Connection timed out
I read that someone directly insert the Eureka Server data as a service inside the Docker-Compose.yml file, but my Eureka Server is already deployed and is already listening to a specific port.
That is probably happening because docker-compose automatically assign a network to the containers.
Try adding network_mode: host to your services in the compose file, like so:
version: "3.3"
services:
docker-mysql:
network_mode: host
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 'password'
MYSQL_DATABASE: 'db'
ports:
- "3007:3306"
phpmyadmin:
network_mode: host
image: phpmyadmin
restart: always
container_name: php-my-admin-users
ports:
- "8081:80"
ldap-app:
network_mode: host
image: myRepo/service1:latest
ports:
- "8090:8090"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://docker-mysql:3306/db
depends_on:
- docker-mysql
First I would suggest you get familiar with how networking in Docker works and then have a look at networking in Docker-Compose.
When you run docker network ls when your containers are deployed you will see that they are running on different networks, which isolates them. Inspect the networks using docker network inspect <id> and you'll see they have different subnets. So for the services to be able to communicate they need to be on the same network.
You can manually create a network and use it in both compose and the docker cli.
I'm facing this issue when trying to use a microservice in docker (this doesn't happen in local).
An exception occurred in RetryableException, in the line -2:
Connection refused executing GET http://localhost:8082/api/car/findAll
this is my docker-compose file
version: '3.9'
services:
people:
build:
context: peoplems
ports:
- '8081:8081'
networks:
- host
vehicles:
build:
context: vehiclesms
ports:
- '8082:8082'
networks:
- host
api:
build:
context: apigateway
dockerfile: Dockefile
ports:
- '8080:8080'
networks:
- host
networks:
host:
driver: bridge
The services are running
The error was that I was trying to call "localhost" using feignclient
url = http://localhost:8081/api/car
So, when the app was 'deployed' in docker, docker wouldn't find the localhost address. I had to change "localhost" by the name of the container where the service was deployed: parking-people-1. My new url in feignclient is now
url = http://parking-people-1:8081/api/car
and it works.
NOTE: with this solution, you don't have to create a new network anymore. (at least in this case.)
I hope this could be useful for someone.
I got troubles get Zuul working with a dockerized Spring boot app.
It seems Zuul is not able to proxy requests to the target application (gis_import_export) even if it is up and running.
My Zuul based Spring app configuration:
spring:
banner:
location: classpath:banner.txt
zuul:
debug:
request: true
routes:
ie:
url: http://gis_import_export:8080
geoserver:
url: http://geoserver:8080
geonetwork:
url: http://geonetwork:8080
ribbon:
eureka:
enabled: false
and my docker-compose.yml file:
version: "3"
services:
geoserver:
image: kartoza/geoserver
geonetwork:
image: geonetwork
postgres:
image: postgres
environment:
- POSTGRES_DB=xxx
- POSTGRES_PASSWORD=xxx
- POSTGRES_USER=xxx
gis_import_export:
image: gis_import_export:develop
ports:
- 8888:8080
zuul:
image: gis_api_gateway:develop
ports:
- 8080:8080
I'm able to have geonetwork/geoserver proxied correctly via Zuul service exposed port but I'm stuck with getting with Spring boot app seems not get proxied.
By the way, the dockerized Spring boot apps works as expected if accessed via the 8888 port and via Zuul if zuul itself is not deployed via Docker.
Running a ping/telnet to dockerized spring boot app inside the Zuul docker container works as expected, so names are being resolved correctly.
Ideas?
Thanks, FB
Your services running in different docker networkds.
You have to specify same network in two files network.
And of course it will be good if you specify hostname parameter for each container
I'm trying to use docker-compose to run 2 simple services locally (Ubuntu): a eureka server, and config server (which is also a eureka client). Both of these have simple dockerfiles that run java -jar, expose their ports, and individually work fine. I also tried to add eureka.client.service-url.defaultZone=http://company-service-discovery:8761/eureka to see if it would register itself, and it worked.
My config server cannot successfully register to the eureka server, and I've googled it and nothing I've seen helped me solve this.
According to docker-compose documentation at https://docs.docker.com/compose/networking/ :
By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.
With the following example web should be able to use postgres://db:5432 to communicate with the database.
version: "3"
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
ports:
- "8001:5432"
I have used the same method to configure my services, but my config server gets connection refused when trying to register:
docker-compose.yml
version: '3.3'
services:
company-service-discovery:
build: company-service-discovery/
ports:
- "8761:8761"
company-config-server:
build: company-config-server/
ports:
- "8888:8888"
links:
- company-service-discovery
config server bootstrap.yml
server:
port: 8888
management:
security:
enabled: false
spring:
application:
name: company-config-server
cloud:
config:
server:
native:
search-locations: classpath:/shared
profiles:
include: native
eureka:
client:
service-url:
defaultZone: http://company-service-discovery:8761/eureka
eureka server bootstrap.yml
spring:
application:
name: company-service-discovery
server:
port: 8761
management:
security:
enabled: false
exception
2017-07-26 14:25:05.738 WARN 1 --- [nfoReplicator-0] c.n.d.s.t.d.RetryableEurekaHttpClient : Request execution failed with message: java.net.ConnectException: Connection refused (Connection refused)
2017-07-26 14:25:05.739 WARN 1 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_COMPANY-CONFIG-SERVER/365d20275ab0:company-config-server:8888 - registration failed Cannot execute request on any known server
question
Is there anything wrong with my configuration ? How can I make it work ?
Let me know if there's any info missing, I'll gladly give any info I can.
Add the defaultZone configuration to the Eureka server's properties too (and change the service-url to serviceUrl in your config server bootstrap.yml).
eureka server bootstrap.yml
spring:
application:
name: company-service-discovery
eureka:
client:
serviceUrl:
defaultZone: http://company-service-discovery:8761/eureka
server:
port: 8761
management:
security:
enabled: false
Thank you sooo much. this post resolved my problem - connecting eureka client to eureka server with docker. After 2 days of searching it work. I am in tears.
So basically -
you should use following in eureka client's application.properties/.yml
eureka.client.service-url.defaultZone=http://eureka-server:8761/eureka
and in docker-compose.yml your eureka service name should match with - the url host name, in my case it is - eureka-server
I met some problems with micro-spring-docker , i think maybe the sso token-url is not correct.
The demo https://github.com/keryhu/micro-oauth2-docker
In local computer , sso service and auth-service works fine .
But not in docker container ,
the problem is that redirecting to auth-server Timeout .
SSO(pc-gateway service) application.yml:
security:
user:
password: none
oauth2:
client:
accessTokenUri: http://${AUTHSERVER_PORT_9999_TCP_ADDR:localhost}:9999/uaa/oauth/token
userAuthorizationUri: http://${AUTHSERVER_PORT_9999_TCP_ADDR:localhost}:9999/uaa/oauth/authorize
docker-compose.yml
eureka:
image: eureka:0.0.1-SNAPSHOT
container_name: eureka
hostname: eureka
ports:
- "8761:8761"
configserver:
image: config-server:0.0.1-SNAPSHOT
container_name: configserver
hostname: configserver
links:
- eureka
ports:
- "8888:8888"
authserver:
image: auth-server:0.0.1-SNAPSHOT
container_name: authserver
hostname: authserver
links:
- eureka
- configserver
ports:
- "9999:9999"
pcgateway:
image: pc-gateway:0.0.1-SNAPSHOT
container_name: pcgateway
hostname: pcgateway
links:
- eureka
- configserver
- authserver
ports:
- "8080:8080"
After starting in docker container :
http://192.168.99.100:8761/ showing :
Instances currently registered with Eureka
Application AMIs Availability Zones Status
AUTHSERVER n/a(1) (1) UP (1) - authserver:authserver:9999
CONFIGSERVER n/a(1) (1) UP (1) - configserver:configserver:8888
PCGATEWAY n/a(1) (1) UP (1) - pcgateway:pcgateway:8080
But when open the auth page: http://192.168.99.100:8080
It should be redirected to auth-server login page , but it opened Timeout , the Address Bar is:
http://172.17.0.4:9999/uaa/oauth/authorize?client_id=clientapp&redirect_uri=http://192.168.99.100:8080/login&response_type=code&state=cdXhfg
I don't know why , maybe the above sso tokenurl is not correct . How to resolve ?
The 172.17.0.4 IP-address is the IP-address of the authserver container on the internal (container-container) network, which is not reachable from outside the docker host (Virtual Machine).
This may be tricky, because (in this case) you need to provide the IP-address of the Virtual Machine that docker runs on, which may change, and definitely will be different in production.
If you change ${AUTHSERVER_PORT_9999_TCP_ADDR:localhost} to 192.168.99.100, it should work.
I suggest to make the IP-address (or domain) configurable using an environment-variable that you provide in the docker-compose.yml, so something like:
${DOMAIN_NAME:192.168.99.100}
Which defaults to the "standard" IP-address of the Virtual Machine. In production you can then pass the actual domain-name, or IP-address of the server your project runs on.
Note that the "link" environment variables are marked deprecated, and only will
be used on the default (bridge) network. The new linking feature won't create
these variables, but you can simply link to other containers by name. See
https://docs.docker.com/engine/userguide/networking/work-with-networks/#linking-containers-in-user-defined-networks