Arconia Dev Services
Arconia Dev Services streamline your development workflow by automatically provisioning external services your application depends on during development and testing. No manual setup is required.
Need a database, message broker, or other infrastructure components for your application? Add the corresponding Dev Service dependency to your project. When you run your application or tests, the required services start automatically as OCI containers and are seamlessly wired into your application. Zero additional code or configuration needed.
Built on Testcontainers and Spring Boot’s Testcontainers support, Arconia Dev Services provide a great developer experience by eliminating the friction of manually setting up and managing services in your development environment.
|
Dev Services are designed exclusively for development and testing workflows. They are excluded from production builds and have zero impact on your production deployments. |
How It Works
When Arconia Dev Services are detected during development or testing, the framework:
-
Starts the container: Launches an OCI container for the required service using Testcontainers.
-
Configures the connection: Sets up connection properties (URLs, credentials, ports).
-
Wires the service: Integrates the service into your application context using Spring Boot’s Service Connection mechanism.
-
Manages the lifecycle: Handles container startup, shutdown, and cleanup.
This happens transparently without requiring any code or configuration. Dev Services take precedence over manually configured properties, ensuring your application always connects to the containerized service during development and testing.
Quick Start
Get started with Arconia Dev Services in three simple steps:
-
Add the dependency for your required service (e.g., PostgreSQL):
-
Gradle
-
Maven
dependencies { testAndDevelopmentOnly 'io.arconia:arconia-dev-services-postgresql' }<dependency> <groupId>io.arconia</groupId> <artifactId>arconia-dev-services-postgresql</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> -
-
Run your application as usual:
-
Gradle
-
Maven
-
CLI
./gradlew bootRun./mvnw spring-boot:runarconia dev -
-
That’s it! The PostgreSQL container starts automatically and your application connects to it. No configuration files, no code changes needed.
|
Want to verify which Dev Services are running? If Spring Boot Actuator is in your classpath, check the |
Using Dev Services
Dev Services are available as separate modules for each supported service. You can find the complete list in the Supported Services section below.
Service Connections
Your application is automatically configured to connect to Dev Services, which take precedence over manually configured properties. For example, when using the arconia-dev-services-postgresql module, the Dev Service transparently overrides properties like spring.datasource.url, spring.datasource.username, and spring.datasource.password.
The auto-configuration mechanism uses Spring Boot’s Service Connections internally to establish connections between your application and containerized services, eliminating the need for manual property configuration or test-specific setup code.
Lifecycle Management
Arconia instructs Spring Boot to manage the lifecycle of Dev Services as beans in the application context:
-
Startup: Services start when the application context initializes.
-
Shutdown: Services stop when the context closes.
-
Persistence: Services remain available throughout the lifecycle of your application or tests.
When using Spring Boot DevTools, Dev Services are not recreated on restart. They remain running in the background, ensuring a smooth development experience without wait times or state loss.
Configuration Options
Each Dev Service can be customized through Spring Boot configuration properties. All Dev Services support a common set of properties under the arconia.dev.services.<service-name> prefix.
Common Properties
The following properties are available for all Dev Services.
|
All Dev Services are enabled by default. Other properties have sensible defaults that may vary by service. |
| Property | Description |
|---|---|
|
Whether the dev service is enabled. |
|
Full name of the container image used in the dev service. |
|
Environment variables to set in the service. |
|
Network aliases to assign to the dev service container. |
|
Fixed port for exposing the primary service port to the host. When it’s 0 (default), a random available port is assigned dynamically. |
|
Resources from the classpath or host filesystem to copy into the container. They can be files or directories that will be copied to the specified destination path inside the container at startup and are immutable (read-only). |
|
Whether the dev service is shared among applications. Only applicable in dev mode. |
|
Maximum waiting time for the service to start. |
|
Files or directories to mount from the host filesystem into the container. They are mounted at the specified destination path inside the container at startup and are mutable (read-write). Changes in either the host or the container will be immediately reflected in the other. |
Sharing Dev Services
Dev Services can be shared across multiple applications during development, allowing you to reuse the same containerized service for multiple projects running simultaneously. This is particularly useful for:
-
Distributed systems: Share a message broker (e.g., RabbitMQ, Kafka) or observability platform (e.g. Grafana LGTM) across multiple services.
-
Resource efficiency: Avoid running duplicate containers for the same service, especially for resource-intensive services (e.g., Docling, Ollama).
To enable/disable sharing for a specific Dev Service, you can set the arconia.dev.services.<service-name>.shared property. By default, sharing is enabled only for services where it makes sense, such as message brokers, observability platforms, and resource-intensive services.
|
Sharing Dev Services is only supported when running the application in dev mode. When running automated tests, Dev Services are never shared to ensure test isolation, consistency, and reliability. |
Pre-Requisites for Container Sharing
Container sharing relies on the Reusable Containers feature of Testcontainers, which is disabled by default. To enable it:
-
Create or edit the file
~/.testcontainers.propertiesin your home directory -
Add the following line:
testcontainers.reuse.enable=true
Once enabled, shared Dev Services will persist across application restarts and can be reused by other applications.
|
Reusable containers will not be automatically removed when no longer needed. You must stop and remove them manually using your container runtime (Docker/Podman) when they are no longer required. |
Resource Mappings
Dev Services support copying files and directories from your classpath or host filesystem into the container at startup. This can be useful for various scenarios, including for loading configuration files, seeding initialization data, or making static resources available to containerized services.
Resources are copied to the specified destination path inside the container at startup and are never changed on the host after being copied (read-only). This means that any modifications made by the container to these files will not persist or affect the source files on the host.
This strategy is preferred over mounting host directories as volumes, as it avoids potential issues with file permission mismatches, path resolution, and cross-platform compatibility.
Configuration
Resource mappings are configured through the arconia.dev.services.<service-name>.resources property. Each mapping requires two values:
-
Source path: Location of the resource on the classpath or filesystem;
-
Container path: Destination path inside the container.
For example, to copy a configuration file from the classpath into an OpenTelemetry Collector container:
arconia:
dev:
services:
otel-collector:
resources:
- source-path: otel-collector-config.yml
container-path: /etc/otelcol-contrib/config.yaml
Source Path Resolution
The source path supports multiple resolution strategies:
-
Automatic resolution: Without a prefix, Arconia first attempts to locate the resource on the classpath. If not found, it searches the filesystem. For example,
config/database.confwill be resolved from the classpath if available, otherwise from the filesystem. -
Explicit classpath: Use the
classpath:prefix to load resources from the classpath. For example,classpath:config/database.conf. -
Explicit filesystem: Use the
file:prefix to load resources from the host filesystem. For example,file:./config/database.conf.
Using explicit prefixes (classpath: or file:) improves clarity and readability, making it clear where the resource is being loaded from. It also avoids ambiguity and potential resolution issues, especially in complex projects with multiple resource locations.
|
Volume Mappings
Dev Services support binding files and directories from the host filesystem into the container at startup. This can be useful for various scenarios, including for persisting data generated by the containerized service or for sharing files between your host and the container.
Files or directories specified in the volume mappings are mounted from the host filesystem into the container at the specified destination path inside the container at startup and are mutable (read-write). Changes in either the host or the container will be immediately reflected in the other.
Since this provides direct read-write access between the host and container, use this feature with caution. Ensure that the mounted paths are secure and do not expose sensitive data or system files. Furthermore, be aware of potential file permission issues that may arise due to differences between the host and container environments.
|
It’s recommended to use volume mappings only when necessary. Instead, consider using resource mappings for most use cases where read-only access is sufficient. |
Configuration
Volume mappings are configured through the arconia.dev.services.<service-name>.volumes property. Each mapping requires two values:
-
Host path: Location of the file or directory on the host filesystem;
-
Container path: Destination path inside the container.
For example, to mount a configuration directory from the host filesystem into a PostgreSQL container:
arconia:
dev:
services:
postgresql:
volumes:
- host-path: ./postgresql/data
container-path: /var/lib/postgresql/data/pgdata
Networks and Ports
Dev Service containers are connected to the default Docker/Podman network and are accessible from your application via the local host and dynamically assigned ports.
Fixed Ports
By default, Dev Services use random available ports to avoid conflicts. However, you can configure fixed exposed ports when needed. Each service supports the arconia.dev.services.<service-name>.port property to specify a fixed port for exposing the primary service provided by the container.
Some Dev Services may expose multiple ports (e.g., management console ports). In such cases, the Dev Service will offer additional properties to configure fixed ports for those secondary services. For example, the RabbitMQ Dev Service provides the common arconia.dev.services.rabbitmq.port property for the main AMQP port and an additional arconia.dev.services.rabbitmq.management-console-port property for the management UI port.
A common use case for fixed ports is when other tools or services in your development environment need to connect to the Dev Service container using a known port, or for exposing UI consoles through well-known ports. For example, to expose Grafana on port 3000.
|
Using fixed ports may cause conflicts if another service is already using the port. Consider using fixed ports only when necessary. |
Startup Sequence
Control how Dev Services start using the spring.testcontainers.beans.startup property. It can be set to parallel or sequential. By default, Dev Services are started sequentially.
Global Configuration
In case you want to disable all Dev Services at once, you can set the arconia.dev.services.enabled property to false.
|
Disabling Dev Services globally overrides individual service settings. If global disabling is set, no Dev Services will start, regardless of their individual |
Actuator
When running the application in dev mode, a devservices actuator endpoint is auto-configured if Spring Boot Actuator is present in the classpath. This endpoint exposes information about the running Dev Services containers, helping you inspect and debug your development environment.
Usage
List All Dev Services
Retrieve information about all running Dev Services:
http :8080/actuator/devservices
Response example:
{
"docling": {
"name": "docling",
"description": "Docling Dev Service",
"containerInfo": {
"id": "dbbda8272b5dc8d2ccfa48d3723756d767eef727322d9c35e0fd4c44ba60e967",
"imageName": "ghcr.io/docling-project/docling-serve:latest",
"exposedPorts": [
{
"ip": "0.0.0.0",
"privatePort": 5001,
"publicPort": 45525,
"type": "tcp"
}
]
}
},
"postgresql": {
"name": "postgresql",
"description": "PostgreSQL Dev Service",
"containerInfo": {
"id": "cbf5a15cf5420eddd2daf0e912256b140c0ad067f9329f425a2ecdaa01008bc5",
"imageName": "docker.io/pgvector/pgvector:latest",
"exposedPorts": [
{
"ip": "0.0.0.0",
"privatePort": 5432,
"publicPort": 36803,
"type": "tcp"
}
]
}
}
}
Get Details for a Specific Dev Service
Retrieve detailed information about a specific Dev Service:
http :8080/actuator/devservices/postgresql
Response example:
{
"name": "postgresql",
"description": "PostgreSQL Dev Service",
"containerInfo": {
"id": "cbf5a15cf5420eddd2daf0e912256b140c0ad067f9329f425a2ecdaa01008bc5",
"imageName": "docker.io/pgvector/pgvector:latest",
"names": [
"/unwritten_mithrandir"
],
"exposedPorts": [
{
"ip": "0.0.0.0",
"privatePort": 5432,
"publicPort": 36803,
"type": "tcp"
}
],
"labels": {
"org.testcontainers.lang": "java",
"org.testcontainers": "true"
},
"status": "Up About 67 minutes"
}
}
The endpoint provides visibility into container IDs, image names, port mappings, and other runtime information useful for troubleshooting and debugging.
Arconia Dev Services vs. Spring Boot Development-time Services
Arconia Dev Services is a higher-level abstraction built on top of Spring Boot’s Testcontainers support. While both approaches leverage Testcontainers for provisioning services, Arconia Dev Services provides a more streamlined, zero-configuration experience.
Key Differences
The primary distinction is simplicity. Arconia Dev Services eliminates boilerplate code and configuration, allowing you to focus on development rather than infrastructure setup.
-
Arconia Dev Services
-
Spring Boot Development-time Services
dependencies {
testAndDevelopmentOnly 'io.arconia:arconia-dev-services-postgresql'
}
Run your application normally:
./gradlew bootRun
dependencies {
testAndDevelopmentOnly 'org.springframework.boot:spring-boot-testcontainers'
testAndDevelopmentOnly 'org.testcontainers:postgresql'
}
Create a test configuration class:
@TestConfiguration(proxyBeanMethods = false)
public class TestContainersConfiguration {
@Bean
@ServiceConnection
@RestartScope
PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:latest");
}
}
Create a test main class:
public class TestApplication {
public static void main(String[] args) {
SpringApplication.from(Application::main)
.with(TestContainersConfiguration.class)
.run(args);
}
}
Run from the test classpath:
./gradlew bootTestRun
Import the Testcontainers configuration in each test class needing the service:
@SpringBootTest
@Import(TestContainersConfiguration.class)
class ApplicationTests {
}
Migration Path
If your project already uses Spring Boot’s Testcontainers support, you can adopt Arconia Dev Services incrementally:
-
Add Arconia dependencies for services you want to manage automatically.
-
Keep existing Testcontainers configuration for custom or unsupported services.
-
Gradually migrate more services to Arconia as needed.
Both approaches work alongside each other, allowing smooth transitions without disrupting your workflow.
Feature Comparison
| Aspect | Arconia Dev Services | Spring Boot Development-time Services |
|---|---|---|
Dependencies |
Single dependency per service. |
Multiple dependencies per service. |
Code Requirements |
Zero additional code required |
Requires: |
Configuration |
Declarative via |
Programmatic configuration in Java code when defining container beans. |
Application Startup |
Standard commands: |
Special test classpath commands: |
Integration Testing |
Automatic service discovery and wiring: no imports or annotations needed. |
Requires explicit |
DevTools Live Restart |
Automatic persistence across restarts: containers survive application reloads. |
Requires |
Service Sharing |
Declarative via properties: |
Manual configuration when defining container beans with |
Customization |
Configuration properties for common scenarios. |
Full programmatic control. Direct access to Testcontainers API in bean definitions. |
Flexibility |
Opinionated with sensible defaults. Configuration properties are available for common use cases. |
Maximum flexibility. Full control over container lifecycle and configuration. |
Learning Curve |
Minimal |
Moderate |
Best For |
Rapid development, standard use cases, teams seeking simplicity. |
Advanced scenarios requiring custom container configuration or specialized setups |