Testcontainers with a company proxy - java

Each start of different testcontainers will throw com.github.dockerjava.api.exception.InternalServerErrorException: {"message":"Get https://quay.io/v1/_ping: dial tcp x.x.x.x: getsockopt: connection refused"}
This is no surprise (docker is behind a company proxy). How can I configure testcontainers to use a specific HTTP proxy?
Another approach could be disabling the "ping" command and using our company docker repo.

You can by specifying env variables when you are building an image or running a container. For example, below I'm building an Elasticsearch container by passing proxy configuration:
GenericContainer container = new GenericContainer("docker.elastic.co/elasticsearch/elasticsearch:6.1.1")
.withExposedPorts(9200)
.withEnv("discovery.type", "single-node")
.withEnv("HTTP_PROXY", "http://127.0.0.1:3001")
.withEnv("HTTPS_PROXY", "http://127.0.0.1:3001")
.waitingFor(Wait.forHttp("/_cat/health?v&pretty")
.forStatusCode(200));
Otherwise, you can set your proxy settings globally in docker. For windows with a docker machine you have to connect to it and the HTTP proxy in boot2docker profile.
docker-machine ssh default
sudo -s
echo "export HTTP_PROXY=http://your.proxy" >> /var/lib/boot2docker/profile
echo "export HTTPS_PROXY=http://your.proxy" >> /var/lib/boot2docker/profile
On Linux, you can create a file ~/.docker/config.json like :
{
"proxies":
{
"default":
{
"httpProxy": "http://127.0.0.1:3001",
"noProxy": "*.test.example.com,.example2.com"
}
}
}

Related

How to call one microservice from another microservice using docker images

I have two SpringBoot microservices M1(port 2002) and M2(port 2004)
M1 and M2 are communicating successfully if I run them using eclipse (run as Java Project or SpringBoot Project).
However, I want to communicate them using Docker container.
So I build images for both Microservices (M1 and M2) using the command:
docker build -f Dockerfile -t image_name .
And run the images using:
docker run -p 2004:2004 image_name
Note: I am exposing same port from docker as defined above
But the M1 and M2 are not able to communicate.
I am using RestTemplate
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> isUp = restTemplate.getForEntity("http://localhost:2002/apis/test",Boolean.class);
I am getting below exception :
I/O error on GET request for \"http://localhost:2002/apis/test\": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
However, If I call the other microservice using my machine's IP, It's communicating successfully
ResponseEntity<Boolean> isUp = restTemplate.getForEntity("http://XX.XX.XX.XXX:2002/apis/test",Boolean.class);
Can someone please tell if I am doing it write(using IP address) or there is another good approach to call one microservice from another using Docker?
Trying to communicate with the other container won't work with localhost.
You should create a custom bridged network, which will allow you to refer to the containers by name. And there is no need to publish the ports if you are only talking internally.
# create network
docker network create -d bridge mynet
# container 1
docker container run --network mynet --name container1 -d image_name
# container 2
docker container run --network mynet --name container2 -d some_other_image_name
The IP in code snippet can then be replaced with the name of the other container
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> isUp = restTemplate.getForEntity("http://container2:2002/apis/test",Boolean.class)
Alternately, you can also link the two containers together by --link. Assuming you want container1 as client to container2, you can use below:
sudo docker run --link container2 --name=container1 -d image_name

Running Spring boot application inside docker container

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!

Connecting an Oracle DB Container and a Java application Container (Docker)

