Skip to content

Support reuse of dev containers#1861

Open
nscuro wants to merge 1 commit intomainfrom
dev-container-reuse
Open

Support reuse of dev containers#1861
nscuro wants to merge 1 commit intomainfrom
dev-container-reuse

Conversation

@nscuro
Copy link
Copy Markdown
Member

@nscuro nscuro commented Mar 8, 2026

Description

Supports reuse of dev containers.

Allows database state to be reused across restarts, and more generally makes startup faster.

Addressed Issue

N/A

Additional Details

N/A

Checklist

  • I have read and understand the contributing guidelines
  • This PR fixes a defect, and I have provided tests to verify that the fix is effective
  • This PR implements an enhancement, and I have provided tests to verify that it works as intended
  • This PR introduces changes to the database model, and I have updated the migration changelog accordingly
  • This PR introduces new or alters existing behavior, and I have updated the documentation accordingly

Allows database state to be reused across restarts, and more generally makes startup faster.

Signed-off-by: nscuro <nscuro@protonmail.com>
@nscuro nscuro added this to the 5.7.0 milestone Mar 8, 2026
Copilot AI review requested due to automatic review settings March 8, 2026 17:14
@nscuro nscuro added the dx Issues related to developer experience (DX) label Mar 8, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for reusing Testcontainers-backed “dev services” containers across API server restarts, aiming to speed up local development by keeping stateful containers (e.g., PostgreSQL) running.

Changes:

  • Introduces a new configuration flag to enable/disable dev-services container reuse.
  • Configures PostgreSQL/Kafka/frontend dev-service containers with labels and withReuse(...).
  • Adjusts Kafka topic creation to tolerate existing topics when reusing containers.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
apiserver/src/main/resources/application.properties Adds dev.services.container-reuse-enabled configuration and docs for container reuse.
apiserver/src/main/java/org/dependencytrack/dev/DevServicesInitializer.java Enables container reuse/labels, tolerates “topic already exists”, and conditionally skips stopping containers on shutdown.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1398 to +1404
# Defines whether dev services containers should be reused.
# <br/><br/>
# Refer to <https://java.testcontainers.org/features/reuse/> for details.
#
# @category: Development
# @type: boolean
dev.services.container-reuse-enabled=true
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new dev.services.container-reuse-enabled setting is documented, but it doesn’t mention two important behavioral constraints of Testcontainers reuse: (1) reuse is ignored unless TESTCONTAINERS_REUSE_ENABLE=true or testcontainers.reuse.enable=true is set, and (2) when reuse is enabled the containers are intentionally not disposed on shutdown. As written, this also conflicts with the earlier dev-services description that says containers are disposed when Dependency-Track stops. Please update the property docs (and/or the dev-services section above) to reflect the prerequisite and the changed shutdown behavior so users don’t end up with unexpected lingering containers.

Copilot uses AI. Check for mistakes.
Comment on lines 185 to 203
public void contextDestroyed(final ServletContextEvent event) {
if (postgresContainer != null) {
if (postgresContainer != null && !isContainerReuseEnabled) {
LOGGER.info("Stopping postgres container");
try {
postgresContainer.close();
} catch (Exception e) {
LOGGER.error("Failed to stop PostgreSQL container", e);
}
}
if (kafkaContainer != null) {
if (kafkaContainer != null && !isContainerReuseEnabled) {
LOGGER.info("Stopping Kafka container");
try {
kafkaContainer.close();
} catch (Exception e) {
LOGGER.error("Failed to stop Kafka container", e);
}
}
if (frontendContainer != null) {
if (frontendContainer != null && !isContainerReuseEnabled) {
LOGGER.info("Stopping frontend container");
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contextDestroyed() skips closing containers solely based on dev.services.container-reuse-enabled. In Testcontainers, withReuse(true) has no effect unless reuse is enabled globally (e.g. testcontainers.reuse.enable=true), so this can leave non-reusable containers running (and keep host ports bound) when the webapp is stopped/redeployed without a JVM exit. Consider only skipping close() when Testcontainers reports that the environment supports reuse, otherwise always close containers on shutdown.

Copilot uses AI. Check for mistakes.
Comment on lines 172 to +176
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException("Failed to create topics", e);
if (e.getCause() == null
|| !"TopicExistsException".equals(e.getCause().getClass().getSimpleName())) {
throw new RuntimeException("Failed to create topics", e);
}
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TopicExists handling is based on comparing e.getCause().getClass().getSimpleName() to a string. This is brittle and can misclassify unrelated exceptions with the same simple name; it also doesn’t preserve the thread interrupt status when an InterruptedException is caught. Prefer checking the actual Kafka exception type (e.g. org.apache.kafka.common.errors.TopicExistsException, accounting for potential wrapping) and, for InterruptedException, re-interrupt the thread before propagating/handling it.

Copilot uses AI. Check for mistakes.
@codacy-production
Copy link
Copy Markdown

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
-0.03% (target: -1.00%) (target: 70.00%)
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (092c4c8) 25749 21913 85.10%
Head commit (617dfcf) 25749 (+0) 21906 (-7) 85.08% (-0.03%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#1861) 0 0 ∅ (not applicable)

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dx Issues related to developer experience (DX)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants