Docker Containers cannot communicate with Host Database - database

I know this question has been asked before, but I haven't managed to solve it from those answers.
System spec: I am running the server on Ubuntu 22.10 docker version is 20.10.16 and docker-compose version is 1.29.2
What I want to achieve: I have nextcloud running as a docker container and have MariaDB installed on the host machine uncontainerized. I want to use a database I created in MariaDB by nextcloud in docker container. But Hostname is always incorrect, and I get the following error.
Failed to connect to the database: An exception occurred in the driver: SQLSTATE[HY000] [2002] Connection refused
Troubleshooting I've tried so far
Option 1: I added an extra host to my docker compose file so it can listen to the host system. Here's how my docker compose file like
version: '2'
services:
app:
image: nextcloud
restart: always
ports:
- 8080:80
volumes:
- /home/ritzz/nextcloud:/var/www/html
extra_hosts:
- host.docker.internal:host-gateway
However, when adding database if I use host.docker.internal as hostname I still get the error mentioned above.
Option2: Using docker host IP as database hostname. I used the following command to find out my host ip which was 172.17.0.1
ip addr show docker0
However, again adding 172.17.0.1 or 172.17.0.1:3306 returns with the same error.
Option 3: I saw an option on the Internet to use network_mode: host to make the container use the same network as host. However, since docker container uses port 80 and on my host I can't use port 80. This method won't work for me I assume.
Additional Troubleshooting
I made sure Mariadb is with command sudo systemctl status mariadb as well as checked that it's listening to port 3306 using command sudo netstat -tlnp I also logged in to the database with the user and pass using command sudo mysql -u<username> -p<password> <database> and I can login successfully.
I am at the edge with this. Hopefully someone else can help me out

Related

How to connect superset to postgresql - The port is closed

My operating system is Linux.
I am going to connect Superset to PostgreSQL.
PostgreSQL port is open and its value is 5432.
PostgreSQL is also running and not closed.
Unfortunately, after a day of research on the Internet, I could not solve the problem and it gives the following error:
The port is closed.
Database port:
command: lsof -i TCP:5432
python3 13127 user 13u IPv4 279806 0t0 TCP localhost:40166->localhost:postgresql (ESTABLISHED)
python3 13127 user 14u IPv4 274261 0t0 TCP localhost:38814->localhost:postgresql (ESTABLISHED)
Please help me, I am a beginner, but I searched a lot and did not get any results.
Since you're running Superset in a docker container, you can't use 127.0.0.1 nor localhost, since they resolve to the container, not the host. For the host, use host.docker.internal
I had a similar problem using docker compose. Port is closed can be due to networking problem. Host.docker.internal doesn’t worked for me on Ubuntu 22. I would like to recommend to not follow official doc and use better approach with single docker image to start. Instead of running 5 containers by compose, run everything in one. Use official docker image, here image. Than modify docker file as follows to install custom db driver:
FROM apache/superset
USER root
RUN pip install mysqlclient
RUN pip install sqlalchemy-redshift
USER superset
Second step is to build new image based on docker file description. To avoid networking problems start both containers on same network (superset, your db) easier is to use host network. I used this on Google cloud example as follow:
docker run -d --network host --name superset supers
The same command to start container with your database. —network host. This solved my problems. More about in whole step to step tutorial: medium or here blog
From the configuration file, you set port 5432, but it does not mean that your pg service is available

Can't Connect to External SQL Server From Docker Container

