Remote Debugging of Tomcat/Wildfly server in docker container in VSCode/Intellij - docker

I want to remote debug a Java application in Wildfly/Tomcat embedded in a
Docker container. I want to debug the application in VsCode; I also tried to remote debug in IntelliJ. For both I am getting the same error:
Error running 'Tomcat in Docker': Unable to open debugger port (localhost:9000): java.net.SocketException "Connection reset"
docker-compose
version: '3.7'
services:
wildfly:
image: jboss/wildfly:latest
ports:
- 8088:8080
- 9990:9990
- 8787:8787
entrypoint: "/opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 --debug"
tomcat:
image: tomcat:10
environment:
- JPDA_ADDRESS=8000
- JPDA_TRANSPORT=dt_socket
ports:
- 8888:8080
- 9000:8000
entrypoint: "/usr/local/tomcat/bin/catalina.sh jpda run"
launch.json in VsCode
{
"configurations": [
{
"type": "java",
"name": "Attach Wildfly",
"request": "attach",
"hostName": "localhost",
"port": "8787"
},
{
"type": "java",
"name": "Attach Tomcat",
"request": "attach",
"hostName": "localhost",
"port": "9000"
}
]
}
netstat -tuplen | grep 8787
tcp 0 0 0.0.0.0:8787 0.0.0.0:* LISTEN 0 257375 -
tcp6 0 0 :::8787 :::* LISTEN 0 257380 -
netstat -tuplen | grep 9000
tcp 0 0 0.0.0.0:9000 0.0.0.0:* LISTEN 0 255587 -
tcp6 0 0 :::9000 :::* LISTEN 0 253926 -
Any ideas? Thanks.

I had a similar issue when trying to attach to a tomcat container. VS Code displayed the following message:
Failed to connect to remote VM
com.sun.jdi.connect.spi.ClosedConnectionException
I think the problem is that the process is not allowing external connection unless it is listening on 0.0.0.0.
Add this environment variable to your tomcat container in your docker compose file:
JPDA_OPTS: "-agentlib:jdwp=transport=dt_socket,address=0.0.0.0:8000,server=y,suspend=n"
Alternatively, you can use the JAVA_TOOL_OPTS to pass the variables, but then you should start catalina regularly (without the jpda).
JAVA_TOOL_OPTIONS: "-agentlib:jdwp=transport=dt_socket,address=0.0.0.0:8000,server=y,suspend=n"

Related

telnet: Unable to connect to remote host: Connection refused when trying to connect running docker image

I am having ubuntu 18.04 running on a server. I am got a JasperServer image running on docker in it. I am trying to access it from my system. But it throws the following error:
jamshaid#jamshaid:~$ telnet my_server_address 9095
Trying my_server_ip...
telnet: Unable to connect to remote host: Connection refused
Here is the output for sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
69c31ba800ab bitnami/jasperreports "/app-entrypoint.sh …" 5 hours ago Up 5 hours 0.0.0.0:9095->8080/tcp, 0.0.0.0:443->8443/tcp ceyedev_jasperreports_1
2a7cb72da0c7 bitnami/mariadb:10.3 "/opt/bitnami/script…" 5 hours ago Up 5 hours 0.0.0.0:3306->3306/tcp ceyedev_mariadb_1
if I telnet on localhost, it connects and then connection closes which means it is running well.
Here is the output when I telnet it from localhost:
ceyedev#ub18servertiny:~$ telnet localhost 9095
Trying ::1...
Connected to localhost.localdomain.
Escape character is '^]'.
Connection closed by foreign host.
Here is the docker-compose file
version: '2'
services:
mariadb:
restart: always
image: 'bitnami/mariadb:10.3'
environment:
- MARIADB_USER=bn_jasperreports
- MARIADB_DATABASE=bitnami_jasperreports
- ALLOW_EMPTY_PASSWORD=yes
ports:
- 3306:3306
volumes:
- 'mariadb_data:/bitnami'
jasperreports:
restart: always
image: 'bitnami/jasperreports'
environment:
- MARIADB_HOST=mariadb
- MARIADB_PORT_NUMBER=3306
- JASPERREPORTS_DATABASE_USER=bn_jasperreports
- JASPERREPORTS_DATABASE_NAME=bitnami_jasperreports
- ALLOW_EMPTY_PASSWORD=yes
ports:
- '9095:8080'
- '443:8443'
volumes:
- 'jasperreports_data:/bitnami'
depends_on:
- mariadb
volumes:
mariadb_data:
driver: local
jasperreports_data:
driver: local
Here is the output for sudo docker logs container_id_for_jasper
I can telnet other ports from my local machine but having an issue with this one. Any ideas? thanks
keeping in the view of bullet 2 from answers, I executed the below command and found that 9095 is allocated by the server. Any ideas, please?
ceyedev#ub18servertiny:~$ netstat -atn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN
tcp 0 244 10.0.114.15:22 182.185.223.147:54326 ESTABLISHED
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 ::1:5432 :::* LISTEN
tcp6 0 0 :::443 :::* LISTEN
tcp6 0 0 :::9095 :::* LISTEN
tcp6 0 0 :::3306 :::* LISTEN
To people who got there and didn't find solution:
Make sure your web server is listening on 0.0.0.0 to listen ALL interfaces, including docker bridge to outer network
Based on your question, you know:
Docker container is running
Docker container is listening to port 9095
telnet from Linux server to docker container is working
telnet from other client somewhere in Internet to docker container is NOT working
I guess your Ubuntu server is not accepting incoming requests from Internet on port 9095.
There can be many reasons for that:
Your server has firewall settings, which block connection
Your server did not publish port 9095 to Internet
Your client has no Internet access, when using port 9095
So I would investigate these aspects.
The docker part seems to be ok, because telnet to localhost is working.

