diff --git a/.gitignore b/.gitignore
index c96abe90..9f05de2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -340,7 +340,8 @@ ASALocalRun/
healthchecksdb
# Exclude tools folder
-src/MSBuild.Sdk.SqlProj/tools/
+src/MSBuild.Sdk.SqlProj/tools/*
+!src/MSBuild.Sdk.SqlProj/tools/container/
# Exclude generated Dacpac's
*.dacpac
diff --git a/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.props b/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.props
index 8e8635ee..4d6e7e7e 100644
--- a/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.props
+++ b/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.props
@@ -10,6 +10,7 @@
$(MSBuildAllProjects);$(MsBuildThisFileFullPath)
Sql150
.dacpac
+ 170.2.70
diff --git a/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.targets b/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.targets
index 0b0eb508..9b6b566e 100644
--- a/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.targets
+++ b/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.targets
@@ -310,4 +310,74 @@
+
+
+
+
+ $(MSBuildThisFileDirectory)..\tools\container\sqlpackage.Dockerfile
+
+
+ $([System.String]::Copy('$(MSBuildProjectName)').ToLowerInvariant().Trim())-publisher
+ $([System.String]::Copy('$(Configuration)').ToLowerInvariant().Trim())
+
+
+ $(SqlPackageVersion)
+
+
+ $(MSBuildProjectDirectory)\.container
+ $(MSBuildProjectName).dacpac
+ $(ContainerStagingDir)\$(ContainerDacpacName)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MSBuild.Sdk.SqlProj/tools/container/sqlpackage.Dockerfile b/src/MSBuild.Sdk.SqlProj/tools/container/sqlpackage.Dockerfile
new file mode 100644
index 00000000..ef7db16b
--- /dev/null
+++ b/src/MSBuild.Sdk.SqlProj/tools/container/sqlpackage.Dockerfile
@@ -0,0 +1,46 @@
+# Base image: ships with the SDK
+ARG BASE_IMAGE=mcr.microsoft.com/dotnet/runtime:8.0
+FROM ${BASE_IMAGE}
+ARG SQLPACKAGE_VERSION
+ARG DACPAC_NAME
+ENV DACPAC_NAME=${DACPAC_NAME}
+
+# Install sqlpackage dependencies and pull from NuGet
+# - Supports native (platform zip) and dotnet tool layouts
+# - Installs a stable wrapper in /usr/local/bin/sqlpackage
+RUN set -eux; \
+ apt-get update \
+ && apt-get install -y --no-install-recommends ca-certificates curl unzip \
+ && curl -L -o /tmp/sqlpackage.nupkg "https://globalcdn.nuget.org/packages/microsoft.sqlpackage.${SQLPACKAGE_VERSION}.nupkg" \
+ && mkdir -p /opt/sqlpackage-src /opt/sqlpackage \
+ && unzip -q /tmp/sqlpackage.nupkg -d /opt/sqlpackage-src \
+ && inner="$(find /opt/sqlpackage-src -type f -iname '*linux-x64*.zip' | head -n1 || true)" \
+ && if [ -n "$inner" ]; then \
+ unzip -q "$inner" -d /opt/sqlpackage; \
+ else \
+ cp -R /opt/sqlpackage-src/tools/*/any/* /opt/sqlpackage/; \
+ fi \
+ && printf '#!/usr/bin/env bash\nset -euo pipefail\nif [ -x /opt/sqlpackage/sqlpackage ]; then exec /opt/sqlpackage/sqlpackage "$@"; elif [ -f /opt/sqlpackage/sqlpackage.dll ]; then exec dotnet /opt/sqlpackage/sqlpackage.dll "$@"; else echo "sqlpackage not found"; exit 127; fi\n' > /usr/local/bin/sqlpackage \
+ && chmod +x /usr/local/bin/sqlpackage \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /opt/sqlpackage-src \
+ # Create entrypoint wrapper as root:
+ # - Bakes in `-Action:Publish` and `-SourceFile:/work/$DACPAC_NAME`
+ # - Forwards user-supplied args to sqlpackage
+ && install -d /usr/local/bin \
+ && printf '%s\n' \
+ '#!/usr/bin/env bash' \
+ 'set -euo pipefail' \
+ 'exec sqlpackage -Action:Publish -SourceFile:/work/"${DACPAC_NAME}" "$@"' \
+ | tee /usr/local/bin/docker-entrypoint >/dev/null \
+ && chmod +x /usr/local/bin/docker-entrypoint
+
+# Staging: the SDK copies all dacpacs into /work at build time
+WORKDIR /work
+COPY ./.container/*.dacpac /work/
+
+# Drop privileges to a non-root user
+RUN useradd -m runner
+USER runner
+
+# Exec-form ENTRYPOINT for proper signal handling and linter compliance
+ENTRYPOINT ["/usr/local/bin/docker-entrypoint"]