From df8f43ba5a60b6cf4087bede7720625050efdbb3 Mon Sep 17 00:00:00 2001 From: Liam Pietralla Date: Wed, 12 Feb 2025 10:50:06 +1100 Subject: [PATCH] added docker items for db --- .vitepress/config.mts | 2 + docs/docker/index.md | 4 +- docs/docker/local-db-mssql.md | 174 ++++++++++++++++++++++++++++++++++ docs/docker/local-db-pg.md | 89 +++++++++++++++++ 4 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 docs/docker/local-db-mssql.md create mode 100644 docs/docker/local-db-pg.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index bb0bf12..87af42a 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -71,6 +71,8 @@ export default defineConfig({ collapsed: true, items: [ { text: 'Docker Exec', link: '/docker/exec-into-container' }, + { text: 'Local DB (MSSQL)', link: '/docker/local-db-mssql' }, + { text: 'Local DB (PostgreSQL)', link: '/docker/local-db-pg' }, ] }, { diff --git a/docs/docker/index.md b/docs/docker/index.md index 0c1f35e..fc05300 100644 --- a/docs/docker/index.md +++ b/docs/docker/index.md @@ -1,3 +1,5 @@ # Docker Snippets and Musings -#### [Exec Into Container](./exec-into-container.md) \ No newline at end of file +#### [Exec Into Container](./exec-into-container.md) +#### [Local Database With Scripts (MSSQL)](./local-db-mssql.md) +#### [Local Database With Scripts (PostgreSQL)](./local-db-pg.md) \ No newline at end of file diff --git a/docs/docker/local-db-mssql.md b/docs/docker/local-db-mssql.md new file mode 100644 index 0000000..3761762 --- /dev/null +++ b/docs/docker/local-db-mssql.md @@ -0,0 +1,174 @@ +# Local Database With Scripts (MSSQL) + +When developing apps locally it can be really useful to have a dockerised database unique to the application. + +Often rather than just running a pre-built image, you'll want to run a database with some initial data, tables, or a schema. + +For this purpose we can create our own image that extends the base image and adds our own scripts. + +## Setup + +For most applications the directory structure will look something like this: + +``` +database/ + Dockerfile + scripts/ + 01-create-database.sql + 02-create-tables.sql + 03-seed-data.sql +development/ + compose.yml +src/ + ... +tests/ + ... +``` + +### Dockerfile + +Create a dockerfile in the `database/` directory: + +::: code-group + +```dockerfile [Dockerfile] +FROM mcr.microsoft.com/mssql/server:2022-latest + +# Set the SQL Server environment variables +ENV ACCEPT_EULA="Y" +ENV SA_PASSWORD="Password123" + +# Setup port +EXPOSE 1433 + +# Create a temp directory +RUN mkdir -p /tmp/init + +# Copy all the scripts into the container +COPY ./scripts/ /tmp/init + +ENTRYPOINT [ "/tmp/init/entrypoint.sh" ] +``` + +::: + +::: danger + +As this is a local development database, we're using the `sa` user with a simple password. **Do not use this in production**. + +::: + +### Scripts + +Create the scripts in the `database/scripts/` directory: + +::: code-group + +```bash [entrypoint.sh] +#!/bin/bash + +# Run the sql scripts and start sql server +/tmp/init/run-scripts.sh & /opt/mssql/bin/sqlservr +``` + +::: + +::: code-group + +```bash [run-scripts.sh] +#!/bin/bash + +# Wait for the mssql database to be ready +while ! /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -C -Q "SELECT 1" > /dev/null; do + sleep 1 +done + +echo "SQL Server is up and running" + +# Check if the setup has already been executed +SETUP_DONE=$(/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -Q "IF EXISTS (SELECT 1 FROM master.sys.tables WHERE name = 'setup_marker' AND schema_id = SCHEMA_ID('dbo')) SELECT 1 ELSE SELECT 0" -h -1 -W -r 1 | grep -oE '^[0-9]+' | tr -d '[:space:]') + +if [[ "$SETUP_DONE" == "1" ]]; then + echo "Setup has already been completed. Skipping initialization." + exit 0 +else + echo "Setup has not been completed. Running initialization." +fi + +# Run all scripts in the scripts folder +for entry in /tmp/init/*.sql; +do + echo "Running script $entry" + /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -C -i $entry +done + +# Create a marker table to indicate setup completion +/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -C -Q "CREATE TABLE master.dbo.setup_marker (id INT PRIMARY KEY IDENTITY, created_at DATETIME DEFAULT GETDATE())" + +echo "All scripts have been run" +``` + +::: + +The above script waits for the database to be ready, then checks if the setup has already run. If not it will run all the scripts in the `scripts/` directory and create a marker table to indicate that the setup has been completed. + +Create any scripts that you need in the `database/scripts/` directory. + +::: tip + +See below for an example of the scripts you might want to run. + +::: + +::: code-group + +```sql [01-create-database.sql] +CREATE DATABASE MyDatabase +``` + +```sql [02-create-tables.sql] +USE MyDatabase + +CREATE TABLE MyTable ( + id INT PRIMARY KEY, + name NVARCHAR(50) +) +``` + +```sql [03-seed-data.sql] +USE MyDatabase + +INSERT INTO MyTable (id, name) VALUES (1, 'Alice') +INSERT INTO MyTable (id, name) VALUES (2, 'Bob') +``` + +```sql [04-create-user.sql] +USE MyDatabase + +CREATE LOGIN MyUser WITH PASSWORD = 'MyPassword' +CREATE USER MyUser FOR LOGIN MyUser +ALTER ROLE db_owner ADD MEMBER MyUser; +``` + +::: + +## Compose + +Lastly we need to create a `docker-compose.yml` file in the `development/` directory: + +::: code-group + +```yaml [compose.yml] +services: + db: + build: + context: ../database + dockerfile: Dockerfile + volumes: + - db-data:/var/opt/mssql + ports: + - "1433:1433" + +volumes: + db-data: +``` \ No newline at end of file diff --git a/docs/docker/local-db-pg.md b/docs/docker/local-db-pg.md new file mode 100644 index 0000000..21ff7b5 --- /dev/null +++ b/docs/docker/local-db-pg.md @@ -0,0 +1,89 @@ +# Local Database With Scripts (PostgreSQL) + +When developing apps locally it can be really useful to have a dockerised database unique to the application. + +Often rather than just running a pre-built image, you'll want to run a database with some initial data, tables, or a schema. + +For this purpose we can create our own image that extends the base image and adds our own scripts. + +## Setup + +For most applications the directory structure will look something like this: + +``` +database/ + Dockerfile + scripts/ + 01-create-tables.sql +development/ + compose.yml +src/ + ... +tests/ + ... +``` + +### Dockerfile + +Create a dockerfile in the `database/` directory: + +::: code-group + +```dockerfile [Dockerfile] +FROM postgres:17 + +# Setup the postgres environment variables +ENV POSTGRES_USER=myuser +ENV POSTGRES_PASSWORD=mypassword +ENV POSTGRES_DB=mydatabase + +# Setup port +EXPOSE 5432 + +# Copy all the scripts into the container +COPY ./scripts /docker-entrypoint-initdb.d/ +``` + +::: + +::: danger + +As this is a local development database, we're using the a simple username and password. **Do not use this in production**. + +::: + +### Scripts + +Create any scripts you need in the `database/scripts/` directory. PostgreSQL will run these scripts in alphabetical order against the database specified in the `POSTGRES_DB` environment variable. + +::: code-group + +```sql [01-create-tables.sql] +CREATE TABLE MyTable ( + Id INT NOT NULL PRIMARY KEY, + Name VARCHAR(50) NOT NULL +); +``` + +::: + +## Compose + +Lastly we need to create a `docker-compose.yml` file in the `development/` directory: + +::: code-group + +```yaml [compose.yml] +services: + db: + build: + context: ../database + dockerfile: Dockerfile + volumes: + - db-data:/var/lib/postgresql/data + ports: + - "5432:5432" + +volumes: + db-data: +``` \ No newline at end of file