Using Quarkus Dev Services for Disposable Dependency Containers in Development
An architecture note that outlines the requirements, minimal design, trust boundaries, operational checks, failure modes, and redesign triggers for leveraging Quarkus Dev Services to provision lightweight, disposable containers for dependencies during development and testing.
28 Feb 2026, 03:48 UTC

Requirements
When developing a Quarkus application that depends on external services such as a database or a message broker, developers need a way to:
- Spin up a service instance with zero manual configuration.
- Have the service lifetime tied to the development or test JVM lifecycle.
- Keep the production deployment footprint minimal by ensuring the service is not started automatically in prod.
- Allow quick iteration: code changes trigger a fast restart without tearing down the dependent service.
These requirements are especially relevant in inner‑loop development, CI pipelines that run unit tests, and local developer workstations where installing and managing full‑blown service installations is undesirable.
Smallest Suitable Design
The minimal design that satisfies the above consists of three components:
- Quarkus Dev Services extension – built‑in functionality that watches for missing service configuration and launches a container via the Docker daemon.
- Docker daemon – the runtime that creates, manages, and removes the lightweight containers.
- Quarkus configuration properties – flags such as
quarkus.datasource.devservices.enabledthat toggle the feature per profile (dev, test, prod).
No additional service discovery, orchestration, or external scripts are required. The design relies on convention: if a datasource is declared but no URL is provided, Dev Services assumes the developer wants a disposable PostgreSQL, MySQL, etc., and starts the appropriate container.
Trust and Data Boundaries
Trust boundaries are defined as follows:
- Application ↔ Dev Service: The application trusts that the container exposes the expected protocol on a localhost port. No authentication is configured by default; the connection uses default credentials (e.g.,
quarkus/quarkus) which are safe because the container is isolated to the developer’s machine or CI agent. - Dev Service ↔ Docker Daemon: Trust is limited to the ability to create and remove containers. The Dev Services extension does not request privileged capabilities; it runs as a regular user process that communicates with the Docker socket.
- Data Boundary: Data stored inside the Dev Service container is ephemeral. When the container stops (unless reuse mode is enabled), the filesystem layer is discarded. This ensures no accidental persistence of test data across runs.
Because the containers are launched on the same host that runs the JVM, network traffic stays within the loopback interface, reducing exposure to external networks.
Operational Checks
To verify that Dev Services is behaving as expected, perform the following checks:
- Startup observation – Run the application in dev mode (
./mvnw quarkus:dev) with a datasource declared but no URL. The console should contain a line indicating that a Dev Service container is starting, e.g., "Starting Dev Service for postgresql". - Container inspection – After the application is up, execute
docker ps --filter "name=quarkus-devservice-*"from a terminal with access to the Docker daemon. You should see a container whose name includes the service kind (e.g.,quarkus-devservice-postgres). - Connectivity test – Use a simple JDBC call or a REST endpoint that accesses the database to confirm the application can reach the service.
- Feature toggle – Set
quarkus.datasource.devservices.enabled=falseinapplication.properties(or via an environment variable) and restart the dev mode. The application should fail to start unless an explicitquarkus.datasource.jdbc.urlis provided, confirming the feature is disabled. - Cleanup verification – Stop the Quarkus process (CTRL+C) and run
docker psagain. The Dev Service container should disappear unlessquarkus.datasource.devservices.reuse.enabled=trueis set.
All of these checks can be performed with standard command‑line tools; no custom instrumentation is required.
Failure Modes
Understanding how the design can fail helps teams prepare mitigations:
- Docker daemon unavailable – If the Docker daemon is not running or the process lacks permission to access
/var/run/docker.sock, Dev Services will log an error and the application will fail to start. Mitigation: ensure Docker is installed and the user is in thedockergroup, or configure an external service URL explicitly. - Port conflicts – Dev Services selects a random free port for the service. If the host’s port range is exhausted or another process binds to the same random port, the container startup may fail. Mitigation: increase the host’s ephemeral port range or disable reuse mode to avoid long‑lived containers that occupy ports.
- Image pull failures** – In environments without internet access, the extension cannot pull the required image (e.g.,
docker.io/library/postgres). Mitigation: pre‑pull the image or configurequarkus.datasource.devservices.image-nameto point to a locally available image. - Startup latency** – Each JVM launch triggers a container start, adding seconds to dev‑mode startup. Mitigation: enable reuse mode (
quarkus..devservices.reuse.enabled=true) so the container persists across restarts, or externalize the service for very frequent restarts.
Conditions That Would Change the Design
The current minimal design is appropriate when:
- Docker is available and the team is comfortable managing container lifecycles.
- Services needed in dev/test are officially supported by Quarkus Dev Services (databases, message brokers, key‑value stores, etc.).
- Data persistence across runs is not required, or reuse mode can be safely enabled.
If any of the following conditions arise, consider revising the design:
- No Docker access** – In restricted CI runners or environments where Docker is prohibited, replace Dev Services with explicit testcontainers configuration or rely on external service URLs provided via configuration.
- Need for custom service versions** – When a specific patched version of a database is required that is not offered by the default Dev Services image, override
quarkus..devservices.image-nameor switch to manual container management. - Long‑running integration test suites** – If tests run for many minutes and container startup overhead becomes noticeable, enable reuse mode or provision a shared external service for the test namespace.
- Security constraints** – If default credentials are unacceptable, configure
quarkus..devservices.usernameandquarkus..devservices.passwordto use stronger secrets, or inject credentials via Kubernetes/OpenShift secrets when deploying to a dev namespace.
By evaluating these triggers, teams can decide whether to stay with the built‑in Dev Services approach or adopt a more customized container orchestration strategy while preserving the core goal of zero‑configuration, disposable dependencies for development and testing.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.