2

My goal is to create an SQL login for my apps before running other images. Since my container uses Linux - scripts are saved with LF line endings. And the Docker output console is not showing any errors related to the script, only about my apps - they can't connect to the server because no such login exists.

The problem is that the shell script is not running and no login is being created. Thanks for your help in advance.

I was looking for the examples on the web, and here is what I came up with:

docker-compose.yml

version: '3.4'

services:
    mssql:
        image: mcr.microsoft.com/mssql/server:2019-latest
        environment:
            SA_PASSWORD: "3qqimIuTQEGqVCD!"
            ACCEPT_EULA: "Y"
            LOGIN: "MyLogin"
            PASSWORD: "3qqimIuTQEGqVCD!"

        ports:
            - "1433:1433"
        volumes:
            - ./DockerScripts/SQL/CreateLogin.sql:/CreateLogin.sql
            - ./DockerScripts/Shell/Entrypoint.sh:/Entrypoint.sh
        entrypoint:
            - ./Entrypoint.sh

    webapi:
        image: ${DOCKER_REGISTRY-}webapi
        build:
            context: .
            dockerfile: Source/Code/Web/WebApi/Dockerfile
        depends_on:
            - mssql

    maintenance:
        image: ${DOCKER_REGISTRY-}maintenance
        build:
            context: .
            dockerfile: Source/Code/Web/Maintenance/Dockerfile
        depends_on:
            - mssql

DockerScripts\Shell\Entrypoint.sh

#!/bin/bash

# Start SQL server
/opt/mssql/bin/sqlservr

# Wait for MSSQL server to start
export STATUS=1
i=0
while [[ $STATUS -ne 0 ]] && [[ $i -lt 30 ]]; do
    i=$i+1
    /opt/mssql-tools/bin/sqlcmd -t 1 -U sa -P $SA_PASSWORD -Q "select 1" >> /dev/null
    STATUS=$?
done

if [ $STATUS -ne 0 ]; then
    echo "Error: MS SQL Server took more than 30 seconds to start up."
    exit 1
fi

echo "MS SQL Server started successfully."

echo "Setting up server login."

/opt/mssql-tools/bin/sqlcmd  -U sa -P $SA_PASSWORD -S localhost -i CreateLogin.sql

DockerScripts\SQL\CreateLogin.sql

USE [master];
GO
CREATE LOGIN [$(LOGIN)] WITH PASSWORD=N'$(PASSWORD)', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF;
GO
ALTER SERVER ROLE [dbcreator] ADD MEMBER [$(LOGIN)];
GO

UPDATE

I removed a lot of stuff since it doesn't relate to the issue. So for now, the main problem persists - Entrypoint.sh just not being called on compose startup.

15
  • You can add a sleep 1 in the while loop waiting for sql server start Commented Nov 16, 2021 at 17:13
  • @PtitXav It is not solving my problem, but thank you anyway, I forgot to put sleep there. Commented Nov 16, 2021 at 17:46
  • maybe exec inside once and try to use sqlcmd manually to see what is the issue. Commented Nov 16, 2021 at 18:45
  • @TheFool, sorry, didn't really get what you mean. I understand your idea but didn't get how you want me to do that. Could you explain in more detail, please? Commented Nov 16, 2021 at 19:00
  • 1
    hard to say exactly because you have posted too much sutff imo. Its not very focused. But I am suggesting to you use exec on the running container using bash or sh as command and providing the -ti flags. Or that you use docker-compose run on the service to do the same. Once inside you can start debugging by using sqlcmd. Commented Nov 16, 2021 at 19:03

1 Answer 1

6

Okay, so finally I was able to solve this issue.

The problem was not that Entrypoint.sh was not called, but that all the commands after

# Start SQL server
/opt/mssql/bin/sqlservr

were just skipped.

I don't really know why, but I was searching the web more and more and in the end, I came up with this solution.

First of all, I separated the login creation logic into its own script file, this slightly improves readability:

DockerScripts/Shell/CreateLogin.sh

#!bin/bash

echo "Creating MS SQL Login."

for i in {1..50};
do

/opt/mssql-tools/bin/sqlcmd -U sa -P $SA_PASSWORD -S localhost -i CreateLogin.sql

    if [ $? -eq 0 ]
    then
        echo "MS SQL Login created."
        break
    else
        echo "..."
        sleep 1
    fi

done

Secondly - I simplified my Entrypoint.sh file to just a few rows:

#!bin/bash
/opt/mssql/bin/sqlservr | /opt/mssql/bin/permissions_check.sh | /Scripts/CreateLogin.sh

Let me explain what the commands above means:

  • /opt/mssql/bin/sqlservr - this start the server itself.
  • /opt/mssql/bin/permissions_check.sh - this is just the default entrypint file.
  • /Scripts/CreateLogin.sh - and this point us to the server login creation.

And of course, I mounted the new shell script to a volume.

That's it, literally months of struggling with this issue, and turned out it was very simple to solve.

Hope this would help somebody else. Thanks!

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you a lot for your answer. It helps me a lot! The only problem I have is that I keep incurring this error (my script is very similar to yours): WARNING: Connection error: The port number 1433/database is not valid.
@bellotto, Glad my answer helped you as well :) Maybe your 1433 port is already allocated, I don't really know, just a guess... But I have never seen such error before. Sorry, nothing I can do to help you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.