I am now working on a docker project with two docker containers - one for the oracle db and the other with a java application.
The container for oracle db is working ok. I used the already built image for oracle and created my tablespaces and users in it.
Commands I used to pull and use the oracle db container is as given below:
docker pull wnameless/oracle-xe-11g
docker run -d -p 49160:22 -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g
Now I have my own Java application that interacts with the oracle db and I run it using the command given below:
docker run -it --name mypgm myrepo/oracletesting
It runs an interactive java program that asks for the Oracle DB details and allows users to interact with the DB.
However I could not figure out how I have to specify details such as
Driver Name, Connection URL, Username, and Password
The values I gave are as given below:
Driver Name: oracle.jdbc.OracleDriver
Connection URL:jdbc:oracle:thin:#localhost:1521:orcl11g
Username: imtheuser
Password: **********
I dont know whats going wrong where but its not working.
I tried giving different inputs for Connection URL after inspecting the docker container ip address as well:
Connection URL: jdbc:oracle:thin:#172.17.0.2:1521:orcl11g
Am I giving the Connection URL and/or the port number correct? Can someone help me out to correctly connect these two containers and to get the project moving?
Thanks for your kind help..
You have to link the containers.
The oracle container should have a name.
try the following:
docker network create my-network # Create a network for containers
docker run -d -p 49160:22 -p 49161:1521 --network my-network --name oracle-db -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g
docker run -it --network my-network --name mypgm myrepo/oracletesting
Use as connection url to following string jdbc:oracle:thin:#oracle-db:1521:orcl11g
You can use a domain name in oracle connection string: oracle.dbhost.com, and use a --addhost oracle.dbhost.com:[ip address] when running your app in docker, or configure a dns to resolve the domain name.

Docker: Linking Spring Boot container with Mongo DB container

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)

Docker port isn't accessible from host

I have a new Spring Boot application that I just finished and am trying to deploy it to Docker. Inside the container the application works fine. It uses ports 9000 for user facing requests and 9100 for administrative tasks like health checks. When I start a docker instance and try to access port 9000 I get the following error:
curl: (56) Recv failure: Connection reset by peer
After a lot of experimentation (via curl), I confirmed in with several different configurations that the application functions fine inside the container, but when I try to map ports to the host it doesn't connect. I've tried starting it with the following commands. None of them allow me to access the ports from the host.
docker run -P=true my-app
docker run -p 9000:9000 my-app
The workaround
The only approach that works is using the --net host option, but this doesn't allow me to run more than one container on that host.
docker run -d --net=host my-app
Experiments with ports and expose
I've used various versions of the Dockerfile exposing different ports such as 9000 and 9100 or just 9000. None of that helped. Here's my latest version:
FROM ubuntu
MAINTAINER redacted
RUN apt-get update
RUN apt-get install openjdk-7-jre-headless -y
RUN mkdir -p /opt/app
WORKDIR /opt/app
ADD ./target/oauth-authentication-1.0.0.jar /opt/app/service.jar
ADD config.properties /opt/app/config.properties
EXPOSE 9000
ENTRYPOINT java -Dext.properties.dir=/opt/app -jar /opt/app/service.jar
Hello World works
To make sure I can run a Spring Boot application, I tried Simplest-Spring-Boot-MVC-HelloWorld and it worked fine.
Netstat Results
I've used netstat to do port scans from the host and from the container:
From the host
root#my-docker-host:~# nmap 172.17.0.71 -p9000-9200
Starting Nmap 6.40 ( http://nmap.org ) at 2014-11-14 19:19 UTC Nmap
scan report for my-docker-host (172.17.0.71)
Host is up (0.0000090s latency).
Not shown: 200 closed ports
PORT STATE SERVICE
9100/tcp open jetdirect
MAC Address: F2:1A:ED:F4:07:7A (Unknown)
Nmap done: 1 IP address (1 host up) scanned in 1.48 seconds
From the container
root#80cf20c0c1fa:/opt/app# nmap 127.0.0.1 -p9000-9200
Starting Nmap 6.40 ( http://nmap.org ) at 2014-11-14 19:20 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0000070s latency).
Not shown: 199 closed ports
PORT STATE SERVICE
9000/tcp open cslistener
9100/tcp open jetdirect
Nmap done: 1 IP address (1 host up) scanned in 2.25 seconds
The container is using Ubuntu
The hosts I've replicated this are Centos and Ubuntu.
This SO question seems similar but had very few details and no answers, so I thought I'd try to document my scenario a bit more.
I had a similar problem, in which specifying a host IP address as '127.0.0.1' wouldn't properly forward the port to the host.
Setting the web server's IP to '0.0.0.0' fixes the problem
eg - for my Node app - the following doesn't work
app.listen(3000, '127.0.0.1')
Where as the following does work:
app.listen(3000, '0.0.0.0')
Which I guess means that docker, by default, is exposing 0.0.0.0:containerPort -> local port
You should run with docker run -P to get the ports to map automatically to the same values to set in the Dockerfile.. Please see http://docs.docker.com/reference/run/#expose-incoming-ports

Categories

Resources