I needed a local SQL Server with the AdventureWorks2022 sample database. Sounds like a 10-minute job, right? Run a container, restore a .bak, connect with DBeaver. Done.
It took two hours. Here's what actually happened, what broke, and the setup that finally worked.
The Goal
- SQL Server 2022 running in Docker on Debian
- Auto-restore
AdventureWorks2022.bakon first boot - Connect from DBeaver without certificate errors
- Survive restarts without re-restoring the database
What I Built
A Docker Compose setup with a custom entrypoint.sh that:
- Starts SQL Server in the background
- Polls
sqlcmdevery 2 seconds until the engine is ready - Checks if
AdventureWorks2022already exists (idempotent) - If not, runs
RESTORE DATABASE ... WITH MOVE - Keeps the container alive
The database files live in a named Docker volume, so stopping and restarting the container doesn't wipe your data.
The Bugs That Weren't in the Tutorial
1. Permission denied on entrypoint.sh
I store my projects on Koofr (cloud-synced). chmod +x works on the host, but Docker bind-mounts the file without the execute bit. The container kept restarting with Permission denied.
Fix: Run the script through /bin/bash instead of relying on the shebang:
entrypoint: ["/bin/bash", "/usr/config/entrypoint.sh"]
2. "Access is denied" on master.mdf
SQL Server's default mssql user couldn't write to the Docker volume.
Fix: Added user: root to the compose service. Fine for local dev. Don't do this in production.
3. sqlcmd v18 won't connect without -C
SQL Server 2022 bundles sqlcmd in /opt/mssql-tools18/bin/. This version refuses to connect to localhost without explicitly trusting the self-signed certificate, even though it's the same machine.
Fix: Every sqlcmd call gets the -C flag. The healthcheck too.
4. DBeaver's JDBC driver demanded a keystore
I kept getting:
"keyStoreAuthentication" connection string keyword must be specified, if "keyStoreSecret" is specified
Clearing the properties in one connection didn't help — the driver had cached defaults somewhere. I spent 20 minutes in DBeaver preferences before giving up and creating a dummy Java keystore.
Fix: One keytool command to generate a fake .jks file, then four driver properties in DBeaver:
| Property | Value |
|---|---|
keyStoreAuthentication |
JavaKeyStorePassword |
keyStoreLocation |
/absolute/path/to/dummy.jks |
keyStoreSecret |
dummy123 |
trustServerCertificate |
true |
It shouldn't be this hard to connect to a local database. But here we are.
DBeaver Connection — The Exact Settings
After the container is running, here's how to connect DBeaver without any certificate drama.
Main Tab
| Setting | Value |
|---|---|
| Host | localhost |
| Port |
1433 (or whatever you set in .env) |
| Database | AdventureWorks2022 |
| Authentication | SQL Server Authentication |
| User | sa |
| Password | your .env password |
Driver Properties Tab
These are the properties that actually matter. Add or edit them here:
| Property | Value | Why |
|---|---|---|
trustServerCertificate |
true |
Tells the JDBC driver to accept the self-signed cert SQL Server generates on first boot. Without this, you get SSL handshake failures even on localhost. |
keyStoreAuthentication |
JavaKeyStorePassword |
Tells the driver you're using a local JKS file, not Azure Key Vault. |
keyStoreLocation |
/absolute/path/to/dummy.jks |
Points to the dummy keystore file. Use the absolute path — DBeaver doesn't resolve ~ here. |
keyStoreSecret |
dummy123 |
The password for the dummy keystore. |
How to get there: Edit Connection → Driver Properties → scroll down or use the search box. If a property doesn't exist, right-click in the list and choose Add New Property.
Click Test Connection. It should say "Connected".
If You Don't Want the Keystore Hack
You can try resetting the driver completely:
- Window → Preferences → Connections → Drivers → Microsoft JDBC Driver for SQL Server
- Click Reset to Defaults (or delete and re-download)
- In your connection: Driver Properties → gear icon → Reset to Defaults
- Add back only:
trustServerCertificate = true
Sometimes this works. Sometimes the keystore properties come back anyway. The dummy keystore is faster and more reliable.
The Repo
Everything is here: docker-compose.yml, entrypoint.sh, the keystore generator, and a full setup guide.
github.com/sjyotis/adventureworks2022-docker
Quick Start
git clone https://github.com/sjyotis/adventureworks2022-docker.git
cd adventureworks2022-docker
mv /path/to/AdventureWorks2022.bak backups/
docker compose up -d
Wait for the logs to show Restore completed successfully!, then connect DBeaver using the settings above.
Repo Structure
adventureworks2022-docker/
├── docker-compose.yml # Main SQL Server container
├── .env # Password and port config
├── init/
│ └── entrypoint.sh # Auto-restore on first boot
├── backups/
│ └── AdventureWorks2022.bak # Drop your .bak here
├── dbeaver-keystore-fix.md # Full keystore workaround guide
├── adventureworks-docker-setup.md # Complete implementation docs
└── keystore-generator/
├── docker-compose.yml # One-shot keystore generator
└── generate_keystore.py # Python wrapper if you prefer
What This Actually Demonstrates
- Docker Compose orchestration with health checks and named volumes
- Bash scripting for service initialization and idempotency
- SQL Server administration (
RESTORE FILELISTONLY,WITH MOVE) - SSL/TLS debugging in client drivers
- Cross-platform filesystem edge cases (cloud-synced storage stripping permissions)
It's not just "I ran a database in Docker." It's a complete local dev infrastructure setup that handles provisioning, initialization, persistence, and client connectivity across the full stack.
The Files
-
docker-compose.yml— SQL Server 2022 container with volume mounts and healthcheck -
init/entrypoint.sh— Auto-restore script with startup polling -
.env— Configurable SA password and port -
backups/— Drop your.bakhere -
dbeaver-keystore-fix.md— Standalone guide for the DBeaver certificate workaround
If you've ever fought with DBeaver certificates, SQL Server Docker permissions, or restore scripts that assume the database is already running, this repo is for you.
Pull requests welcome. Issues too — especially if you hit a new edge case I haven't seen yet.
Top comments (0)