I've developed a SpringBoot(Java) application that calls out to an external SQL Server on port 1433. The SQL Server instance is located on-premises (not local SQL Server instances). However, it's reachable from my desktop using either IntelliJ or SQL Clients.
I am using the Microsoft SQL Server JDBC connector to communicate with the instances.
If I run the app from IntelliJ all is well, the app can call the SQL Server, execute the command and returns a resultsset.
However, now I'm trying to Dockerize the api app. The container does the usual SpringBoot initialization but when it tries to call the SQL Server I get the following error:
com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host myexternalsqlserver.domain, port 1433 has failed. Error: "myexternalsqlserver.domain. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:234)
at com.microsoft.sqlserver.jdbc.SQLServerException.ConvertConnectExceptionToSQLServerException(SQLServerException.java:285)
at com.microsoft.sqlserver.jdbc.SocketFinder.findSocket(IOBuffer.java:2434)
at com.microsoft.sqlserver.jdbc.TDSChannel.open(IOBuffer.java:659)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:2546)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:2216)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:2067)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:1204)
at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:825)
at java.sql/java.sql.DriverManager.getConnection(Unknown Source)
at java.sql/java.sql.DriverManager.getConnection(Unknown Source)
at com.symetra.SdsApi.SqlConnector.getResultSet(SqlConnector.java:26)
This is my Docker file
FROM openjdk:11.0.4-jre-slim-buster
VOLUME /tmp
COPY target/myapi-1.0-SNAPSHOT.jar app.jar
EXPOSE 8080
EXPOSE 1433
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -jar /app.jar" ]
And these are the Docker commands I use to build and run the container:
docker build -t myapi . && docker run -p 8080:8080 -p 1433:1433 --name myapi myapi "java","-jar","myapi-1.0-SNAPSHOT.jar"
I don't think the mapping of port 1433 is necessary, it's just an experiment. I should be able to communicate outside of my container through to port 1433 on the host. Port 1433 isn't being blocked on the host because I have no problems running this outside the container.
Finally, this is the connection string I'm using:
//Create Connection Url.
String connectionUrl="jdbc:sqlserver://myexternalsqlserver.domain:1433;database=mydb;user=MyUser;password=MyPassword";
I'm not sure what I'm doing wrong here. I'm wondering if I need to set up Docker networking.
Thanks for your help!
It should work.
NB I'm assuming myexternalsqlserver.domain is not what you're using.
One way to test your container is to shell into it (or create a variant) and try resolving the SQL Server's host name:
docker run --interactive --tty openjdk:11.0.4-jre-slim-buster /bin/bash
# then from within the container's shell
apt update && apt install -y dnsutils
nslookup ${SQL_SERVER}
If that succeeds, it's your code.
If not, it's the network.
NB Your container need not publish 1443 (--publish=1433:1433) since it's consuming that port (on the SQL Server) not exposing the port itself.
The same issue bugged me for days and finally was able to solve it by following the steps below.
In my case the SQL server was hosted on Azure managed instance and exposed a private endpoint. The docker was able to resolve the DNS name of the Azure managed instance to a private IP address (as expected ). But this resolved IP was considered by the docker network/bridge as a locally running application because upon inspecting docker's bridge (docker network inspect bridge)The subnet of the bridge was found to be a range of IP addresses where the resolved IP of the SQL server also falls. Hence, the docker assumed the SQL server to be hosted in the same local network and not outside (here enterprise network). In my case the Windows VM I was working was already on the private network of the enterprise.
Solution:
In the docker desktop -> settings -> Docker Engine json file, add a new key value pair
"bip": "<local IP address range which is outside of the resolved sql server IP>".
Restart the docker desktop and the issue should be solved.

How to communicate between two docker containers (mssql and .net core app) got Connection refused 127.0.0.1:1433

I have a .net core 2.0 project which uses mssql server. I have Created a docker image and container for my .net core 2.0 and running on 9090:9090. I created it like below.
docker container run --name mytestapp --publish 9090:9090 --detach my_.netapp_image_name
and below is my connection string in .net core 2.0 app.
"DefaultConnection": "Server=127.0.0.1;Database=mydatabase;UserId=SA;Password=mydbpassword"
before this, I created a container for mssql server with below,
docker container run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=<YourStrong!Passw0rd>' \
-p 1433:1433 --name sql1 \
-d microsoft/mssql-server-linux:2017-latest
my .net core app has seeds for database. each time it gives me an error says
Unhandled Exception: System.Data.SqlClient.SqlException: A
network-related or instance-specific error occurred while establishing
a connection to SQL Server. The server was not found or was not
accessible. Verify that the instance name is correct and that SQL
Server is configured to allow remote connections. (provider: TCP
Provider, error: 35 - An internal exception was caught) --->
System.AggregateException: One or more errors occurred. (Connection
refused 127.0.0.1:1433) --->
System.Net.Internals.SocketExceptionFactory+ExtendedSocketException:
Connection refused 127.0.0.1:1433
NOTE: this works fine when I run my .net app via IDE(visual studio) and use db as docker mssql container. I ran these two containers separately. then I tried to run using docker-compose, but didn't work.
What am I doing wrong here. hope your help with this.
Containers each have their own network namespace by default. Compose will place all containers on a shared network and set an alias in DNS for the service name. So to connect between containers, all you need to do is point to your service name instead of the 127.0.0.1 (assuming mysql is your service name):
"DefaultConnection": "Server=mysql;Database=mydatabase;UserId=SA;Password=mydbpassword"
This is more portable and handles containers scaling/updating better than to attaching containers to the same network namespace.
So the issue here is the docker sandboxing. For each container that you run you can think of as different virtual environment that has its own host name, IP address and network. While using -p only forwards port form that internal network to host. So while you are running from VS you can point to your db using localhost (127.0.0.1:1433) just because you have exposed that port to host and your application is starting on host directly. When it is runing inside its own container localhost no longer refers to host but rather to that docker environment. To fix this you can run both containers in the same network (--network argument on run) and refer from one to another by host name (--name argument on run).
docker container run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=<YourStrong!Passw0rd>' \
-p 1433:1433 --name sql1 \
-d microsoft/mssql-server-linux:2017-latest \
--name sql_server
docker container run \
--name mytestapp
--publish 9090:9090
--detach my_.netapp_image_name
--network container:sql_server
and in your settings refer to your database as sql_server.
To make this process less painful you can research docker-compose.

connecting to Mongodb inside a docker with mongodb compass GUI