CAN connect to Docker service on localhost. CANNOT connect to Docker service on LAN IP Address

I have a Docker service running on an Ubuntu 19.04 server, which lives on my LAN.
The service in question exposes a SOCKS5 proxy on port 1080.
When I run the following commands from the server they work:
~$ curl --proxy socks5://127.0.0.1:1080 ipinfo.io
{
"ip": "xx.xxx.xxx.xxx",
"city": "Phoenix",
"region": "Arizona",
"country": "US",
...
}
~$ docker container inspect my-docker-service | grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "",
"IPAddress": "172.19.0.8",
~$ curl --proxy socks5://172.19.0.8:1080 ipinfo.io
{
"ip": "xx.xxx.xxx.xxx",
"city": "Phoenix",
"region": "Arizona",
"country": "US",
...
}
But when I run this one from the server, it doesn't:
~$ ip a
...
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
...
inet 192.168.1.95/24
...
~$ curl --proxy socks5://192.168.1.95:1080 ipinfo.io
curl: (7) Failed to connect to 192.168.1.95 port 1080: Connection timed out
My docker-compose.yml looks like:
my-docker-service:
privileged: true
image: ohpe/socks-my-vpn
container_name: my-docker-service
devices:
- /dev/net/tun
cap_add:
- net_admin
tty: true
sysctls:
net.ipv6.conf.all.disable_ipv6: 0
environment:
- PROXY_PORT=1080
volumes:
- /path/to/configs/my-docker-service:/vpn:ro
ports:
- 1080:1080
dns:
- 1.1.1.1
restart: unless-stopped
I've disabled ufw, and also using nmap on another LAN device gives me:
λ nmap -p 1080 192.168.1.95
Starting Nmap 7.80 ( https://nmap.org ) at xxx
Nmap scan report for 192.168.1.95
Host is up (0.0020s latency).
PORT STATE SERVICE
1080/tcp filtered socks
MAC Address: xx:xx:xx:xx:xx:xx (xxx)
Nmap done: 1 IP address (1 host up) scanned in 5.53 seconds
How can I make this proxy service available to other devices on my LAN?

Why I am unable to access service created by docker-compose?

I am building a micro-service based web app with Flask and Docker. Currently, I have 2 services running by docker-compose under the same default network.
mysql
product_api
docker-compose.yml file is --
version: '3'
services:
mysql:
image: mysql
environment:
MYSQL_USER: "mysqluser"
MYSQL_PASSWORD: "mysqlpassword"
MYSQL_ROOT_PASSWORD: "root"
MYSQL_DATABASE: "gadgetfreeiot"
container_name: mysql
ports:
- 3306:3306
restart: always
entrypoint: ['docker-entrypoint.sh', '--default-authentication-plugin=mysql_native_password']
product_api:
build: ./${SERVICE_ROOT:-src/services/product/api}
image: product_api:v1
container_name: product_api
volumes:
- ./${SERVICE_ROOT:-src/services/product/api}:${PROJECT_ROOT:-/usr/projects/gadgetfreeiot}/${SERVICE_ROOT:-src/services/product/api}
ports:
- 5000:5000
depends_on:
- mysql
environment:
username: "mysqluser"
password: "mysqlpassword"
host: "mysql"
port: "3306"
database: "gadgetfreeiot"
command: ["./wait-for-mysql.sh", "--", "python", "./run.py"]
docker ps output gives me --
johir#ubuntu:gadgetfreeiot$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e10329e26e5c product_api:v1 "./wait-for-mysql.sh…" 18 minutes ago Up 18 minutes 0.0.0.0:5000->5000/tcp product_api
7fed5a136123 mysql "docker-entrypoint.s…" 18 minutes ago Up 18 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
Both services are running under gadgetfreeiot_default network. docker inspect gadgetfreeiot_default shows that both are under the same network --
johir#ubuntu:gadgetfreeiot$ docker inspect gadgetfreeiot_default
[
{
"Name": "gadgetfreeiot_default",
"Id": "67e09ae3a33c0ff4203eefe4fee6ba421d3f68564c6e32c7d1cd04e866ac6850",
"Created": "2018-10-18T14:56:05.86215576+03:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "192.168.0.0/20",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"14ffb8eaa0c17de0122de142dbcf7aa5455b41b47eadb197e8be200c2375fbb3": {
"Name": "mysql",
"EndpointID": "38ed4140ed728271194ee82f12b3d937c53166f6159ab4e6fcf2d8087039ed06",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/20",
"IPv6Address": ""
},
"e013059b510e42933d33f7c3fb7e141a19a6c78a0e34d031e5fce5e104aa8697": {
"Name": "product_api",
"EndpointID": "fdbe0ed92d0e53d6fc1040a50b1898e2bb87b34384f80b98e638a3a89a57c4e1",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/20",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "gadgetfreeiot",
"com.docker.compose.version": "1.22.0"
}
}
]
Now I am trying to access the product_api as well as mysql services from my host OS. In the meantime, I am also trying to access from one container to another (from product_api to mysql and from mysql to product_api). mysql is accessible from all 3 that is my host OS, product_api and mysql itself by --
mysql -h172.19.0.2 -P3306 -umysqluser -p
product_api is also able to access by --
mysql -hmysql -P3306 -umysqluser -p
Luckily I am able to access curl http://localhost:5000 shows from product_api --
johir#ubuntu:gadgetfreeiot$ docker exec -it product_api bash
root#e013059b510e:/usr/projects/gadgetfreeiot/src/services/product/api# curl http://localhost:5000
{
"message": "Endpoint not found",
"status": "failed"
}
Where curl http://172.19.0.3:5000 shows --
curl: (7) Failed to connect to 172.19.0.3 port 5000: Connection refused
That means product_api is up & running and only accessible by localhost or 127.0.0.1 from inside the product_api container not by IP or by service name from outside product_api container that is neither from my host OS nor from mysql container.
Finally, I checked -- active networks among 3 by netstat -tln --
# product_api container
root#e10329e26e5c:/usr/projects/gadgetfreeiot/src/services/product/api# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.11:40071 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN
# mysql container
root#7fed5a136123:/# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.11:35507 0.0.0.0:* LISTEN
tcp6 0 0 :::33060 :::* LISTEN
tcp6 0 0 :::3306 :::* LISTEN
# host OS
johir#ubuntu:gadgetfreeiot$ netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp6 0 0 ::1:631 :::* LISTEN
tcp6 0 0 :::5000 :::* LISTEN
tcp6 0 0 :::3306 :::* LISTEN
Note:
port 5000 is not open by tcp6 in product_api container. On the other hand port 3306 is open by tcp6 on mysql container.
Question: Why I am unable to access product_api service from my host OS or even from mysql (in constraint, why tcp6 is not exposing port 5000 for product_api service)?
The short answer is, you aren't unable to access, as you showed with curl http://localhost:5000. It just seems to be a bit confusing who (host vs containers) can access which IPs and resolve which hostnames.
In your docker-compose.yml you mapped the ports 3306 and 5000 to your respective containers. So docker added a port forward from any interface on your host (w/o the interfaces of the docker networks) to your containers (have a look at the output of sudo iptables-save | grep 5000 if you are interested in how it's done under the hood, it will look something like this:
-A DOCKER -d 192.168.0.2/20 ! -i br-e013059b510e -o br-e013059b510e -p tcp -m tcp --dport 5000 -j ACCEPT
Access
So from your host, you can reach your service via
curl http://localhost:5000
From another computer (assuming firewall settings allow) via
curl http://your.hostname:5000
From a container on the same docker network
curl http://product_api:5000 # or
curl http://product_api.gadgetfreeiot_default:5000 # or
curl http://192.168.0.3:5000
To have both container on the same docker network, adjust your docker-compose.yml like this:
services:
mysql:
[...]
ports:
- 3306:3306
networks:
- gadgetfreeiot
[...]
product_api:
ports:
- 5000:5000
networks:
- gadgetfreeiot
[...]
networks:
gadgetfreeiot:
DNS
Container hostnames like product_api are not resolvable on the host. They are however inside your containers. Inside a container you have an extra docker DNS server at 127.0.0.11 which can resolve what your host can resove, plus docker hostnames like product_api.gadgetfreeiot_default. Try
nslookup product_api.gadgetfreeiot_default
on your host and from inside the container
docker exec -it mysql bash
Check https://docs.docker.com/network/ for more info on that.
With regards to your note: netstat doesn't show you which port is "open", i.e. allowed by the firewall, but which port is bound to by a program. Whether a program binds to a port on an interface on IPv4, v6 or both, is up to the program. This is not related to docker networking.

docker-compose can't connect to adjacent service via service name

I have this docker-compose.yml that basically builds my project for e2e test. It's composed of a postgres db, a backend Node app, a frontend Node app, and a spec app which runs the e2e test using cypress.
version: '3'
services:
database:
image: 'postgres'
backend:
build: ./backend
command: /bin/bash -c "sleep 3; yarn backpack dev"
depends_on:
- database
frontend:
build: ./frontend
command: /bin/bash -c "sleep 15; yarn nuxt"
depends_on:
- backend
spec:
build:
context: ./frontend
dockerfile: Dockerfile.e2e
command: /bin/bash -c "sleep 30; yarn cypress run"
depends_on:
- frontend
- backend
The Dockerfiles are just simple Dockerfiles that based off node:8 which copies the project files and run yarn install. In the spec Dockerfile, I pass http://frontend:3000 as FRONTEND_URL.
But this setup fails at the spec command when my cypress runner can't connect to frontend with error:
spec_1 | > Error: connect ECONNREFUSED 172.20.0.4:3000
As you can see, it resolves the hostname frontend to the IP correctly, but it's not able to connect. I'm scratching my head over why can't I connect to the frontend with the service name. If I switch the command on spec to do sleep 30; ping frontend, it's successfully pinging the container. I've tried deleting and let docker-compose recreate the network, I've tried specifying expose and links to the services respectively. All to no success.
I've set up a sample repo here if you wanna try replicating the issue:
https://github.com/afifsohaili/demo-dockercompose-network
Any help is greatly appreciated! Thank you!
Your application is listening on loopback:
$ docker run --rm --net container:demo-dockercompose-network_frontend_1 nicolaka/netshoot ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.11:35233 *:*
LISTEN 0 128 127.0.0.1:3000 *:*
From outside of the container, you cannot connect to ports that are only listening on loopback (127.0.0.1). You need to reconfigure your application to listen on all interfaces (0.0.0.0).
For your app, in the package.json, you can add (according to the nuxt faq):
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "3000"
}
},
Then you should see:
$ docker run --rm --net container:demo-dockercompose-network_frontend_1 nicolaka/netshoot ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:3000 *:*
LISTEN 0 128 127.0.0.11:39195 *:*
And instead of an unreachable error, you'll now get a 500:
...
frontend_1 | response: undefined,
frontend_1 | statusCode: 500,
frontend_1 | name: 'NuxtServerError' }
...
spec_1 | The response we received from your web server was:
spec_1 |
spec_1 | > 500: Server Error

