SQL Server named instance in Docker - sql-server

How can I run a named SQL Server instance inside a Docker container?
I have an application that has a connection string pointing to a named SQL Server instance, something like Data Source=HostName\InstanceName; this connection string is very problematic for me to change. I want to dockerize that SQL Server instance. I already configured it so that I can connect to the dockerized instance via sqlcmd using sqlcmd -S HostName but when using sqlcmd -S HostName\InstanceName (which should be equivalent to the connection string this application is using) it does not establish a connection.

Docker containers do not support named instances; this is mentioned here:
There is no concept of a named instance. Every container can have a unique name. ...Containers don't have a concept of running multiple SQL Server instances. So there is no option of running more than one instance name.
Really, you should change the connection string. An alternative if you can't change the connection string (but you really should change the connection string) is to create an alias on each client using their local client network utility or configuration manager.
For example, you can create an alias on the client that points to HostName\InstanceName but, underneath, the mapping would actually redirect to HostName,2700 (assuming 2700 is the port you specified in docker run ... -p 2700:1433 ...).
Aliases are talked about more thoroughly here and I talk about using custom and specific ports for Docker containers here.
Did I mention it is much more logical to change your connection strings? That is probably the problem you want to fix.

Related

How to populate SQL Server database in Docker using .NET Core app?

I have a .NET Core app and when running it via dotnet run command, it automatically populates the database based on its ConnectionString in appSettings.json as shown below:
"ConnectionStrings": {
"DefaultConnection": "Server=localhost,21433;Initial Catalog=DemoDb;User Id=demo;Password=******;"
},
As I have already an SQL Server database in my Docker container, I want to use the existing server container and populate the new database to it in Docker. When I run the app, the new database is populated, but the app is not initialized.
I use the same port number of the ConnectionString above but when running the app it throws "The underlying exception message was 'No connection could be made because the target machine actively refused it. (localhost:4200)'" error. I think it is related to using the same port with the other database in this container.
At this step:
Should I create a new container for this new database, or use the same SQL Server container for both databases?
Can I use the same port as the previously installed database on Docker? Or should I change it with another port in the connection string?
Sorry, I am new in Docker.
The nature of Docker suggest that if the databases are unrelated then they should exist in separate containers.
If there is a need to interact between the databases then having them on the same instance within the same container is fine.
The port is for the Instance - not the individual database, but you will need to have something in your code that identifies the database you need - whether that is a USE statement in your T-SQL code or an explicit connection to the new database.
What scope have you defined your user at? Is it a contained database user? If so then you MUST specify the correct database in the connection string - if it is at the instance level as a login then that doesn't matter, but it does have to be mapped to a database user in the new database for that login.

Connect to SQL Server Express running inside a container from SSMS

I am trying to connect to an instance of SQL Server Express running inside a container from SSMS running on my host machine.
The container was started as follows:
docker pull microsoft/mssql-server-windows-express
docker run -d -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=password" -p 1436:1433 --name mydb microsoft/mssql-server-windows-express
The container is running on the IP address that I got using
docker inspect --format '{{.NetworkSettings.Networks.nat.IPAddress}}' mydb
Now I am trying to connect to this instance, at the above IP address using SSMS, but get the following error:
I get the same error even if I change the case/position of the instance, e.g. 1.2.3.4,1436\SQLExpress, or 1.2.3.4\SQLExpress,1436.
What am I missing?
Possible duplicates:
Cannot connect to SQL Server express from SSMS
Connect to SQL Express with SSMS
But the answers didn't help me.
I have made sure that the container is up and running. I can ping to the IP address of the container.
The username and password are correct.
One thing I could be missing is that the SQL Server authentication is not enabled on the database instance in the container. I am not sure how to do that.
How can I connect to the SQL Server Express instance running inside a container from SSMS?
The original password I had used was weak (no I wasn't using password used in the question, but a different one which was still weak).
After starting a new container with a password which has combinations of uppercase, lowercase, characters, and numbers, I can now log into the database using following settings.

Can't reach docker-hosted SQL server from web app docker on same host

On the same virutal machine (remote, ubuntu), I have
An SQL Server running in a Docker
An .NET Core 2.2 (IdentityServer) application running in a docker
An instance of jwilder.nginx-proxy serving as a reverse-proxy for every web application on the machine
A multitude of other .NET Core apps
I am able to connect to all of my websites using both machine IP + port and domain name, which means the reverse proxy works as expected and the dockers are well-configured
I am able to connect to the SQL Server using SSMS from my local machine, which means that the SQL Server docker properly forwards the TCP connection on port 1433
The IdentityServer .NET Core 2 web application is able to connect to the SQL Server when run on my local machine.
The remote-docker IdentityServer application can't reach the SQL Server instance with the following error (shortened for clarity - removed stack trace)
System.Data.SqlClient.SqlException (0x80131904):
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: 40 - Could not open a connection to SQL Server) at [...]
I know that the SQL server is running and reachable from the internet, and I know that the application's code is not at fault because I tested both.
So I deduced it had to be the IdentityServer docker that was blocking the connexion. So I tried:
Using the --expose 20 command on the IdentityServer docker
Opening mapping the port 20 inside the container to some port outside -p 45264:20 in addition to the already exposed port 80
I originally worked on using the port 1433 on both sides of the mapping but since it didn't work I tried using an other port on the outside (20). Didn't change anything
Here is the connexion string used by the IdentityServer (sensitive data hidden):
Data Source=***.***.***.***,20;Initial Catalog=Identity;Persist Security Info=True;User ID=**;Password=******************
Why can't my IdentityServer docker reach the SQL Server docker while the SQL Server itself is perfectly reachable? How can I make this setup work?
When wrapping SQL server into Docker, the first thing to anticipate is the way you connect. SQL Server prefers named pipes and you have to explicitly set mode to tcp.
If connection is done locally, don't use localhost, change it to 127.0.0.1. Also writing explicit tcp: prefix may help, like this: Server=tcp:x.y.z.q,1433
As I understood you run Sql Server and IdentityServer (which has connection problem) in separate docker containers.
If this is so then referring to localhost (i.e. 127.0.0.1) is not correct. Because in this case IdentityServer tries to connect to itself. This would work if the IdentityServer have run on the host machine, since you forward SQL server port to it. But in your case, you should connect to the SQL server container IP instead.
Considering all above I see three options for you to solve this:
You can get ip address of SQL Server container by running docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <sql_container_name_or_id>
Run SQL container with static IP via docker run --ip <static_ip_value> <sql_container_name_or_id> and then use static ip you have specified in connection string.
Run SQL container with specified host name via docker run --hostname <sql_host_name> <sql_container_name_or_id> and then use specified hostname in the connection string.
It is up to you which way to go.
Use tcp, 127.0.0.1 and host port to connect. Mention in the identity server docker settings that it depends on sql database server container. Like this,
identityservice:
...
depends_on:
- sqldataservice
This way the database container will be made available first.
"ConnectionString": "Server=tcp:127.0.0.1,8433;Database=dbname;User Id=sa;Password=abc#1234;"
I ended up giving up on getting this to work using a single host, so I simply decided to have the SQL Server run in a separate machine.

