sql-serverlinuxdockerdockerfilesqlpackage

How to locate Sqlpackage tool after global installation in Docker container?


I'm attempting (relatively inexperienced) to write a Dockerfile that publishes a dacpac to a linux container before firing up sqlserver, but building the Dockerfile always results in the following: /bin/sh: 1: /home/mssql/localtools/sqlpackage: not found

below is a snippet of my Dockerfile (omitted some boilerplate for brevity)

FROM mcr.microsoft.com/mssql/server:2022-latest AS base

build/publish etc
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build

# https://learn.microsoft.com/en-us/sql/tools/sqlpackage/sqlpackage-download?WT.mc_id=DT-MVP-4025156&view=sql-server-ver16
RUN dotnet tool install --tool-path ~/localtools microsoft.sqlpackage
#RUN dotnet tool install -g microsoft.sqlpackage

ARG CONFIGURATION=Release
WORKDIR /src
COPY . .
RUN dotnet build "SomeName.Database.sqlproj" -c $CONFIGURATION -o /db/build -v diag

FROM base AS final
COPY --from=build "/db/build/SomeName.Database.dacpac" "/tmp/SomeName.Database.dacpac"

# Launch SQL Server, confirm startup is complete, deploy the DACPAC, then terminate SQL Server.
# See https://stackoverflow.com/a/51589787/488695
RUN ( /opt/mssql/bin/sqlservr & ) | grep -q "Service Broker manager has started" && ( echo "SQLServer started" && sleep 10s ) || ( echo "SQLSERVER failed to start" && exit )

RUN ~/localtools/sqlpackage \
    /Action:Publish \
    /TargetServerName:. \
    /TargetDatabaseName:SomeNameDB \
    /TargetUser:sa \
    /TargetPassword:$MSSQL_SA_PASSWORD \
    /SourceFile:/tmp/SomeName.Database.dacpac \
    && pkill sqlservr

I've tried specifying the local tools path via dotnet tool install --tool-path ~/localtools microsoft.sqlpackage but to no avail

UPDATE

The file now looks as follows but now getting #0 21.67 SQLServer started #0 31.68 /bin/sh: 1: /tmp/sqlpackage/sqlpackage: Permission denied

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS dacpac-build
ARG CONFIGURATION=Release
WORKDIR /dacpac
COPY . .
RUN dotnet build "SomeName.Database.sqlproj" -c $CONFIGURATION -o /build -v diag
RUN dotnet tool install --tool-path /localtools microsoft.sqlpackage

FROM sql-server AS final
COPY --from=dacpac-build /localtools /tmp/sqlpackage/sqlpackage
COPY --from=dacpac-build "/build/SomeName.Database.dacpac" /tmp/SomeName.Database.dacpac

RUN ( /opt/mssql/bin/sqlservr & ) | grep -q "Service Broker manager has started" && ( echo "SQLServer started" && sleep 10s ) || ( echo "SQLSERVER failed to start" && exit ) && \
    /tmp/sqlpackage/sqlpackage \
    /Action:Publish \
    /TargetServerName:. \
    /TargetDatabaseName:SomeNameDB \
    /TargetUser:sa \
    /TargetPassword:$MSSQL_SA_PASSWORD \
    /SourceFile:/tmp/SomeName.Database.dacpac \
    && pkill sqlservr

Solution

  • You need to understand the problem step by step. Follow the code and explantion given in this blog by Ken Muse. SqlPackage needs to be installed separately.

    As quoted in blog:

    Switching to root is required when running apt-get to install packages, adjusting the ownership of folders, or performing other operations which required elevated privileges. In this case, the Dockerfile is installing dependencies that are required for sqlpackage

    code from blog:

    FROM mcr.microsoft.com/mssql/server:2019-latest
    
    # Elevate to root to install required packages
    USER root
    RUN apt-get update 
    && apt-get install unzip libunwind8 libicu55 -y
    
    # Install SQLPackage for Linux and make it executable
    RUN wget -progress=bar:force -q -O sqlpackage.zip https://go.microsoft.com/fwlink/?linkid=2113331 
    && unzip -qq sqlpackage.zip -d /opt/sqlpackage 
    && chmod +x /opt/sqlpackage/sqlpackage 
    && chown -R mssql /opt/sqlpackage 
    && mkdir /tmp/db 
    && chown -R mssql /tmp/db