diff --git a/backend/Dockerfile b/backend/Dockerfile index a1d8da4..ac40562 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -20,15 +20,19 @@ FROM alpine:3.19 # Install ca-certificates (if needed) RUN apk add --no-cache ca-certificates +RUN apk add --no-cache netcat-openbsd # Set workdir WORKDIR /app +# Removed hosts entry addition (handled via docker-compose extra_hosts) # Copy the binary from the builder stage COPY --from=builder /app/main . # Expose the application port (default for the Go server) +COPY entrypoint.sh . +RUN chmod +x entrypoint.sh EXPOSE 8080 # Command to run the binary -CMD ["./main"] +CMD ["./entrypoint.sh"] diff --git a/backend/entrypoint.sh b/backend/entrypoint.sh new file mode 100644 index 0000000..dd00b47 --- /dev/null +++ b/backend/entrypoint.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env sh + +# entrypoint.sh – wait for the SQL Server container to become ready +# before starting the Go backend binary. + +set -e + +# Default environment variables (can be overridden in docker-compose) +: "${DB_SERVER:=sql}" +: "${DB_USER:=sa}" +: "${DB_PASSWORD:=Ou812@12!@}" + +# Wait until netcat can successfully connect to the SQL Server port +while ! nc -z "$DB_SERVER" 1433; do + echo "⏳ Waiting for SQL Server at $DB_SERVER:1433..." + sleep 1 +done +# Add a short pause after the port is open to let SQL Server finish startup +sleep 5 +# Add a short pause after the port is open to let SQL Server finish startup +sleep 2 + +echo "✅ SQL Server is ready. Starting backend." +exec ./main diff --git a/backend/main.go b/backend/main.go index 319295a..0d3bb2a 100644 --- a/backend/main.go +++ b/backend/main.go @@ -41,17 +41,9 @@ func main() { // ----------------------------------------------------------------- var newCustID int insertCustSQL := ` -DECLARE @NewID int; -EXEC dbo.sp_InsertCustomer - @CustomerName = @name, - @AddressLine1 = @addr1, - @AddressLine2 = @addr2, - @City = @city, - @State = @state, - @ZipCode = @zip, - @Country = @country, - @NewCustomerID = @NewID OUTPUT; -SELECT @NewID; +INSERT INTO dbo.Customers (CustomerName, AddressLine1, AddressLine2, City, State, ZipCode, Country) +VALUES (@name, @addr1, @addr2, @city, @state, @zip, @country); +SELECT SCOPE_IDENTITY() AS NewID; ` row := db.QueryRow(insertCustSQL, sql.Named("name", "Acme Corp"), @@ -72,14 +64,9 @@ SELECT @NewID; // ----------------------------------------------------------------- var newContactID int insertContactSQL := ` -DECLARE @NewContactID int; -EXEC dbo.sp_InsertContact - @CustomerID = @custID, - @ContactTypeID = @typeID, - @ContactValue = @value, - @IsPrimary = @primary, - @NewContactID = @NewContactID OUTPUT; -SELECT @NewContactID; +INSERT INTO dbo.Contacts (CustomerID, ContactTypeID, ContactValue, IsPrimary) +VALUES (@custID, @typeID, @value, @primary); +SELECT SCOPE_IDENTITY() AS NewContactID; ` // Assume ContactTypeID 1 = Phone (created by init.sql) row = db.QueryRow(insertContactSQL, diff --git a/db/Dockerfile b/db/Dockerfile new file mode 100644 index 0000000..3143501 --- /dev/null +++ b/db/Dockerfile @@ -0,0 +1,27 @@ +# Dockerfile for DB init service + +FROM mcr.microsoft.com/mssql/server:2022-latest + +# Set SQL Server environment variables +ENV SA_PASSWORD=Ou812@12!@ \ + ACCEPT_EULA=Y + +# Set working directory inside the container +WORKDIR /usr/src/app + +# Copy the initialization script and SQL file into the image +COPY --chmod=0755 init.sh . +COPY init.sql . + +# Make the script executable + + +# Start SQL Server, wait until it is ready, then run the init script +CMD /opt/mssql/bin/sqlservr & \ + /bin/bash -c "\ + until /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P $$SA_PASSWORD -Q \"SELECT 1\" >/dev/null 2>&1; do \ + sleep 1; \ + done && \ + ./init.sh && \ + tail -f /dev/null \ + " diff --git a/db/init.sh b/db/init.sh new file mode 100644 index 0000000..9239628 --- /dev/null +++ b/db/init.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# init.sh - Initialize the SQL Server database with the schema and sample data. +# This script is intended to be run inside the SQL Server container (or from the host +# with sqlcmd reachable). It executes the init.sql script located in the same +# directory. + +set -euo pipefail + +# Default connection settings – can be overridden via environment variables +: "${DB_SERVER:=localhost}" +: "${DB_USER:=sa}" +: "${DB_PASSWORD:=YourStrong!Passw0rd}" +: "${DB_NAME:=CustomerDB}" +: "${SQLCMD_PATH:=sqlcmd}" # Path to the sqlcmd executable + +# Path to the init script (relative to this script's location) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +INIT_SQL="${SCRIPT_DIR}/init.sql" + +if [[ ! -f "${INIT_SQL}" ]]; then + echo "❌ init.sql not found at ${INIT_SQL}" + exit 1 +fi + +echo "🚀 Running database initialization..." +"${SQLCMD_PATH}" -S "${DB_SERVER}" -U "${DB_USER}" -P "${DB_PASSWORD}" -d "master" -Q "IF DB_ID(N'${DB_NAME}') IS NULL CREATE DATABASE ${DB_NAME};" + +# Run the init script against the newly created database +"${SQLCMD_PATH}" -S "${DB_SERVER}" -U "${DB_USER}" -P "${DB_PASSWORD}" -d "${DB_NAME}" -i "${INIT_SQL}" + +echo "✅ Database ${DB_NAME} initialized successfully." diff --git a/docker-compose.yml b/docker-compose.yml index 6a86f77..02ef477 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,39 @@ services: + sql: + image: mcr.microsoft.com/mssql/server:2022-latest + container_name: sql + environment: + - ACCEPT_EULA=Y + - SA_PASSWORD=Ou812@12!@ + ports: + - "1433:1433" backend: build: context: ./backend dockerfile: Dockerfile + depends_on: + - sql container_name: backend environment: - - DB_SERVER=homelab.local + - DB_SERVER=sql - DB_USER=sa - DB_PASSWORD=Ou812@12!@ - DB_NAME=CustomerDB ports: - "8080:8080" command: ./main + extra_hosts: + - "homelab.local:192.168.1.129" + + init-db: + build: + context: ./db + dockerfile: Dockerfile + container_name: init-db + depends_on: + - sql + environment: + - DB_SERVER=sql + - DB_USER=sa + - DB_PASSWORD=Ou812@12!@ + - DB_NAME=CustomerDB