I have a mongodb database running on the default port 27017 in a docker container.
Is there a way to connect to the database with the mongodb compass GUI running natively on my ubuntu OS?
docker run -p 27018:27017 and then connect from Compass on your host with port 27018. I don't see a reason to expose all ports.
Replace localhost with your IP address in the connection string, eg, my IP address is 10.1.2.123 then I have mongodb://10.1.2.123:27017?readPreference=primary&appname=MongoDB%20Compass&ssl=false.
Saw this 👆 here: https://nickjanetakis.com/blog/docker-tip-35-connect-to-a-database-running-on-your-docker-host
With docker-compose you just have to expose the port 27017. When You hit "Connect" in the GUI it will auto-detect this connection.
version: "3"
services:
mongo-database:
container_name: mongo-database
image: mongo:4
ports:
- 27017:27017
Yes we can run
Steps:
Pull/Restart the docker container mongodb
Enter the bash shell
docker exec -it mongodb bash
Now open the mongodb compass community and with same default connection just click connect and the docker container's mongodb will be connected to compass community.
My terminal running docker:
Mongodb Compass:
Use docker inspect or docker desktop to inspect and find the exposing port
docker inspect your_container_name
and find this section
"Ports": {
"27017/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "27012"
}
]
},
and then connect using this url string
mongodb://localhost:27012/?readPreference=primary&appname=MongoDB%20Compass&ssl=false
Do not pass in replica set name if you are using one otherwise connection will fail. This is if you have deployed a replica set instead of turning your standalone to a replica set.
Leave a comment if you don't know how to deploy a replica set and I can leave a docker-compose file to set up and deploy replica set.
I could connect the compass on windows to a docker using these tags at the end:
mongodb://user:password#localhost:27017/dbname?authSource=dbname&readPreference=primary&gssapiServiceName=mongodb&appname=MongoDB%20Compass&ssl=false
Just open compass and inside connect add the credentials if you have used envs like
ME_CONFIG_MONGODB_ADMINUSERNAME=admin
and hit connect.No addition settings required.
Or you can use mongo-express which a web based UI tool for monodb.
Run command sudo docker ps
it will show docker containers you have where you can find the port number of mongodb
the run the command sudo mongodb-compass
it will open the mongodb compass
If you are connecting locally so general hostname is : localhost
and then just put the port number and click on connect.
I was also having trouble connecting to my local MongoDB using Compass, but discovered it was an SSL problem. By default, Compass sets SSL to "System CA". However, if you try that with your dockerized Mongo, your Mongo logs will show you this error:
Error receiving request from client: SSLHandshakeFailed: SSL handshake received but server is started without SSL support. Ending connection from 172.17.0.1:45902 (connection id: 12)
end connection 172.17.0.1:45902 (0 connections now open)
Therefore, to connect, I had to click "Fill in connection fields individually" then set the SSL field to "None". For reference, I ran Mongo using this:
docker run -p 27017:27017 --name some-mongo mongo:4.0. No authentication necessary.
This solution worked for me.
Run the docker container using:
docker run -d --name mongo-db -v ~/mongo/data:/data/db -p 27017:27017 mongo
-v is for mapping the local volume to the docker writable space. This will keep the data even when the container is destroyed.
MongoDB connection string Compass GUI:
mongodb://localhost:27017
Run your mongo container with 'publish-all-ports' option (docker run -P). Then you should be able to inspect the port exposed to the host via docker ps -a and connect to it from Compass (just use your Hostname: localhost and Port: <exposed port>).
Use the --net=host option for Docker container shares its network namespace with the host machine.
docker run -it --net=host -v mongo_volume:/data/db --name mongo_example4 -d mongo
So now we can connect the mongodb with compass using mongodb://localhost:27017
Other hand to connect, simply get the docker container IPAddress using the docker inspect command and use that ip address instead of localhost
mongodb://172.17.0.2:27017

How can a dockerfile expose SQL Server as localhost?

Following the documentation on the microsoft/mssql-server-linux page, it provides the following command to get a docker container running.
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Test!234' -p 1433:1433 -d --name sqllinux microsoft/mssql-server-linux
This works fine and I'm able to open up SSMS and connect to localhost with the credentials:
username: sa
password: Test!234
What I wanted to do after that is to create a Dockerfile that will create the image that will do the same thing:
FROM microsoft/mssql-server-linux
ENV ACCEPT_EULA Y
ENV SA_PASSWORD Test!234
EXPOSE 1433 1433
I then ran docker build . -t sqltestfile followed by docker run sqltestfile.
The container seems to start just fine and through Kitematic I can see (what looks like to me) the same output as running the other image, but I'm not able to connect to this image through SSMS using localhost.
What needs to be changed about the Dockerfile to have it work the way I would expect (can connect to the container instance using SSMS through localhost)?
Any help would be greatly appreciated!
You still need to explicitly publish the port with -p.
From the docs:
The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. You can specify whether the port listens on TCP or UDP, and the default is TCP if the protocol is not specified.
The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published. To actually publish the port when running the container, use the -p flag on docker run to publish and map one or more ports, or the -P flag to publish all exposed ports and map them to to high-order ports.

Resources