Skip to content

Commit f5059fb

Browse files
committed
chore: wip
1 parent 111496a commit f5059fb

16 files changed

+8907
-18
lines changed

src/dynamodb.ts

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import { exists } from './utils'
1313

1414
const debug = Debug('dynamodb-local')
1515
const JARNAME = 'DynamoDBLocal.jar'
16+
const DOCKER_IMAGE = 'amazon/dynamodb-local:latest'
1617

1718
export const runningProcesses: { [port: number]: Subprocess } = {}
19+
export const runningContainers: { [port: number]: string } = {}
1820

1921
export const dynamoDb = {
2022
async launch(options?: LaunchOptions): Promise<Subprocess | undefined> {
@@ -26,11 +28,17 @@ export const dynamoDb = {
2628
verbose = false,
2729
detached = config.local.detached,
2830
javaOpts = config.local.javaOpts,
31+
useDocker = false,
2932
} = options ?? {}
3033

3134
if (runningProcesses[port])
3235
return runningProcesses[port]
3336

37+
// Use Docker if requested
38+
if (useDocker) {
39+
return this.launchDocker({ port, dbPath, verbose, detached })
40+
}
41+
3442
const args = [
3543
'-Xrs',
3644
'-Djava.library.path=./DynamoDBLocal_lib',
@@ -73,10 +81,108 @@ export const dynamoDb = {
7381
}
7482
},
7583

84+
/**
85+
* Launch DynamoDB Local using Docker
86+
*/
87+
async launchDocker(options: {
88+
port?: number
89+
dbPath?: string | null
90+
verbose?: boolean
91+
detached?: boolean
92+
}): Promise<Subprocess | undefined> {
93+
const config = await getConfig()
94+
const {
95+
port = config.local.port,
96+
dbPath = config.local.dbPath,
97+
verbose = false,
98+
detached = config.local.detached,
99+
} = options
100+
101+
const containerName = `dynamodb-local-${port}`
102+
103+
// Check if container already exists and is running
104+
const checkResult = Bun.spawnSync(['docker', 'ps', '-q', '-f', `name=${containerName}`])
105+
const existingContainer = checkResult.stdout.toString().trim()
106+
if (existingContainer) {
107+
debug(`DynamoDB Local container already running on port ${port}`)
108+
// Return a fake subprocess that represents the running container
109+
if (runningProcesses[port])
110+
return runningProcesses[port]
111+
}
112+
113+
// Stop and remove any existing container with same name
114+
Bun.spawnSync(['docker', 'rm', '-f', containerName], { stdout: 'ignore', stderr: 'ignore' })
115+
116+
const dockerArgs = [
117+
'run',
118+
'--rm',
119+
'-d',
120+
'--name', containerName,
121+
'-p', `${port}:8000`,
122+
]
123+
124+
// Add volume mount if dbPath is specified
125+
if (dbPath) {
126+
const absoluteDbPath = path.resolve(dbPath)
127+
await fs.promises.mkdir(absoluteDbPath, { recursive: true })
128+
dockerArgs.push('-v', `${absoluteDbPath}:/home/dynamodblocal/data`)
129+
dockerArgs.push(DOCKER_IMAGE, '-jar', 'DynamoDBLocal.jar', '-dbPath', '/home/dynamodblocal/data')
130+
}
131+
else {
132+
dockerArgs.push(DOCKER_IMAGE)
133+
}
134+
135+
debug('Launching DynamoDB Local with Docker:', dockerArgs)
136+
137+
try {
138+
const child = Bun.spawn(['docker', ...dockerArgs], {
139+
onExit: (proc, exitCode, signalCode, error) => {
140+
if (exitCode !== 0 && verbose)
141+
debug('Docker container exit code:', exitCode)
142+
if (error)
143+
debug('Docker container error:', error)
144+
},
145+
})
146+
147+
// Wait a moment for container to start
148+
await new Promise(resolve => setTimeout(resolve, 1000))
149+
150+
// Verify container is running
151+
const verifyResult = Bun.spawnSync(['docker', 'ps', '-q', '-f', `name=${containerName}`])
152+
const runningContainer = verifyResult.stdout.toString().trim()
153+
if (!runningContainer) {
154+
throw new Error('Failed to start DynamoDB Local Docker container')
155+
}
156+
157+
runningContainers[port] = containerName
158+
159+
if (!detached) {
160+
process.on('exit', () => {
161+
Bun.spawnSync(['docker', 'stop', containerName], { stdout: 'ignore', stderr: 'ignore' })
162+
})
163+
}
164+
165+
runningProcesses[port] = child
166+
return child
167+
}
168+
catch (error) {
169+
debug('Error launching DynamoDB Local via Docker:', error)
170+
throw error
171+
}
172+
},
173+
76174
stop(port: number): void {
77-
const process = runningProcesses[port]
78-
if (process) {
79-
process.kill('SIGKILL')
175+
const proc = runningProcesses[port]
176+
const containerName = runningContainers[port]
177+
178+
if (containerName) {
179+
// Stop Docker container
180+
Bun.spawnSync(['docker', 'stop', containerName], { stdout: 'ignore', stderr: 'ignore' })
181+
delete runningContainers[port]
182+
}
183+
184+
if (proc) {
185+
proc.kill('SIGKILL')
80186
delete runningProcesses[port]
81187
}
82188
},

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,11 @@ export type LaunchOptions = Partial<Pick<LocalConfig, 'port' | 'dbPath' | 'detac
799799
* @default false
800800
*/
801801
verbose?: boolean
802+
/**
803+
* Use Docker to run DynamoDB Local instead of Java
804+
* @default false
805+
*/
806+
useDocker?: boolean
802807
}
803808

804809
// ============================================================================

0 commit comments

Comments
 (0)