{"id":401,"date":"2025-02-04T08:00:00","date_gmt":"2025-02-04T13:00:00","guid":{"rendered":"https:\/\/www.sqltabletalk.com\/?p=401"},"modified":"2025-02-03T21:57:16","modified_gmt":"2025-02-04T02:57:16","slug":"sql-server-always-on-docker-setup","status":"publish","type":"post","link":"https:\/\/www.sqltabletalk.com\/?p=401","title":{"rendered":"How to Set Up a SQL Server Always On Environment Using Docker Containers"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>For enterprise SQL Server DBAs, high availability is essential for maintaining seamless database operations\u2014particularly in scenarios involving Change Data Capture (CDC) or other mission-critical functionalities. Docker containers can streamline the setup and management of development or testing environments for Always On Availability Groups (AOAG). By bundling configuration files, scripts, and dependencies into containers, teams gain a reproducible, portable, and efficient deployment mechanism.<\/p>\n<p>This guide explains how to build an Always On environment inside Docker containers using <strong>Docker Desktop<\/strong>, <strong>Docker Compose<\/strong>, and a series of setup scripts. It walks through the creation of two containers (primary and secondary) configured in a clusterless Always On Availability Group scenario.<\/p>\n<h3>Prerequisites<\/h3>\n<p>Before proceeding, ensure you have the following:<\/p>\n<ol>\n<li><strong>Docker Desktop<\/strong> (running with <strong>WSL 2<\/strong> on Windows)<br \/>\n<a href=\"https:\/\/docs.docker.com\/desktop\/install\/windows-install\/\" target=\"_blank\" rel=\"noopener\">Install Docker Desktop on Windows | Docker Docs<\/a><\/li>\n<li><strong>Docker Compose<\/strong><br \/>\n<a href=\"https:\/\/docs.docker.com\/compose\/install\/\" target=\"_blank\" rel=\"noopener\">Install Compose standalone | Docker Docs<\/a><\/li>\n<li><strong>Basic Familiarity with SQL Server<\/strong> and <strong>Availability Groups<\/strong><br \/>\nWhile this tutorial covers essential T-SQL scripts, some background knowledge of Always On concepts is recommended.<\/li>\n<\/ol>\n<h3>Overview of the Required Files<\/h3>\n<p>Your working directory (e.g., <code>AlwaysOnDockerExample\/<\/code>) will include the following files and folders:<\/p>\n<pre><code>AlwaysOnDockerExample\/\n\u251c\u2500\u2500 Dockerfile\n\u251c\u2500\u2500 docker-compose.yml\n\u251c\u2500\u2500 entrypoint.sh\n\u251c\u2500\u2500 dbinit.sh\n\u2514\u2500\u2500 sql_scripts\/\n    \u251c\u2500\u2500 aoag_primary.sql\n    \u2514\u2500\u2500 aoag_secondary.sql<\/code><\/pre>\n<p><strong>Dockerfile<\/strong>: Defines the base image (SQL Server on Linux), installs or configures required software, and sets up environment variables. It also specifies which scripts to copy into the container and the command to run when the container starts.<\/p>\n<p><strong>docker-compose.yml<\/strong>: Orchestrates multiple containers. It describes how your containers should be built, connected, and what environment variables are passed in.<\/p>\n<p><strong>entrypoint.sh<\/strong>: Runs at container startup to finalize any dynamic configuration. Common tasks include setting backup directories, configuring environment variables, or making last-minute updates.<\/p>\n<p><strong>dbinit.sh<\/strong>: Performs the initial database setup. For example, it can run T-SQL scripts to create or update schemas, seed data, or configure high availability settings.<\/p>\n<p><strong>aoag_primary.sql<\/strong> &amp; <strong>aoag_secondary.sql<\/strong>: SQL scripts responsible for creating and configuring the Always On Availability Group components. One script creates the primary database and configures the primary node, while the other configures the secondary replica.<\/p>\n<h3>Step-by-Step Implementation<\/h3>\n<p>Below are the detailed steps to create and run two SQL Server containers that form a clusterless Always On Availability Group.<\/p>\n<h4>1. Create the Dockerfile<\/h4>\n<p>Create a <code>Dockerfile<\/code> (e.g., in a <code>sql\/<\/code> directory) with the following content:<\/p>\n<pre><code>FROM mcr.microsoft.com\/mssql\/rhel\/server:2019:latest\n\nCOPY . \/\n\nUSER root\n\nRUN chmod +x db-init.sh\nRUN \/opt\/mssql\/bin\/mssql-conf set sqlagent.enabled true\nRUN \/opt\/mssql\/bin\/mssql-conf set hadr.hadrenabled 1\nRUN \/opt\/mssql\/bin\/mssql-conf set memory.memorylimitmb 2048\n\nCMD \/bin\/bash .\/entrypoint.sh<\/code><\/pre>\n<p><strong>Key Points:<\/strong><\/p>\n<ul>\n<li><strong>Base Image<\/strong>: Uses <code>mcr.microsoft.com\/mssql\/rhel\/server:2019:latest<\/code> for SQL Server on RHEL.<\/li>\n<li><strong>Copying Files<\/strong>: The <code>COPY . \/<\/code> command transfers your scripts and configuration files from the local directory to the container\u2019s root directory.<\/li>\n<li><strong>Script Permissions<\/strong>: <code>RUN chmod +x db-init.sh<\/code> ensures the script is executable.<\/li>\n<li><strong>SQL Server Configuration<\/strong>: <code>mssql-conf<\/code> commands enable SQL Agent, Always On HADR, and set memory limits.<\/li>\n<li><strong>Container Startup<\/strong>: The <code>CMD<\/code> instruction runs <code>entrypoint.sh<\/code> whenever the container starts.<\/li>\n<\/ul>\n<h4>2. Create the docker-compose.yml<\/h4>\n<p>In your main project directory, create a <code>docker-compose.yml<\/code> that references the <code>Dockerfile<\/code> above (assumed to be in a <code>sql\/<\/code> subfolder). The following example defines two containers\u2014<code>db1<\/code> (primary) and <code>db2<\/code> (secondary):<\/p>\n<pre><code>version: \"3\"\n\nservices:\n  db1:\n    build: .\/sql\n    environment:\n      SA_PASSWORD: \"\"        # Replace with a strong password\n      ACCEPT_EULA: \"Y\"\n      MSSQL_AGENT_ENABLED: \"true\"\n      INIT_SCRIPT: \"aoag_primary.sql\"\n      INIT_WAIT: 30\n    ports:\n      - \"2500:1433\"\n    container_name: db1\n    hostname: db1\n    volumes:\n      - mssql-server-shared:\/var\/opt\/mssql\/shared\n      - mssql-server-backup:\/var\/opt\/mssql\/backup\n    networks:\n      - sqlaoag\n\n  db2:\n    build: .\/sql\n    environment:\n      SA_PASSWORD: \"\"        # Replace with a strong password\n      ACCEPT_EULA: \"Y\"\n      MSSQL_AGENT_ENABLED: \"true\"\n      INIT_SCRIPT: \"aoag_secondary.sql\"\n      INIT_WAIT: 50\n    ports:\n      - \"2600:1433\"\n    container_name: db2\n    hostname: db2\n    volumes:\n      - mssql-server-shared:\/var\/opt\/mssql\/shared\n      - mssql-server-backup:\/var\/opt\/mssql\/backup\n    networks:\n      - sqlaoag\n\nvolumes:\n  mssql-server-shared:\n  mssql-server-backup:\n\nnetworks:\n  sqlaoag:<\/code><\/pre>\n<p><strong>Key Points:<\/strong><\/p>\n<ul>\n<li><strong>Services (<code>db1<\/code> and <code>db2<\/code>)<\/strong>: Each service is a SQL Server instance configured for Always On.<\/li>\n<li><strong>Environment Variables<\/strong>:\n<ul>\n<li><code>SA_PASSWORD<\/code>, <code>ACCEPT_EULA<\/code>, and <code>MSSQL_AGENT_ENABLED<\/code> are required for Microsoft\u2019s SQL Server image.<\/li>\n<li><code>INIT_SCRIPT<\/code> specifies which SQL file to execute (primary or secondary).<\/li>\n<li><code>INIT_WAIT<\/code> enforces a startup delay, ensuring SQL Server is ready before running the setup scripts.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Ports<\/strong>: Maps the container\u2019s port <code>1433<\/code> to host ports <code>2500<\/code> and <code>2600<\/code>. Connect to <code>localhost,2500<\/code> or <code>localhost,2600<\/code> in SSMS or Azure Data Studio.<\/li>\n<li><strong>Volumes<\/strong>:\n<ul>\n<li><code>mssql-server-shared<\/code> is used to share a certificate file between containers.<\/li>\n<li><code>mssql-server-backup<\/code> provides a shared location for backups.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Networks<\/strong>: Assigns both containers to the <code>sqlaoag<\/code> network for internal communication.<\/li>\n<\/ul>\n<h4>3. Create the Entry Script (<code>entrypoint.sh<\/code>)<\/h4>\n<p>Place the following in <code>entrypoint.sh<\/code>:<\/p>\n<pre><code>#!\/bin\/bash\n\n# Set the default backup directory\n\/opt\/mssql\/bin\/mssql-conf set filelocation.defaultbackupdir \/var\/opt\/mssql\/backup &amp;\n\n# Run the db-init.sh script in the background\nsh .\/db-init.sh &amp;\n\n# Start the SQL Server process (keeps container running)\n\/opt\/mssql\/bin\/sqlservr<\/code><\/pre>\n<p><strong>Key Points:<\/strong><\/p>\n<ul>\n<li><strong>Backup Directory<\/strong>: Configured after the volume is mounted, since the directory doesn\u2019t exist at build time.<\/li>\n<li><strong>dbinit.sh Execution<\/strong>: Invokes the database initialization script.<\/li>\n<li><strong>SQL Server Service<\/strong>: Launches SQL Server and keeps the container alive.<\/li>\n<\/ul>\n<h4>4. Create the Database Initialization Script (<code>dbinit.sh<\/code>)<\/h4>\n<p>In the same folder as the <code>entrypoint.sh<\/code>, add <code>dbinit.sh<\/code>:<\/p>\n<pre><code>#!\/bin\/bash\n\n# Wait for SQL Server to fully start\nSLEEP_TIME=$INIT_WAIT\nSQL_SCRIPT=$INIT_SCRIPT\n\necho \"Sleeping for ${SLEEP_TIME} seconds...\"\nsleep ${SLEEP_TIME}\n\necho \"####### Running setup script ${SQL_SCRIPT} #######\"\n\n# If this is the primary node, remove any existing certificate files\nif [ \"$SQL_SCRIPT\" = \"aoag_primary.sql\" ]\nthen\n  rm \/var\/opt\/mssql\/shared\/aoag_certificate.key 2&gt; \/dev\/null\n  rm \/var\/opt\/mssql\/shared\/aoag_certificate.cert 2&gt; \/dev\/null\nfi\n\n# Execute the SQL script using SQLCMD\n\/opt\/mssql-tools\/bin\/sqlcmd -S localhost -U sa -P \"$SA_PASSWORD\" -d master -i \"$SQL_SCRIPT\"\n\necho \"####### AOAG script execution completed #######\"<\/code><\/pre>\n<p><strong>Key Points:<\/strong><\/p>\n<ul>\n<li><strong>Startup Delay<\/strong>: The script waits a specified number of seconds (<code>INIT_WAIT<\/code>) to ensure the SQL Server process is listening.<\/li>\n<li><strong>Certificate Cleanup<\/strong>: If the script is for the primary node, it clears any existing certificate files.<\/li>\n<li><strong>SQLCMD<\/strong>: Executes the respective T-SQL script (<code>aoag_primary.sql<\/code> or <code>aoag_secondary.sql<\/code>) to configure AOAG.<\/li>\n<\/ul>\n<h4>5. Create the T-SQL Scripts (<code>aoag_primary.sql<\/code> and <code>aoag_secondary.sql<\/code>)<\/h4>\n<p>Store these in a <code>sql_scripts\/<\/code> directory. Below is an example of the <strong>Primary<\/strong> script, followed by the <strong>Secondary<\/strong> script. They configure a sample <code>Sales<\/code> database and set up an HADR endpoint and availability group named <code>AG1<\/code>.<\/p>\n<details>\n<summary><strong>aoag_primary.sql<\/strong><\/summary>\n<pre><code>-- AOAG_PRIMARY\n\n-- 1. Create and seed a sample database\nUSE [master];\nGO\n\nCREATE DATABASE Sales;\nGO\n\nUSE [Sales];\nGO\n\nCREATE TABLE CUSTOMER(\n    [CustomerID] INT NOT NULL, \n    [SalesAmount] DECIMAL NOT NULL\n);\nGO\n\nINSERT INTO CUSTOMER (CustomerID, SalesAmount) \n     VALUES (1,100),(2,200),(3,300);\n\n-- 2. Switch the database to FULL recovery and take a backup\nALTER DATABASE [Sales] SET RECOVERY FULL;\nGO\n\nBACKUP DATABASE [Sales] \n  TO DISK = N'\/var\/opt\/mssql\/backup\/Sales.bak' \n  WITH NOFORMAT, NOINIT,  \n       NAME = N'Sales-Full Database Backup', \n       SKIP, NOREWIND, NOUNLOAD,  STATS = 10;\nGO\n\n-- 3. Create logins and a certificate for the AOAG\nUSE [master];\nGO\n\nCREATE LOGIN aoag_login WITH PASSWORD = 'Pa$w0rd';\nCREATE USER aoag_user FOR LOGIN aoag_login;\n\nCREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Pa$w0rd';\nGO\n\nCREATE CERTIFICATE aoag_certificate \n  WITH SUBJECT = 'aoag_certificate';\n\nBACKUP CERTIFICATE aoag_certificate\n  TO FILE = '\/var\/opt\/mssql\/shared\/aoag_certificate.cert'\n  WITH PRIVATE KEY (\n       FILE = '\/var\/opt\/mssql\/shared\/aoag_certificate.key',\n       ENCRYPTION BY PASSWORD = 'Pa$w0rd'\n  );\nGO\n\n-- 4. Create an HADR endpoint on port 5022\nCREATE ENDPOINT [Hadr_endpoint]\n  STATE = STARTED\n  AS TCP (LISTENER_PORT = 5022, LISTENER_IP = ALL)\n  FOR DATA_MIRRORING (\n    ROLE = ALL,\n    AUTHENTICATION = CERTIFICATE aoag_certificate,\n    ENCRYPTION = REQUIRED ALGORITHM AES\n  );\n\nGRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [aoag_login];\nGO\n\n-- 5. Create the Availability Group\nDECLARE @cmd AS NVARCHAR(MAX);\nSET @cmd = '\nCREATE AVAILABILITY GROUP [AG1]\nWITH (\n    CLUSTER_TYPE = NONE\n)\nFOR REPLICA ON\nN'''' WITH\n(\n    ENDPOINT_URL = N''tcp:\/\/:5022'',\n    AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,\n    SEEDING_MODE = AUTOMATIC,\n    FAILOVER_MODE = MANUAL,\n    SECONDARY_ROLE (ALLOW_CONNECTIONS = ALL)\n),\nN''db2'' WITH\n(\n    ENDPOINT_URL = N''tcp:\/\/db2:5022'',\n    AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,\n    SEEDING_MODE = AUTOMATIC,\n    FAILOVER_MODE = MANUAL,\n    SECONDARY_ROLE (ALLOW_CONNECTIONS = ALL)\n);';\n\nDECLARE @create_ag AS NVARCHAR(MAX);\nSELECT @create_ag = REPLACE(@cmd, '', @@SERVERNAME);\n\nEXEC sp_executesql @create_ag;\n\n-- 6. Add the Sales database to AG after a short delay\nWAITFOR DELAY '00:00:10';\n\nALTER AVAILABILITY GROUP [AG1] ADD DATABASE [Sales];\nGO\n<\/code><\/pre>\n<\/details>\n<details>\n<summary><strong>aoag_secondary.sql<\/strong><\/summary>\n<pre><code>-- AOAG_SECONDARY\n\nUSE [master];\nGO\n\n-- 1. Create login and user for AOAG\nCREATE LOGIN aoag_login WITH PASSWORD = 'Pa$w0rd';\nCREATE USER aoag_user FOR LOGIN aoag_login;\n\n-- 2. Create master key and certificate from primary's backup\nCREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Pa$w0rd';\nGO\n\nCREATE CERTIFICATE aoag_certificate\n    AUTHORIZATION aoag_user\n    FROM FILE = '\/var\/opt\/mssql\/shared\/aoag_certificate.cert'\n    WITH PRIVATE KEY (\n      FILE = '\/var\/opt\/mssql\/shared\/aoag_certificate.key',\n      DECRYPTION BY PASSWORD = 'Pa$w0rd'\n    );\nGO\n\n-- 3. Create the HADR endpoint for the secondary\nCREATE ENDPOINT [Hadr_endpoint]\n  STATE = STARTED\n  AS TCP (LISTENER_PORT = 5022, LISTENER_IP = ALL)\n  FOR DATA_MIRRORING (\n    ROLE = ALL,\n    AUTHENTICATION = CERTIFICATE aoag_certificate,\n    ENCRYPTION = REQUIRED ALGORITHM AES\n  );\n\nGRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [aoag_login];\nGO\n\n-- 4. Join the secondary to the existing availability group\nALTER AVAILABILITY GROUP [AG1] JOIN WITH (CLUSTER_TYPE = NONE);\nALTER AVAILABILITY GROUP [AG1] GRANT CREATE ANY DATABASE;\nGO<\/code><\/pre>\n<\/details>\n<h4>6. Confirm the File Structure<\/h4>\n<p>Your project folder should look similar to this:<\/p>\n<pre><code>(your folder)\n\u251c\u2500\u2500 docker-compose.yml\n\u2514\u2500\u2500 sql\/\n    \u251c\u2500\u2500 Dockerfile\n    \u251c\u2500\u2500 aoag_primary.sql\n    \u251c\u2500\u2500 aoag_secondary.sql\n    \u251c\u2500\u2500 dbinit.sh\n    \u2514\u2500\u2500 entrypoint.sh<\/code><\/pre>\n<p>Make sure each file is in the correct directory, and that your scripts are executable (e.g., <code>chmod +x entrypoint.sh dbinit.sh<\/code>).<\/p>\n<h4>7. Build and Run the Containers<\/h4>\n<p>Follow these steps to build and run the containers:<\/p>\n<ol>\n<li>Open a terminal or PowerShell prompt in the folder containing <code>docker-compose.yml<\/code>.<\/li>\n<li>Run:\n<pre><code>docker-compose up --build<\/code><\/pre>\n<p>This command will build the images as defined in the Dockerfile and spin up the two containers (<code>db1<\/code> and <code>db2<\/code>).<\/li>\n<li>Once both containers start, verify the logs. Look for confirmation messages from <code>dbinit.sh<\/code> indicating that the AOAG scripts have run successfully.<\/li>\n<li>Test connectivity by opening a SQL client (e.g., <strong>SQL Server Management Studio<\/strong> or <strong>Azure Data Studio<\/strong>) and connecting to:\n<ul>\n<li><code>localhost,2500<\/code> for the primary container (<code>db1<\/code>)<\/li>\n<li><code>localhost,2600<\/code> for the secondary container (<code>db2<\/code>)<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h3>Conclusion<\/h3>\n<p>Deploying a clusterless SQL Server Always On Availability Group with Docker containers offers a streamlined, repeatable, and efficient way to set up high availability for development or testing scenarios. By defining all necessary components\u2014such as database configurations, scripts, and environment settings\u2014in a <code>Dockerfile<\/code> and <code>docker-compose.yml<\/code>, you can automate the creation of a consistent environment on any machine. This eliminates the complexity of manual configuration and helps ensure that DBAs, BI developers, and other stakeholders can focus on innovating rather than troubleshooting environment inconsistencies.<\/p>\n<p>Docker\u2019s reproducible containers and Compose\u2019s multi-container orchestration together provide a robust and agile approach to testing high availability solutions. Whether you are exploring new features, simulating disaster recovery scenarios, or maintaining CDC in a resilient architecture, this setup offers a strong foundation for reliable SQL Server deployments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Deploy a high availability SQL Server Always On environment using Docker containers. This step-by-step guide covers Dockerfile configuration, Docker Compose orchestration, and T-SQL scripts for enterprise DBAs and BI developers to ensure seamless CDC and database performance.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[55,36,94,20,21],"tags":[493,497,494,492,489,499,496,495,490,131,488,498,491],"class_list":["post-401","post","type-post","status-publish","format-standard","hentry","category-automation","category-availability-groups","category-change-data-capture","category-sql-server-on-linux","category-tutorial","tag-cdc-high-availability","tag-containerized-sql-server","tag-database-containerization","tag-docker-compose","tag-docker-containers","tag-docker-deployment","tag-docker-sql-server-setup","tag-enterprise-sql-server","tag-high-availability-sql-server","tag-sql-server","tag-sql-server-always-on","tag-sql-server-cdc","tag-sql-server-docker"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to Set Up a SQL Server Always On Environment Using Docker Containers - SQL Table Talk<\/title>\n<meta name=\"description\" content=\"Deploy a high availability SQL Server Always On environment using Docker containers. This step-by-step guide covers Dockerfile configuration, Docker Compose orchestration, and T-SQL scripts for enterprise DBAs and BI developers to ensure seamless CDC and database performance.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqltabletalk.com\/?p=401\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Set Up a SQL Server Always On Environment Using Docker Containers - SQL Table Talk\" \/>\n<meta property=\"og:description\" content=\"Deploy a high availability SQL Server Always On environment using Docker containers. This step-by-step guide covers Dockerfile configuration, Docker Compose orchestration, and T-SQL scripts for enterprise DBAs and BI developers to ensure seamless CDC and database performance.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqltabletalk.com\/?p=401\" \/>\n<meta property=\"og:site_name\" content=\"SQL Table Talk\" \/>\n<meta property=\"article:published_time\" content=\"2025-02-04T13:00:00+00:00\" \/>\n<meta name=\"author\" content=\"Yvonne Vanslageren\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Yvonne Vanslageren\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.sqltabletalk.com\/?p=401#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqltabletalk.com\/?p=401\"},\"author\":{\"name\":\"Yvonne Vanslageren\",\"@id\":\"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/68bb31b454bafe9e139183ed4f3e9082\"},\"headline\":\"How to Set Up a SQL Server Always On Environment Using Docker Containers\",\"datePublished\":\"2025-02-04T13:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.sqltabletalk.com\/?p=401\"},\"wordCount\":960,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/1947e42a9438bccd91691d8b791888e0\"},\"keywords\":[\"CDC High Availability\",\"Containerized SQL Server\",\"Database Containerization\",\"Docker Compose\",\"Docker Containers\",\"Docker Deployment\",\"Docker SQL Server Setup\",\"Enterprise SQL Server\",\"High Availability SQL Server\",\"SQL Server\",\"SQL Server Always On\",\"SQL Server CDC\",\"SQL Server Docker\"],\"articleSection\":[\"Automation\",\"Availability Groups\",\"Change Data Capture\",\"SQL Server on Linux\",\"Tutorial\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.sqltabletalk.com\/?p=401#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqltabletalk.com\/?p=401\",\"url\":\"https:\/\/www.sqltabletalk.com\/?p=401\",\"name\":\"How to Set Up a SQL Server Always On Environment Using Docker Containers - SQL Table Talk\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqltabletalk.com\/#website\"},\"datePublished\":\"2025-02-04T13:00:00+00:00\",\"description\":\"Deploy a high availability SQL Server Always On environment using Docker containers. This step-by-step guide covers Dockerfile configuration, Docker Compose orchestration, and T-SQL scripts for enterprise DBAs and BI developers to ensure seamless CDC and database performance.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.sqltabletalk.com\/?p=401#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqltabletalk.com\/?p=401\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqltabletalk.com\/?p=401#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqltabletalk.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Set Up a SQL Server Always On Environment Using Docker Containers\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqltabletalk.com\/#website\",\"url\":\"https:\/\/www.sqltabletalk.com\/\",\"name\":\"SQL Table Talk\",\"description\":\"Breaking Down SQL Server, One Post at a Time.\",\"publisher\":{\"@id\":\"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/1947e42a9438bccd91691d8b791888e0\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqltabletalk.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/1947e42a9438bccd91691d8b791888e0\",\"name\":\"Stephen Planck\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/64181114edc3de3d99072c049bcec024f025c9536dc89fc8ff1bac58976ca81e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/64181114edc3de3d99072c049bcec024f025c9536dc89fc8ff1bac58976ca81e?s=96&d=mm&r=g\",\"caption\":\"Stephen Planck\"},\"logo\":{\"@id\":\"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/image\/\"},\"sameAs\":[\"https:\/\/dexterwiki.com\",\"https:\/\/www.linkedin.com\/in\/stephen-planck-4611b692?trk=people-guest_people_search-card&challengeId=AQErf8gbBmcVMwAAAYsyIsxO-0UvU8z7cHrBpZoo_n3xt9qEKpRN5B_jd_LmAMu-OfeArkQ7GDjobJ2uRoQQV35EQdh_rR6kxA&submissionId=09de7067-c335-8e17-40b8-8dc32b60ed6c&challengeSource=AgEcUCw35zpPmAAAAYsyI4vAWhJTV7Nt4vZYKc3V1qiDBpCkKgUvtlOBgYXcE84&challegeType=AgE_wZiTT09IAQAAAYsyI4vDmNvbZIYe6XHju5V2bXVvM3IVxnJslgY&memberId=AgESFTkUShzs_gAAAYsyI4vGYk0Gic1uc5kB6cKOABA26Gw&recognizeDevice=AgHdSZyUSI5CEwAAAYsyI4vKd_koF9JgpsCJShT8QfbK1QMiv8SI\",\"https:\/\/www.youtube.com\/linuxmate\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/68bb31b454bafe9e139183ed4f3e9082\",\"name\":\"Yvonne Vanslageren\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/22c274a7a354b81a0a8dc5b23e8e0be9bdd81a6bc0541474cfb6b954d6bb2089?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/22c274a7a354b81a0a8dc5b23e8e0be9bdd81a6bc0541474cfb6b954d6bb2089?s=96&d=mm&r=g\",\"caption\":\"Yvonne Vanslageren\"},\"url\":\"https:\/\/www.sqltabletalk.com\/?author=2\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Set Up a SQL Server Always On Environment Using Docker Containers - SQL Table Talk","description":"Deploy a high availability SQL Server Always On environment using Docker containers. This step-by-step guide covers Dockerfile configuration, Docker Compose orchestration, and T-SQL scripts for enterprise DBAs and BI developers to ensure seamless CDC and database performance.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sqltabletalk.com\/?p=401","og_locale":"en_US","og_type":"article","og_title":"How to Set Up a SQL Server Always On Environment Using Docker Containers - SQL Table Talk","og_description":"Deploy a high availability SQL Server Always On environment using Docker containers. This step-by-step guide covers Dockerfile configuration, Docker Compose orchestration, and T-SQL scripts for enterprise DBAs and BI developers to ensure seamless CDC and database performance.","og_url":"https:\/\/www.sqltabletalk.com\/?p=401","og_site_name":"SQL Table Talk","article_published_time":"2025-02-04T13:00:00+00:00","author":"Yvonne Vanslageren","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Yvonne Vanslageren","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.sqltabletalk.com\/?p=401#article","isPartOf":{"@id":"https:\/\/www.sqltabletalk.com\/?p=401"},"author":{"name":"Yvonne Vanslageren","@id":"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/68bb31b454bafe9e139183ed4f3e9082"},"headline":"How to Set Up a SQL Server Always On Environment Using Docker Containers","datePublished":"2025-02-04T13:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.sqltabletalk.com\/?p=401"},"wordCount":960,"commentCount":1,"publisher":{"@id":"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/1947e42a9438bccd91691d8b791888e0"},"keywords":["CDC High Availability","Containerized SQL Server","Database Containerization","Docker Compose","Docker Containers","Docker Deployment","Docker SQL Server Setup","Enterprise SQL Server","High Availability SQL Server","SQL Server","SQL Server Always On","SQL Server CDC","SQL Server Docker"],"articleSection":["Automation","Availability Groups","Change Data Capture","SQL Server on Linux","Tutorial"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.sqltabletalk.com\/?p=401#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.sqltabletalk.com\/?p=401","url":"https:\/\/www.sqltabletalk.com\/?p=401","name":"How to Set Up a SQL Server Always On Environment Using Docker Containers - SQL Table Talk","isPartOf":{"@id":"https:\/\/www.sqltabletalk.com\/#website"},"datePublished":"2025-02-04T13:00:00+00:00","description":"Deploy a high availability SQL Server Always On environment using Docker containers. This step-by-step guide covers Dockerfile configuration, Docker Compose orchestration, and T-SQL scripts for enterprise DBAs and BI developers to ensure seamless CDC and database performance.","breadcrumb":{"@id":"https:\/\/www.sqltabletalk.com\/?p=401#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqltabletalk.com\/?p=401"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqltabletalk.com\/?p=401#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqltabletalk.com\/"},{"@type":"ListItem","position":2,"name":"How to Set Up a SQL Server Always On Environment Using Docker Containers"}]},{"@type":"WebSite","@id":"https:\/\/www.sqltabletalk.com\/#website","url":"https:\/\/www.sqltabletalk.com\/","name":"SQL Table Talk","description":"Breaking Down SQL Server, One Post at a Time.","publisher":{"@id":"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/1947e42a9438bccd91691d8b791888e0"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqltabletalk.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/1947e42a9438bccd91691d8b791888e0","name":"Stephen Planck","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/64181114edc3de3d99072c049bcec024f025c9536dc89fc8ff1bac58976ca81e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/64181114edc3de3d99072c049bcec024f025c9536dc89fc8ff1bac58976ca81e?s=96&d=mm&r=g","caption":"Stephen Planck"},"logo":{"@id":"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/image\/"},"sameAs":["https:\/\/dexterwiki.com","https:\/\/www.linkedin.com\/in\/stephen-planck-4611b692?trk=people-guest_people_search-card&challengeId=AQErf8gbBmcVMwAAAYsyIsxO-0UvU8z7cHrBpZoo_n3xt9qEKpRN5B_jd_LmAMu-OfeArkQ7GDjobJ2uRoQQV35EQdh_rR6kxA&submissionId=09de7067-c335-8e17-40b8-8dc32b60ed6c&challengeSource=AgEcUCw35zpPmAAAAYsyI4vAWhJTV7Nt4vZYKc3V1qiDBpCkKgUvtlOBgYXcE84&challegeType=AgE_wZiTT09IAQAAAYsyI4vDmNvbZIYe6XHju5V2bXVvM3IVxnJslgY&memberId=AgESFTkUShzs_gAAAYsyI4vGYk0Gic1uc5kB6cKOABA26Gw&recognizeDevice=AgHdSZyUSI5CEwAAAYsyI4vKd_koF9JgpsCJShT8QfbK1QMiv8SI","https:\/\/www.youtube.com\/linuxmate"]},{"@type":"Person","@id":"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/68bb31b454bafe9e139183ed4f3e9082","name":"Yvonne Vanslageren","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqltabletalk.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/22c274a7a354b81a0a8dc5b23e8e0be9bdd81a6bc0541474cfb6b954d6bb2089?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/22c274a7a354b81a0a8dc5b23e8e0be9bdd81a6bc0541474cfb6b954d6bb2089?s=96&d=mm&r=g","caption":"Yvonne Vanslageren"},"url":"https:\/\/www.sqltabletalk.com\/?author=2"}]}},"jetpack_featured_media_url":"","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=\/wp\/v2\/posts\/401","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=401"}],"version-history":[{"count":4,"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=\/wp\/v2\/posts\/401\/revisions"}],"predecessor-version":[{"id":973,"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=\/wp\/v2\/posts\/401\/revisions\/973"}],"wp:attachment":[{"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=401"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=401"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqltabletalk.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=401"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}