Search code examples
sqlshellasp.net-coredocker-composesqlcmd

Entrypoint script is not running from docker-compose file


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.


Solution

  • 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!