JDBC connect to MSSQL named instance with non-standard port

Hello guys I'm working on a project and I'm trying to connect JIRA to a MSSQL aliased or named instance. Checkout here if you don't know what i'm talking about.
Under this setup, for example, when you want to connect to a specific DB server, let's say using SQL Studio, you have to use "servername,port" as in the mssql server alias configuration, that reflects the DB instance.
What would be the connection string to use under this circunstances?
I've read about issues with this kind of setup as I'm using the JDBC driver (JIRA uses it). You can try with SQuirreL for testing this, as it uses the same driver.
Cheers!
For SQL Server JDBC you either connect to the named instance or to a specific port. If you specify both named instance and port, it will ignore the instance name.
If you want to connect to a named instance which is not running on the default port, you will need to have the SQL Server Browser service running on the server, this allows the JDBC driver to lookup the right port based on the instance name. I believe this service by default is disabled.

JDBC connect string for SQL Server cluster

I need to setup a JDBC connection string to SQL Server.
This question is similar to the the C# ADO.Net connection question. This one is specific to JDBC connection strings.
The usual format for the JDBC string is "jdbc:sqlserver://{host}:{port}".
Now, for a SQL server cluster I have a cluster name vvv\iii ({virtual server}{instance name}).
There's no problem setting up an ODBC connection through the "New Data Source to SQL Server" wizard when using the vvv\iii string as the server name. However it seems the JDBC connection string requires a specific host and port.
Is there a way to make a JDBC connect string to a SQL Server cluster?
it turns out that you can use the "instanceName" property within the JDBC string, as documented on the Microsoft Technet page in section "Named and Multiple SQL Server Instances". What worked in my case was the following string for virtual server vvv and database instance name iii:
"jdbc:sqlserver://vvv;instanceName=iii"
When using a SQL Server named instance in a cluster or stand alone environment each SQL Server instance is dynamically assigned a port number on startup. The SQL Server Browser server handles requests to each instance because each server restart could change the port number used by each instance. The first instance to start on a server reboot gets assigned 1433 but there is no guarantee if you have 2 instances that one of them will always get 1433. There are several veriables that affect the startup and recovery time it takes for an instance to start. This can change each time.
That being sad... when connecting to a named instance the jdbc connection string should look like this:
jdbc:sqlserver://server_name/db_name;instance=instance_name
rather than this
jdbc:sqlserver://server_name:1433/db_name;instance=instance_name
note that the default database "/db_name" is optional. If exclued the connection will use the default database assigned to the SQL Server login.
The cluster resource has a host name and a listening port. Use jdbc:sqlserver://{virtualserver}:1433 (or the appropriate listening port if not listening on the default one).
I'd comment Mark Stewart's remark, but the reputation is lacking. My source doesn't mention /db_name and I can't get it to work either. Maybe another case of confused instance names?
Make sure you leave the port definition off as the cluster determine this for you.
So my datasource definition looks like:
jdbc:sqlserver://sqlcluster_hostname\instancename;DATABASENAME=databasename;sendStringParametersAsUnicode=false;SelectMethod=direct
I ran into this issue while trying to setup a Railo datasource to connect to MSSQL cluster.
Slightly off topic ... The standard Railo datasource MSSQL driver option sets the port to "-1" if you leave the port field empty however if you set it to "0" then it removes the port definition altogether and then everything works. But the best way is to choose 'Other - JDBC Driver' to define the JDBC connection string in full as above.

Resources