Vinícius Beloni
Posted on June 3, 2022
"Vocês não me escolheram, mas eu os escolhi para irem e darem fruto, fruto que permaneça, a fim de que o Pai lhes conceda o que pedirem em meu nome.
Este é o meu mandamento: amem-se uns aos outros".
"Se o mundo os odeia, tenham em mente que antes odiou a mim."
- João 15.16-18
Quem nunca precisou subir o próprio banco de dados para testar as alterações feitas numas tabelas? Melhor ainda manter isso versionado e rodando em container. Hoje vou compartilhar com vocês como fazer isso.
Sumário
Criando o projeto
Vamos iniciar criando um projeto para o DB, esse projeto será responsável por verificar se seu banco está tudo certo. Mas antes devemos instalar o template MSBUild.Sdk.Sqlproj:
> dotnet new --install MSBuild.Sdk.SqlProj.Templates
> dotnet new sqlproj -n MyDb -o my-db/src -s Sql130
> cd my-db
> dotnet sln -n MyDb
> dotnet sln add src #se exitir um .sqlproj pode adicionar também
Perceba que foi criado um arquivo chamado MyDb.csproj
, ele será responsável por gerenciar o Pre e PostDeploy e "compilar" todo o seu banco de dados. Vamos criar umas tabelas, depois voltaremos para mexer neste arquivo.
> mkdir src/Schemas
> mkdir src/Tables
> 'CREATE SCHEMA [Bible]' > src/Schemas/Bible.sql
> 'CREATE TABLE [Bible].[Verse](
>> [VerseId] INT,
>> [Content] VARCHAR(MAX)
>> )
>> ' > src/Tables/Verse.sql
> dotnet build
Ao fazer isso, será concluído o build com sucesso. Ao criar um script incorreto, será lançado o erro no seu terminal:
> 'CREATE SCHEMA [Pimba] errrrou' > src/Schemas/Pimba.sql
> dotnet build
EXEC : error SQL46010: Incorrect syntax near errrrou. [...]
Agora vamos criar o script de PostDeploy
e adaptar o arquivo MyDb.csproj
para buscar as Seeds
:
> mkdir src/PostDeploy
> '' > src/PostDeploy/SeedTables.sql
SeedTables.sql
:
PRINT 'Merging [Bible].[Verse]'
MERGE INTO [Bible].[Verse] AS TARGET
USING
(
VALUES
(1, 'Joao 15.16'),
(2, 'Joao 15.17'),
(3, 'Joao 15.18')
)
AS SOURCE ([VerseId], [Content])
ON TARGET.[VerseId] = SOURCE.[VerseId]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([VerseId], [Content])
VALUES ([VerseId], [Content])
WHEN MATCHED THEN
UPDATE SET
TARGET.[Content] = SOURCE.[Content];
Adaptando o MyDb.csproj
:
<Project Sdk="MSBuild.Sdk.SqlProj/2.0.0">
<!-- [...] -->
<!-- Adicione este bloco para utilizar o PostDeploy -->
<ItemGroup>
<Content Include=".\**\*.sql" />
<!--Remove all Seed files from the build, but add them as post-deploy https://github.com/rr-wfm/MSBuild.Sdk.SqlProj/issues/103 -->
<Content Remove="..\**\Seed\*.sql" />
<Content Remove=".\PostDeploy\SeedTables.sql" />
<PostDeploy Include=".\PostDeploy\SeedTables.sql" />
</ItemGroup>
</Project>
Vamos testar:
> dotnet build
[...]
Build succeeded.
0 Warning(s)
0 Error(s)
Dockerfile
Agora com suas tabelas funcionando, vamos rodar em um container:
Dockerfile
(UTF-8):
ARG DBNAME=MyDb
ARG PASSWORD=C0mposed
FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY src .
RUN dotnet build ./MyDb.csproj -c Release -o /app/build
FROM mcr.microsoft.com/mssql/server:2017-latest AS final
# Install Unzip
RUN apt-get update \
&& apt-get install unzip -y
# Install SQLPackage for Linux and make it executable
RUN wget -progress=bar:force -q -O sqlpackage.zip https://go.microsoft.com/fwlink/?linkid=2165213 \
&& unzip -qq sqlpackage.zip -d /opt/sqlpackage \
&& chmod +x /opt/sqlpackage/sqlpackage
# Add the DACPAC to the image
COPY --from=build /app/build/MyDb.dacpac /tmp/db.dacpac
# Configure external build arguments to allow configurability.
ARG DBNAME
ARG PASSWORD
# Configure the required environmental variables
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=$PASSWORD
# 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" \
&& /opt/sqlpackage/sqlpackage /a:Publish /tsn:. /tdn:$DBNAME /tu:sa /tp:$SA_PASSWORD /sf:/tmp/db.dacpac \
&& rm /tmp/db.dacpac \
&& pkill sqlservr
Resumidamente estamos criando o nome da instância do banco de dados e fazendo o deploy do DACPAC que geramos. Para mais detalhes os links estarão no final do artigo.
Agora vamos ver se está criando o container corretamente:
> docker build -t my-db .
[+] Building 57.5s (15/15) FINISHED [...]
Rodando
Com tudo preparado, só falta executar o container:
> docker run --name testando -p 1433:1433 my-db
SQL Server 2019 will run as non-root by default.
This container is running as user root.
Your master database file is owned by root. [...]
Para conectar utilize as seguintes informações(SQL Login):
user: sa
pwd: C0mposed
server: localhost, 1433
Os próximos passos serão versionar e configurar o Github Actions.
Versionando
Crie o repositório normalmente, eu criarei no Github:
git init
git remote add origin https://github.com/confianodev/my-db-container
git branch -M main
git fetch
git pull origin main
git add .
git commit -m ":tada: a better commit message"
git push --set-upstream origin main
git checkout -b dev
Dessa forma, qualquer pessoa que for evoluir as tabelas, views, schemas, indexes, etc. Devem conseguir versionar, compilar e executar o banco de dados.
Github Actions
Agora precisamos automatizar isso para que ninguém fique refém dos testes locais. Lembre-se de criar a secret PACKAGES_TOKEN na organização ou no próprio repositório.
mkdir .github/workflows
'' > build-homolog.yml
'' > release-homolog.yml
'' > rollback-homolog.yml
Conteúdo dos arquivos:
https://github.com/confianodev/my-db-container/blob/main/.github/workflows
Lembre-se de trocar o meu usuário(confianodev) pelo seu.
Feito isso, basta fazer o commit e seu container está pronto para ser compartilhado!
git add .
git commit -m ":wrench: github actions"
git push --set-upstream origin dev
E é isso pessoal, a ideia não é fazer deploy em produção, mas sim facilitar os testes e evitar perder tempo com scripts no banco de homologação. Espero que tenha ajudado.
Fiquem com a graça e paz do nosso Senhor Jesus Cristo!
Fontes
https://github.com/rr-wfm/MSBuild.Sdk.SqlProj
https://itnext.io/how-to-build-and-run-a-sql-container-using-a-dacpac-file-c7b0d30f6255
Posted on June 3, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.