Why teams running Apache Fineract in Docker for production need more than the demo compose file
The published compose files are not production-ready. A team that has run the demo stack and now has to operate Fineract for a regulated lender or bank should treat that stack as a learning environment only. The gap is not in the application. It sits in configuration, secrets, instance roles, persistence and upgrade discipline. The demo ships with a default development login, a test profile and settings chosen to start quickly on a laptop, and none of those defaults should reach a system that holds client and loan data. The README is direct about the scale of the problem: a production deployment can be complex, costly and time-consuming, the project does not provide a comprehensive production deployment guide, and organizations may pay a vendor for deployment and maintenance. Plan for that work as a separate project with its own owner, not as a tidy-up of the demo.
Containers are the right choice when you want repeatable images, declared configuration and an orchestrator or runtime you already operate. They are a weaker fit when nobody on the team can run the container platform, the database and backups reliably, or the bank's change process cannot accept image-based releases. Fineract is headless, with REST APIs and no user interface of its own, and it is multi-tenant: requests carry a Fineract-Platform-TenantId header and tenant connections come from a tenants database. That means one running container is not one bank. Each tenant's database settings, the tenants database itself and the choice of which instance type a container plays all have to be defined in the container configuration, and your team should confirm how each tenant is registered before the first deployment.
Start by listing every value the demo hard-codes, then decide where each one will live: credentials in a secrets store, database endpoints and tenant settings as environment variables, and the read, write and batch roles set per container. Confirm against the Fineract platform documentation which settings your chosen release reads, because the documentation is the reference for instance types and Liquibase behavior. Also agree how you will move between image tags, since the project publishes official releases quarterly and archives end-of-life releases. A team that cannot name its owner for each of these decisions is not ready to run Fineract in containers.
What the demo compose setup leaves out for production
The published compose files are built to get a Fineract instance running quickly on a developer machine. Each gap below is a default that is safe for a demo and unsafe for a live core banking system. Confirm every item against the current compose files in the repository before you rely on them.
Default development login
The README shows a development login of mifos with a matching password, and that account must not survive into any real deployment. Remove or replace it in the authentication configuration, then confirm which identities can reach the API and how OAuth2 or basic authentication is enforced for each tenant. Check the compose files for any environment variable that seeds this account.
Test profile in compose
The demo files start Fineract with a test-oriented Spring profile and seed data that exist for automated tests, not for operations. Confirm which profiles the compose service activates and remove the test profile from the production service definition. Use a profile list that you can review in version control, and make sure no seeded tenant or sample client data reaches the production database.
Built-in self-signed TLS
The embedded server can present a self-signed certificate, which clients will reject or users will learn to click through. The project strongly encourages HTTPS only and documents SSL settings through environment variables such as FINERACT_SERVER_SSL_ENABLED. Decide whether TLS terminates inside the container or at a proxy or load balancer, then confirm the certificate chain, the forwarded headers and the port that is exposed.
Credentials and tenant settings in files
Demo compose files commonly put database users, passwords and tenant connection details in plain environment entries or checked-in files. Move these into a secret store or the orchestrator's secret mechanism and inject them at start. Confirm how the tenants database connection is supplied, who can read the container configuration, and that rotation does not require rebuilding the image.
Single instance versus read, write and batch roles
The demo runs one container that does everything, including schema changes, API traffic and background batch work. The Fineract documentation describes read, write and batch instance types set by environment variables, and recommends one write instance, one batch instance and multiple read instances for high load. Confirm the instance type variables in the compose file and decide whether a single container is acceptable for your volume.
Logging and backup wiring
Demo files typically send logs to the container console and do not define retention, shipping or a backup path for the database. For a core banking system, decide where application logs go, how long they are kept and who reviews them, and confirm that PostgreSQL backups cover the tenants database and every tenant schema. Test a restore before go-live rather than assuming the compose setup provides one.
Container configuration options and when each fits
This table compares the container layouts available for Fineract, from a single combined instance to separate write, batch and read instances on an orchestrator. Read each row for the setup it describes, the trade-off it carries and the point at which it stops being enough. The main takeaway is that the documented split of one write instance, one batch instance and several read instances is the layout to plan toward for high load, while simpler layouts suit tests and small environments.
| Option | Trade-off | When it fits |
|---|---|---|
| Single combined instance on Compose | Simplest to run, but one process handles API traffic, schema changes and background jobs together | Local evaluation or a small test environment where load and downtime tolerance are low |
| Separate write, batch and read instances set by environment variables | Role-specific instances isolate heavy batch work from API traffic, at the cost of more containers and config to manage | Production deployments that need predictable API response during Close of Business and reporting |
| Read instances on database read replicas | Spreads read-heavy API load across replicas, but requires replica lag monitoring and separate connection settings | High read volume, as the documentation recommends for high load, after the write path is sized |
| Custom image built on apache/fineract | Lets you add plugin and driver JARs, but every Fineract release requires a rebuild and retest | Deployments that depend on plugins or extra JDBC drivers not in the official image |
| Compose-based host | Quick to operate on one server, but limited restart, scaling and rolling-upgrade options | Single-site installs with a small operations team and a documented restore procedure |
| Orchestrator such as Kubernetes | Supports rolling upgrades, health checks and separate migration jobs, but adds cluster operations to the scope | Multi-instance production layouts that need the write, batch and read split and a repeatable upgrade path |
| Upgrading by image tag | Pinning a tag makes releases explicit, but tags must be checked against the current stable release and end-of-life notices | All production layouts; confirm the target release in the project documentation before each change |
Setting tenant database connections through environment variables
Fineract is multi-tenant, so a single running instance serves several isolated tenants, and each API request identifies its tenant with the Fineract-Platform-TenantId header. The platform reads the connection details for each tenant from a separate tenants database, so the database host, port, database name and credentials for the tenants database are the first settings to get right in a container. In a production compose file or orchestrator manifest, these values are supplied as environment variables on the Fineract containers rather than baked into the image, which keeps one image usable across test, staging and production.
Put the credentials in a secret store or in orchestrator secrets, not in the compose file or the image. A compose file is usually committed to source control and copied between hosts, so a password written there tends to outlive the environment it was meant for. Inject the variables at runtime from a secret manager, Docker secrets or Kubernetes secrets, and restrict who can read them. Also confirm that the database role has only the privileges Fineract needs, and that the password rotates without rebuilding the image.
The exact variable names change between releases, so do not copy them from an older tutorial or blog post. Confirm the names for the tenants database and for tenant schema access against the current Fineract documentation and the docker-compose and configuration files in the apache/fineract repository for the version you deploy. The official Docker image ships only the PostgreSQL JDBC driver, so the database must be PostgreSQL. Plan a test that starts the image with your production-style variables and confirms that a request with each tenant header reaches the correct tenant database.
Steps to convert the demo stack into a production container setup
This sequence turns the published demo compose files into a container setup with a pinned release, externalized tenant and credential settings, controlled database migrations, and logs and restarts you have tested. Each step closes with a check you can record before the next one starts.
Pin the image to a release tag
The platform team replaces any floating or latest image reference with a specific Apache Fineract release tag taken from the project's published releases. Record the tag in the deployment repository so every environment runs the same build. The step is done when the running containers report the expected image tag and the tag matches the one in version control. Confirm the tag against the release notes for the version you plan to run, since the project publishes new releases quarterly and archives end-of-life releases.
Remove the test profile and demo data
Strip the test profile, sample tenant data and any seed scripts from the compose or manifest files used for production. Keep a separate file for local development if the team still needs it, so production definitions cannot pull in demo settings by accident. The step is done when a rendered configuration of the production stack contains no test profile and no demo tenant or client records are created on first start. Your reviewer should check this rendered output, not only the source files.
Externalize tenant database and credential settings
Move the database host, port, tenant identifiers, database user and password out of the image and compose file into environment variables or a secrets store that your platform controls. Use the tenant database settings the Fineract documentation describes, and keep the tenants database and tenant schemas consistent with what your PostgreSQL team provisioned. The step is done when the configuration renders from secrets at deploy time and a search of the image and repository finds no database password. Ask your database team to confirm the account has only the privileges the application needs.
Replace the default login before first use
The published development login is a well-known default, so the security owner changes the administrator credentials and any OAuth2 client secrets before the environment accepts real traffic. Generate the new values in your secrets store and set them through configuration rather than through the API. The step is done when a login attempt with the default username and password is rejected in the production environment and the new credentials succeed. Record the test result as evidence for your access review.
Configure HTTPS or a reverse proxy
Decide whether Fineract terminates TLS itself, using the SSL settings the documentation exposes through environment variables, or sits behind NGINX or a cloud load balancer that terminates TLS. Replace the built-in self-signed certificate with one issued by your certificate authority in either case. The network team confirms that only the proxy or load balancer is reachable from outside the private network. The step is done when a plain HTTP request to the public endpoint fails, the certificate chain validates from a client, and forwarded headers reach the application as expected.
Separate instance roles and run migrations once
Deploy distinct containers for write, batch and read roles using the instance-type environment variables, and point read instances at database read replicas only if your PostgreSQL design includes them. Run Liquibase migrations on a single write instance, since the documentation states migrations run only there. Wait for the migration run to finish before starting batch or additional write containers. The step is done when the migration log reports completion, the schema version matches the image tag, and the batch container starts only after that check passes.
Ship container logs to your collector
Configure the container runtime or log driver to forward application and access logs to the central collector your security operations team uses, and set the log level for production rather than debug. Confirm that tenant identifiers and request metadata appear in the logs without exposing passwords, tokens or personal data. The step is done when a test request produces a searchable entry in the collector within the retention and alerting rules your team set. Ask your security team to review a sample of log lines before go-live.
Test a restart and a rollback
Restart the write, batch and read containers in turn and confirm each returns to healthy without re-running migrations or changing data. Then deploy the previous release tag to a staging copy of the database and confirm the rollback path works, including any schema behavior the upgrade notes describe. Record the image tags, migration outcomes and test results in the change record. The step is done when both the restart and the rollback complete with the expected tag running and the application answering authenticated API requests. Repeat this test before every upgrade.
Logging and upgrades by image tag
Route the container's standard output into your central logging system from day one, and decide before go-live what the Fineract container is allowed to write. Docker captures whatever the Java process prints to stdout and stderr, so the collector (for example, a node agent or sidecar that ships to your SIEM or log platform) should read from the container runtime rather than from files inside the image. Confirm with your platform team which log driver your container host uses and how retention is set. Keep Fineract's log level at INFO or higher in production, and reserve DEBUG or TRACE for a time-boxed investigation in a non-production environment. Set levels per environment through the Spring logging configuration you supply at deployment, not by editing the image. Review the output from a staging run to confirm that request bodies, OAuth2 tokens, HTTP basic credentials and tenant database passwords never appear in the log stream, and check that the development login documented in the README has been replaced.
Pin every environment to an explicit image tag, never latest, and record the tag in your change record and deployment manifests. The Fineract project creates official releases quarterly, at the end of each quarter, under the ASF release policy, and archives end-of-life releases. Before you move to a newer tag, read the release notes and the upgrade guidance for every version between your current and target release, and confirm with the project which of your installed plugins or custom images must be rebuilt. Rehearse the upgrade on a restored copy of the tenants database and every tenant schema, not on an empty database. A tag change can include Liquibase migrations, which must complete before the new image serves traffic. Plan for a single write instance to run the migration first, time the run on your data volume, and agree a rollback point, such as a verified database backup taken just before the migration starts. Ask your vendor or the upstream project which releases carry the migrations you will meet.
Security and operational considerations for containers
The published compose files prioritize a quick demo, so each control below has to be added deliberately before go-live. The cards cover identity, runtime, network, secrets, base images and transport, and each one names a check to run against your own platform and security policy.
Replace default credentials
The Fineract README shows a default development login of mifos with a matching password for OAuth2 and basic authentication examples. Treat that account as a known credential and make sure it is changed or disabled in every tenant before any environment is reachable. Confirm the change in each tenant, not only the default one, and confirm that the platform admin accounts follow your own password and access policy.
Run containers as non-root
Confirm that the image you deploy runs its Java process under a non-root user and that the container runtime enforces this, rather than relying on the image defaults alone. Where the platform allows it, set a read-only root filesystem and mount only the directories the application must write to, such as temporary space for logs. Check these settings against your admission policy, because a container that passes in development can still fail under stricter cluster rules.
Restrict paths to the database
Only the Fineract instances should reach PostgreSQL, and only on the ports and hosts your design lists. Separate network policies for write, batch and read instances help limit what a compromised read container can reach. Confirm that the tenants database and tenant schemas are reachable only from Fineract, and that database administrative access goes through a separate, audited path.
Keep secrets out of images and code
Tenant database passwords, OAuth2 client secrets and keystore passwords should arrive at runtime from a secret store or orchestrator secret, not from a Dockerfile, a compose file committed to version control or an image layer. Check the image history and build logs for accidental values, and confirm that your repository scanning blocks committed credentials. Rotation steps should be written before the first production run.
Scan and patch base images
Each Fineract image inherits layers from its base image and the Java runtime, so vulnerabilities can enter through layers you did not write. Scan images in your registry before deployment, rebuild on a defined schedule, and track which image tag is running in each environment. Official releases are created quarterly according to the project's release policy, so plan how a new Fineract release reaches your registry and how you test it before promoting it.
HTTPS only with forwarded headers
The Fineract documentation strongly encourages HTTPS only and documents SSL settings through environment variables such as FINERACT_SERVER_SSL_ENABLED. Decide whether TLS terminates in Fineract or at a reverse proxy or load balancer, then confirm that forwarded headers are trusted only from that proxy. Verify that plain HTTP requests are rejected or redirected in every environment, including internal test tiers that carry real client data.
Limits to confirm in your environment
The published compose files are a starting point, not a production baseline. The cards below list the points where your release, runtime, account volume and security policy decide whether the container setup holds up, and each one needs a check against your own environment before you commit to a design.
Exact variable names per release
Compose service definitions, environment variable names and profile names can change between Fineract releases. Confirm the exact keys for the release you plan to run against the documentation for that version, not against older blog posts or the demo files. Pin the image tag, then diff the variables your template sets against the release notes before each upgrade. A misspelled tenant database key fails quietly in some setups, so check connectivity to the tenants database after every change.
Supported runtimes and orchestrators
Confirm which container runtime, orchestrator and version your platform team supports for Fineract. Docker Compose suits a single host or a small pilot, while larger deployments usually move to Kubernetes with separate read, write and batch workloads. Ask whether your cluster admission rules, image signing policy and node sizing accept the official image without modification, and whether your team can operate the chosen runtime during an incident.
Custom image for plugin JARs
If you need plugin or JDBC driver JARs beyond what the official image ships, you will need a derived image. The official image includes only the PostgreSQL JDBC driver, so any other driver or plugin must be added in a build step. Confirm who owns that build, how it is rebuilt when a new Fineract release arrives, and how it is scanned and promoted through your registry before it reaches production.
Close of Business at your volume
Close of Business runs as a batch job that can take several hours on deployments with millions of accounts. Confirm with your team how many accounts you expect at go-live and in year three, and whether a single batch instance finishes the nightly run inside your window. If it does not, plan remote partitioning across worker nodes and test it with production-like data. Do not assume the demo container sizing will hold at your account volume.
TLS and secrets policy
Decide how TLS terminates and where tenant database credentials and the default login are stored. The default development login must be replaced, and the embedded SSL settings and any reverse proxy in front of the container need to match your certificate authority and key management policy. Ask your security team whether environment variables for secrets are acceptable, or whether they require a secrets manager and file-mounted credentials before approval.
Logging and retention approval
Container logs leave the host through your logging driver, and their destination, retention and access rules must match your audit requirements. Confirm where Fineract application logs go, who may read them, and whether personal data appears in them. Ask your compliance lead to approve the log pipeline before go-live, since changes after an audit finding are expensive.
Questions teams ask before running Fineract in Docker in production
Can our team run Apache Fineract in Docker in production without a partner?
Yes, many teams can, but only if they already operate PostgreSQL, container platforms and a secrets process at production standard. The Fineract README warns that a production deployment can be complex, costly and time-consuming, and that the project does not provide a comprehensive production deployment guide. Before deciding, check whether you have people who can own the tenant database settings, instance roles, logging, backups and the upgrade test cycle after go-live. If any of these sit with no owner, a partner can take on that work under a written scope.
What drives the effort of a Fineract Docker production setup?
The main drivers are the number of instance roles, the number of tenants, how secrets are delivered, and how much logging and upgrade testing is required. A single read instance is simpler than a setup with one write instance, one batch instance and several read instances on replicas, as the Fineract documentation recommends for high load. Each tenant adds database settings to manage and back up. Secrets handling, log shipping to your monitoring stack and a repeatable upgrade test against your own data all add scope. Ask for each of these to be listed as separate deliverables in any quote.
What skills does our staff need for this work?
Your staff need working knowledge of three areas: container images and runtime configuration, PostgreSQL administration, and security controls for a system that holds financial records. In practice that means someone who can read a Dockerfile and a compose file, configure environment variables without writing secrets into images, define database roles and connection settings, and review TLS and authentication settings. Someone also needs to own the decision to change the default development login, which the README says must be replaced before any real deployment. Confirm these skills in your own team before choosing between internal work and a partner.
How long does a production Fineract Docker setup take?
The duration depends on scope, and no fixed figure applies to every organization. The main factors are the number of instance types, the number of tenants, the state of your existing PostgreSQL and container platform, the security review your organization requires, and how much testing against your own configuration is needed before go-live. Ask any provider for a timeline tied to a written scope with named deliverables and acceptance checks, and ask which of your teams must be available for reviews and approvals.
Can DeployOpen give a fixed-scope quote for this work?
Yes. Most DeployOpen engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts. A quote follows from that written scope, so the scope should state the instance roles to be configured, the tenants and database settings in scope, the secrets approach, the logging design, the image and tag policy, and the upgrade test method. DeployOpen does not publish a price list. Ask for the quote to show each deliverable separately so you can compare it with an internal estimate.
What recurs after go-live for a Fineract container setup?
Recurring work includes applying security patches to the base image and the operating system layer, tracking Fineract releases, and testing each new image tag against your configuration and data before promotion. The project creates official releases quarterly and archives end-of-life releases, so an upgrade calendar is needed. Log retention, credential rotation and periodic review of global configuration after upgrades also recur. Ask any partner whether these tasks are included in a support retainer or handled by your team, and what the expected response process is for a failed upgrade test.
Can we harden the published demo compose files instead of rebuilding them?
You can start from them, but the demo files are not production-ready as published, so hardening them means changing several defaults rather than adding a few settings. The work includes removing the test profile, replacing the default development login, moving tenant database settings into environment variables or a secrets source, setting logging that your monitoring stack can read, and pinning images by tag. Treat the demo files as a reference for service names and wiring, then review each setting against your production standard. Ask whether the result will be documented as a deployment baseline your team can rebuild.
How DeployOpen scopes and delivers a Fineract container setup
DeployOpen plans, implements, hardens, backs up, upgrades, documents and supports self-hosted open-source platforms inside the client's own infrastructure, including the cloud accounts, data centers or air-gapped networks where Fineract will actually run. For a Docker production setup, that means the engagement covers the image source and tag policy, the non-demo compose or orchestration files, the removal of the test profile, the tenant database settings passed through environment variables, log routing, secrets handling and the upgrade procedure. Each of those items becomes a named deliverable in the written scope rather than an informal assumption.
Most engagements are fixed-scope, so the scope document is where the decisions get made before any work starts. Expect it to name the Fineract version and image tag, the PostgreSQL location and how the tenants database is provisioned, which instance types (write, batch or read) run as containers, how TLS is terminated, and who owns the rollback steps for each upgrade. A quote follows from that written scope, so the reader can compare offers on the same deliverables. Ask any partner to show which of these items is included, which is excluded and which depends on decisions still open on the client side.
Ongoing work is available as a retainer for the parts that recur after go-live, such as applying new image tags after each quarterly Fineract release, reviewing logs and patching the base images and surrounding services. Confirm with DeployOpen or any other provider how release notices are tracked, who approves a tag change in your environment and what response expectations are written into the retainer. DeployOpen prepares the systems and evidence for compliance assessments but does not issue audit reports or certifications, so the container controls you commission should be described in terms your independent auditor can test.