Cannot access a Docker Swarm service through its published port on the host

I have deployed a Docker Swarm cluster on several machines and I am now trying to access to the server running in Docker from the host.
I use docker compose file to define my service and the exposed port appears when I inspect the service:
"Endpoint": {
"Spec": {
"Mode": "vip",
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 27017,
"PublishedPort": 3017,
"PublishMode": "host"
}
]
},
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 27017,
"PublishedPort": 3017,
"PublishMode": "host"
}
],
"VirtualIPs": [
{
"NetworkID": "**********",
"Addr": "10.0.0.34/24"
}
]
}
I use host mode because the service is constrained to run on a particular machine, and I want it accessible only from this machine.
But when I list the processes listening on ports on the host machine, the port doesn't appear.
And of course I cannot connect to the server from the host through the exposed port.
I am using iptables as firewall and restrains as much as possible the open ports, but the Docker Swarm needed ones are opened.
Here is my docker-compose.yml file:
version: '3.4'
services:
mongo-router:
image: mongo
networks:
- mongo-cluster
volumes:
- db-data-router:/data/db
- db-config-router:/data/configdb
ports:
- target: 27017
published: 3017
protocol: tcp
mode: host
deploy:
placement:
constraints:
- node.labels.mongo.router == true
command: mongos --configdb cnf/mongodb-cnf_mongo-cnf-1:27017,mongodb-cnf_mongo-cnf-2:27017,mongodb-cnf_mongo-cnf-3:27017
volumes:
db-data-router:
db-config-router:
networks:
mongo-cluster:
external: true
The network is an overlay network on which all services are subscribing.
I had a similar issue. After installing hyper-v feature on windows (even though the cpu did not support hyper-v) I was able to access published ports from the host (even in ingress mode).

Resources