I created a eureka server microservice and a normal microservice , usually when I run both the service separately using STS tool service discovery and registration works fine , but whenever i tried to launch in docker that time registration fails.
Code is below -
Eureka Server
application.properties
spring.application.name=eureka-service
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=eureka-service
eureka.instance.prefer-ip-address=true
eureka.server.wait-time-in-ms-when-sync-empty=0
Dockerfile
FROM openjdk:8
ADD target/SpringEureka-1.0.jar SpringEureka-1.0.jar
EXPOSE 8761
ENTRYPOINT ["java","-jar","SpringEureka-1.0.jar"]
Normal Microservice
application.properties
server.port: 8010
spring.application.name=eureka-client
eureka.client.register-with-eureka=true
eureka.client.fetch-registry= true
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
eureka.client.proxy-host=localhost
eureka.instance.prefer-ip-address=true
Dockerfile
FROM openjdk:8
ADD target/HystrixTest-1.0.jar HystrixTest-1.0.jar
EXPOSE 8010
ENTRYPOINT ["java","-jar","HystrixTest-1.0.jar"]
Are you link the HystrixTest container to Eureka Server container?
You can get more detail in here: https://docs.docker.com/network/links/
The better question if you post docker-compose file or your cmd when starting the container.
I think everything that you did is all right you just need to enable the ports using the
docker run -P 8761:8761 <your_docker_image> command.
And change also the configuration from eureka.instance.hostname=eureka-service to eureka.instance.hostname=localhost
Related
I am trying to run a Spring Boot application where db has to be connected to a MySQL container on Docker. I used following code and commands.
Application properties:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://mysqldb:3306/practice
spring.datasource.username=root
spring.datasource.password=CVnit1234!
spring.jpa.show-sql=true
spring.sql.init.platform=mysql
spring.sql.init.mode=always
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
Commands used for creating container & running it on Docker:
Pulling mysql image from Docker Hub:
docker pull mysql
Creating a container:
docker run --name mysqldb --network spring-net -p 3307:3306 -e MYSQL_ROOT_PASSWORD=password MYSQL_DATABASE=practice -d mysql:latest
After this command, a container is created and even it is up and working fine. I was able to login to sql bash and execute some queries.
I tried with multiple jdbc urls:
jdbc:mysql://mysqldb:3306/practice
jdbc:mysql://mysqldb:3307/practice
jdbc:mysql://mysqldb/practice
jdbc:mysql://host.docker.internal:3306/practice
jdbc:mysql://host.docker.internal:3307/practice
None of this worked, but I was able to connect to localhost:3306 and localhost:3307.
Below is my spring boot code. When I am trying to connect through the Spring Boot application, I was getting the following error.
com.mysql.cj.jdbc.exceptions.CommunicationsException:Communication link failure
The problem over here is when I am trying to connect to localhost the application is up and working, but when trying to connect to mysql container, I was not able to connect.
Check your network to ensure that the application network is connected to the MySQL network
I'm creating a custom Dockerfile with extensions for official keycloak docker image. I want to change web-context and add some custom providers.
Here's my Dockerfile:
FROM jboss/keycloak:7.0.0
COPY startup-config.cli /opt/jboss/tools/cli/startup-config.cli
RUN /opt/jboss/keycloak/bin/jboss-cli.sh --connect --controller=localhost:9990 --file="/opt/jboss/tools/cli/startup-config.cli"
ENV KEYCLOAK_USER=admin
ENV KEYCLOAK_PASSWORD=admin
and startup-config.cli file:
/subsystem=keycloak-server/:write-attribute(name=web-context,value="keycloak/auth")
/subsystem=keycloak-server/:add(name=providers,value="module:module:x.y.z.some-custom-provider")
Bu unfortunately I receive such error:
The controller is not available at localhost:9990: java.net.ConnectException: WFLYPRT0053: Could not connect to remote+http://localhost:9990. The connection failed: WFLYPRT0053: Could not connect to remote+http://localhost:9990. The connection failed: Connection refused
The command '/bin/sh -c /opt/jboss/keycloak/bin/jboss-cli.sh --connect --controller=localhost:9990 --file="/opt/jboss/tools/cli/startup-config.cli"' returned a non-zero code: 1
Is it a matter of invalid localhost? How should I refer to the management API?
Edit: I also tried with ENTRYPOINT instead of RUN, but the same error occurred during container initialization.
You are trying to have Wildfly load your custom config file at build-time here. The trouble is, that the Wildfly server is not running while the Dockerfile is building.
Wildfly actually already has you covered regarding automatically loading custom config, there is built in support for what you want to do. You simply need to put your config file in a "magic location" inside the image.
You need to drop your config file here:
/opt/jboss/startup-scripts/
So that your Dockerfile looks like this:
FROM jboss/keycloak:7.0.0
COPY startup-config.cli /opt/jboss/startup-scripts/startup-config.cli
ENV KEYCLOAK_USER=admin
ENV KEYCLOAK_PASSWORD=admin
Excerpt from the keycloak documentation:
Adding custom script using Dockerfile
A custom script can be added by
creating your own Dockerfile:
FROM keycloak
COPY custom-scripts/ /opt/jboss/startup-scripts/
Now you can simply start the image, and the built features in keycloak (Wildfly feature really) will go look for a config in that spedific directory, and then attempt to load it up.
Edit from comment with final solution:
While the original answer solved the issue with being able to pass configuration to the server at all, an issue remained with the content of the script. The following error was received when starting the container:
=========================================================================
Executing cli script: /opt/jboss/startup-scripts/startup-config.cli
No connection to the controller.
=========================================================================
The issue turned out to be in the startup-config.cli script, where the jboss command embed-server was missing, needed to initiate a connection to the jboss instance. Also missing was the closing stop-embedded-server command. More about configuring jboss in this manner in the docs here: CHAPTER 8. EMBEDDING A SERVER FOR OFFLINE CONFIGURATION
The final script:
embed-server --std-out=echo
/subsystem=keycloak-server/theme=defaults/:write-attribute(name=cacheThemes,value=false)
/subsystem=keycloak-server/theme=defaults/:write-attribute(name=cacheTemplates,value=false)
stop-embedded-server
WildFly management interfaces are not available when building the Docker image. Your only option is to start the CLI in embedded mode as discussed here Running CLI commands in WildFly Dockerfile.
A more advanced approach consists in using the S2I installation scripts to trigger CLI commands.
I have a spring boot application with two services but i need to run one on port 8080 and the other on 8081. Now i'm developing with sts (Spring tool suite) and i run the application with the option "Run as spring boot app", so i don't know where change server configurations. Someone can help me?
You can't run two different services under the same spring boot application in two different ports. If you want you can move one service to another spring boot application.
But port number will not be same for both services.
you can configure SprintBoot support two ports.The common method configure is use application.properties or the application.yaml as #Madhu Bhat answer. In SprintBoot to configure another port code like this:
create a connector
int port = Integer.parseInt(probePort);
Connector httpConnector = new Connector(HTTP_PROTOCOL);
httpConnector.setPort(port);
Http11NioProtocol handler = (Http11NioProtocol) httpConnector.getProtocolHandler();
handler.setMaxThreads(10);
handler.setMinSpareThreads(4);
//handler.setAddress(InetAddress.getLocalHost());
handler.setAddress(StringTool.getInetAddress());
return httpConnector;
configure connector to
((TomcatEmbeddedServletContainerFactory) container).addAdditionalTomcatConnectors(connector);
The port can be defined on the application.properties or the application.yaml configuration file that you use.
In application.properties file, define it as below:
server.port=8090
Or in case you are using a application.yaml config, define it as below:
server:
port: 8090
If you use Docker (most common solution), you can add the port or its full address as an Environment Variable
docker-compose.yml file like this:
application1:
image: 'application1:latest'
build:
context: ./
container_name: application
environment:
- HOST-APP2=localhost:8082
ports:
- 8091:8080
application2:
image: 'application2:latest'
build:
context: ./
container_name: application
environment:
- HOST-APP1=localhost:8081
ports:
- 8092:8080
or straight in the Dockerfile while building containers
check out here : https://vsupalov.com/docker-arg-env-variable-guide/
it's a good article
you can write below line in application.properties or application.yml
server.port=8080
Sure. You can do it in the application.properties file of spring boot project via setting server.port=number for each service.
I have created an image out of my simple spring-boot application and set the port to 7000 for the tomcat , when I run the image and try to hit the service in my local I am not getting any response.
here are the contents of the dockerfile
FROM java:8
VOLUME /tmp
ADD /target/demo-1.0-SNAPSHOT.jar /app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Am I missing something here ( I am new to docker and I just used the file in spring boot sample docker and created the image and stuck here.)
Apart from publishing the port from docker as mentioned by #Van0SS you need to create a port forwarding rule as well.
Open virtualbox and Navigate to VM -> Settings -> Network -> Advanced -> Port forwarding
Create a new rule:
Name : <Anything - Purpose of port>
Protocol: TCP
HostIP: 127.0.0.1
Host port: 7000
Guest Port: 7000
Not sure that it is only one problem, but at least you have to publish your port in docker. To do so run the container with flag:
-p 7000:7000
Try access on :7000 port.
You need to add:
EXPOSE: 7000
to your docker file, and keep an eye on the console log info when running the docker image to see on which port your app is being served.
Useful Ref:
https://www.youtube.com/watch?v=FlSup_eelYE
Best of luck!
How can I link my Spring Boot application container with MongoDB container?
Spring Boot app is using MongoDBRespository which by default connects to localhost:27017.
You should use container linking. From the docs:
When you set up a link, you create a conduit between a source container and a recipient container. The recipient can then access select data about the source
When two containers are linked, Docker will set some environment variables in the target container to enable programmatic discovery of information related to the source container.
Basically what this means is the following
your MongoDB-container should expose some ports (either via the EXPOSE entry in the Dockerfile or via the -p option to docker run).
your Spring Boot-container should be started with the --link option that points to the MongoDB-container.
The MongoDBRepository should be configured to use the address that is provided in the environment variables by the linking.
Check out this article on how to link containers for more info.
#Himanshu Yadav , you can try this resource. it did solve my problem. :-) It has got a full tutorial in that regard
https://www.jiwhiz.com/blogs/Spring_Boot_Docker_MySQL_Demo
Quote
docker run -p 8080:8080 --name demo-app --link demo-mysql:mysql -d jiwhiz/spring-boot-docker-mysql
I wonder if you got this to work by linking containers, it didn't work for me, tried using a linked container alias as a dbhost name in my Springboot app. I did not try it as MongoClientURI though.
I did opt a work around, with mongodb containers and spring apps containers, I had to set up mongo containers host and port to spring app containers while creating the apps containers as Containers ENV variables , as shown below
Mongo container
docker run -d -p 27027:27017 -p 28027:28017 --name mongodb --volumes-from dbdata iamiddy/mongodb
SpringBoot Apps containers
docker run -d -p 8000:8080 --name AppDockerContainer
-e db.host.name=EC2-HOSTING-MONGO-CONTAINER
-e db.host.port=DB-HOST-PORT AppDockerImage
application.properties
db.host.port=27017
db.host.name=localhost
MongoConfig
public class MongoRepositoryConfig extends AbstractMongoConfiguration {
#Value("${db.host.port}")
private int port;
#Value("${db.host.name}")
private String host;
#Value("${db.name}")
private String dbname;
#Override
public Mongo mongo() throws Exception {
ServerAddress serverAdress = new ServerAddress(host,port);
Mongo mongo = new MongoClient(serverAdress);
mongo.setWriteConcern(WriteConcern.ACKNOWLEDGED);
return mongo;
}
public #Bean MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), getDatabaseName());
}
#Override
protected String getDatabaseName() {
return dbname;
}
}
As docker links are now deprecated, one can use user defined networks to achieve communication between containers.
Referring to Docker Networking, docker has 3 different types of networks - Bridge, Host, Network. Using docker network ls you can list all networks currently defined. By default docker comes with 1 for each type pre-configured.
While running your container, one can specify(--network=abcd) network the process will join - by default its the docker0 of type bridge.
Now, for the problem statement in the question here, the simplest approach is to use --network=host while launching mongo & spring-boot-app container.
docker run -d -P --name=my-mongo --network=host mongo:latest
Then in your Spring boot app, you will have something like this:-
spring:
application:
name: my-app
data:
mongodb:
database: app
host: 192.168.99.100 // your machine private ip.
port: 27017
Run you spring boot app from image using :-
docker run -d -P --name=my-boot-app --network=host my-app-image
You can then use/reach mongo & app instances as if they were run without docker.
(While using docker-toolbox on Windows, you are actually running docker inside a VM that has different IP - I found it to be 192.168.99.100 . So remember to use this ip instead of your local ip)