https://github.com/peterrichards-lr/liferay-docker-manager
A professional command-line orchestrator for quickly standing up Liferay Portal and DXP environments using Docker Compose.
https://github.com/peterrichards-lr/liferay-docker-manager
automation cli docker docker-compose dxp ldm liferay liferay-docker-manager orchestrator python sales-engineering
Last synced: 21 days ago
JSON representation
A professional command-line orchestrator for quickly standing up Liferay Portal and DXP environments using Docker Compose.
- Host: GitHub
- URL: https://github.com/peterrichards-lr/liferay-docker-manager
- Owner: peterrichards-lr
- License: mit
- Created: 2026-03-24T17:44:28.000Z (3 months ago)
- Default Branch: master
- Last Pushed: 2026-05-08T11:10:50.000Z (about 1 month ago)
- Last Synced: 2026-05-08T11:39:21.020Z (about 1 month ago)
- Topics: automation, cli, docker, docker-compose, dxp, ldm, liferay, liferay-docker-manager, orchestrator, python, sales-engineering
- Language: Python
- Homepage: https://liferay.dev/b/liferay-docker-automation-python-scripts
- Size: 101 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: docs/README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: docs/SECURITY.md
- Roadmap: docs/roadmap.md
Awesome Lists containing this project
README
# Liferay Docker Manager (ldm)
A professional command-line orchestrator for quickly standing up Liferay Portal and DXP environments using Docker Compose.
> [!NOTE]
> **Project History:** This tool was originally born as part of the [liferay-docker-scripts](https://github.com/peterrichards-lr/liferay-docker-scripts) repository. It has since evolved into a standalone application to provide better modularity and multi-instance stability.
---
## Why use LDM?
`ldm` is designed to be both fast for power users and helpful for newcomers. It follows a consistent usage pattern:
1. **Sensible Defaults**: Whenever a standard Liferay convention exists, `ldm` uses it automatically (e.g., port `8080`, managed DB name `lportal`).
2. **Smart Context**: If you run a command from inside a project folder, `ldm` automatically detects the project context.
3. **Interactive Fallback**: If a required piece of information (like a project name or a Liferay tag) is missing from your command and cannot be detected, `ldm` will **prompt you interactively** or show you a list of choices.
4. **Graceful Abort**: You can type `q` at any interactive prompt to safely cancel the operation.
---
## 🛡️ Compatibility (Verified Environments)
The badges below represent our verified support for various Docker providers. Environments marked as **Hardened** have received specific logic refinements to handle complex file-sharing and permission scenarios.
| Architecture | Host OS | Docker Provider | Hardening | Verified |
| :--- | :--- | :--- | :--- | :--- |
| **Apple Silicon** | macOS 11+ | **OrbStack** |  | ✅ |
| **Apple Silicon** | macOS 11+ | **Docker Desktop** |  | ✅ |
| **Apple Silicon** | macOS 11+ | **Colima** |  | ✅ |
| **Apple Intel** | macOS 11+ | **Colima** |  | ✅ |
| **Windows PC** | Windows 11 | **Native WSL2** |  | ✅ |
| **Windows PC** | Windows 11 | **Docker Desktop** |  | ✅ |
| **Linux Workstation** | Fedora 43 | **Native Docker** |  | ✅ |
| **Linux Node** | Ubuntu 22.04 | **Docker Engine** |  | ✅ |
## Global Infrastructure
| Component | Verified Versions | Notes |
| :--- | :--- | :--- |
| **Traefik** | `v3.6.1+` | Automatic API version negotiation enabled. |
| **Elasticsearch** | `8.17.0`, `7.17.24` | Dual support with version-aware project sync. |
---
## Key Features
- **Multi-Instance Session Isolation**: Run multiple demos side-by-side on the same machine without session cross-talk. `ldm` automatically manages unique session cookie names and virtual hostnames.
- **Orchestrated Search Snapshots**: Save and restore the exact state of a demonstration, including the database, files, and **Elasticsearch 8.x index state**.
- **Service-Specific Lifecycle**: Manage individual components within a project surgically. Restart or view logs for a single extension without affecting the rest of the stack.
- **Client Extension Lifecycle**: Automatically detects and builds Server-Side Client Extensions (SSCE). Subdomains are automatically generated, and traffic is routed based on `LCP.json`.
- **Zero-Config SSL**: Automated HTTPS using `mkcert` and a global Traefik proxy. Works on Docker Desktop, **Colima**, and **WSL2**.
- **Proactive License Verification**: Automatically detects Liferay XML licenses in `common/`, `deploy/`, or `osgi/modules/` folders. Warns you before boot if a DXP license is missing or expired.
- **Fail-Fast Design**: Proactive environment checking. LDM verifies Docker reachability, volume mounts, resource allocations (CPU/RAM), and **Compose functionality** before execution, providing clean, actionable error messages instead of tracebacks.
- **Architecture-Aware**: The tool detects your OS automatically to fetch the correct optimized binary during self-updates.
---
## Documentation
- [Installation Guide](installation.md)
- [Architecture Overview](LDM_ARCHITECTURE.md)
- [Test & Validation Strategy](TESTING.md)
- [Security Posture & Disclosures](SECURITY.md)
- [Future Roadmap](roadmap.md)
---
## Scripting & Automation
LDM is designed to be pipeline-friendly. The `ldm doctor` command returns a non-zero exit code if critical environment issues are detected.
### Health Check Pipe
Ensure your environment is healthy before attempting to start a project:
```bash
ldm doctor --skip-project && ldm run my-project
```
### Automation Patterns
Check if services are running before executing operations:
```bash
# Start infrastructure only if it's not already running
ldm ps || ldm infra-setup --search
```
### CI/CD Integration
You can use LDM in automated scripts to verify infrastructure:
```bash
if ldm doctor --skip-project; then
echo "Environment is healthy, proceeding..."
else
echo "Critical environment failure!"
exit 1
fi
```
---
## Installation (Quick Start)
The standalone binary is the recommended way to use LDM.
```bash
# For macOS (Apple Silicon)
sudo curl -L https://github.com/peterrichards-lr/liferay-docker-manager/releases/latest/download/ldm-macos-arm64 -o /usr/local/bin/ldm
# For macOS (Apple Intel)
sudo curl -L https://github.com/peterrichards-lr/liferay-docker-manager/releases/latest/download/ldm-macos-x86_64 -o /usr/local/bin/ldm
# For Linux / WSL2
sudo curl -L https://github.com/peterrichards-lr/liferay-docker-manager/releases/latest/download/ldm-linux -o /usr/local/bin/ldm
# Make it executable
sudo chmod +x /usr/local/bin/ldm
```
For detailed instructions and Windows setup, see the **[Full Installation Guide](installation.md)**.
---
## Quick Start
> [!IMPORTANT]
> **Binary vs Script**: If you have installed the **Standalone Binary**, use `ldm` in your commands. If you are using the **Manual Installation**, use `./ldm` (on Linux/macOS) or `ldm.bat` (on Windows) from the root of this repository.
```bash
# 1. THE CONFIDENCE BOOSTER: Run Liferay with pre-configured samples
ldm run my-sample-project --samples
# 2. THE DEVELOPER FLOW: Initialize from a workspace and start monitoring
ldm init-from /path/to/workspace my-project
# 3. THE ARCHIVE FLOW: Import a static snapshot of a workspace
ldm import /path/to/workspace my-static-project
# 4. THE RECOVERY FLOW: Re-create a deleted project from a snapshot folder
ldm run my-recovered-project --snapshot ~/Desktop/old-baseline-snapshot
# Monitor an existing project (manually)
ldm monitor /path/to/workspace
```
---
## Command Reference
### `list` (alias: `ls`)
Display a tabulated overview of all initialized LDM sandbox environments.
```bash
ldm list
ldm ls
```
### `run` (alias: `up`)
Initialize and start a project stack.
```bash
# Run with a specific tag and virtual hostname
ldm run --tag 2024.q4.0 --host-name demo.local
# Using the alias
ldm up demo
# Initialize with "Confidence Booster" samples
ldm run demo --samples
# Interactive run (will prompt for version and project name)
ldm run
```
#### SSL Defaults (New Projects)
LDM uses smarter defaults for SSL based on your hostname. When a custom `--host-name` is used, SSL is enabled by default to support modern Liferay features like Client Extensions.
| Command | Host Name | SSL Default | Access URL |
| :--- | :--- | :--- | :--- |
| `ldm run` | `localhost` | `False` | `http://localhost:8080` |
| `ldm run --host-name my.local` | `my.local` | `True` | `https://my.local` |
| `ldm run --no-ssl` | `localhost` | `False` | `http://localhost:8080` |
| `ldm run --host-name my.local --no-ssl` | `my.local` | `False` | `http://my.local:8080` |
### `init-from` (Live Link)
Initialize a project from a source workspace and establish a **persistent link**. This command records the workspace path in the project metadata and automatically starts the `monitor` process to sync your code changes in real-time.
```bash
ldm init-from ~/repos/my-workspace my-project
```
### `import` (Static Snapshot)
Scaffold a new project by taking a **one-time static import** of an existing workspace. This project is detached from the source; changes to the source workspace will not be synced. Follows the same internal deployment sequence as `init-from`.
```bash
ldm import ~/repos/my-workspace my-static-project
```
### `monitor`
Restarts the background watch process for a project linked to a Liferay workspace. This command can **only be used for projects created with `init-from`**. It automatically syncs built artifacts (`.jar`, `.war`, `.zip`) whenever they are updated in the workspace.
```bash
ldm monitor [project_name] --delay 2.0
```
### `logs`
View real-time logs. Supports filtering by project and specific service.
```bash
ldm logs [project] [service]
# Examples:
ldm logs # All logs for current project
ldm logs demo # All logs for 'demo' project
ldm logs demo liferay # Only Liferay logs for 'demo'
ldm logs demo my-extension # Only logs for a specific client extension
```
### `stop`, `restart`, `down` (alias: `rm`)
Manage the lifecycle of a project or a specific service.
```bash
ldm stop [project] [service] # Stop containers gracefully
ldm restart [project] [service] # Stop and then start
ldm down [project] [service] # Remove containers (and optionally -v volumes)
ldm rm [project] # Alias for 'down'
# Examples:
ldm restart # Full stack restart (graceful stop + run)
ldm restart demo liferay # Surgical restart of just the Liferay container
ldm down --volumes # Tear down stack and clear all database/data state
ldm rm demo -v # Remove 'demo' and its volumes
```
### `deploy`
Hot-deploy built artifacts or rebuild extension images.
```bash
ldm deploy [project] [service] --rebuild
# Examples:
ldm deploy # Sync all artifacts and refresh stack
ldm deploy demo my-ext --rebuild # Rebuild and restart one extension
```
### `scale`
Scale services within a project for multi-node simulation and clustering tests.
```bash
ldm scale [project] service=count
# Examples:
ldm scale demo liferay=2 # Scale Liferay to 2 nodes (enables clustering)
ldm scale demo my-ext=3 # Scale a client extension to 3 nodes
```
### `snapshot` & `restore`
Backup and recover project states, including files, DB, and search indices.
**Examples:**
```bash
# Create a named snapshot
ldm snapshot demo --name "post-setup-gold-standard"
# List snapshots for a project
ldm restore demo --list # Non-interactive list of all snapshots
ldm restore demo --index 1 # Restore to index 1
```
### `shell` & `gogo`
Jump into a container shell for deep inspection or connect to the OSGi Gogo console for runtime management.
**Interactive Shell Examples:**
```bash
# Enter bash in the Liferay container
ldm shell demo
# Common Shell Tasks (inside container):
# 1. View live Tomcat logs
cd tomcat/logs && tail -f catalina.out
# 2. Check injected environment variables
env | grep LIFERAY
# 3. Verify mounted OSGi configurations
ls osgi/configs
```
**Gogo Shell Examples:**
```bash
# Connect to the Gogo shell (requires --gogo-port during run)
ldm gogo demo
# Common Gogo Commands:
# 1. List all active bundles
lb
# 2. Check for unresolved dependencies
diag
# 3. List declarative services (SCR)
scr:list
```
### `env`
Manage persistent environment variables in project metadata.
```bash
ldm env [project] KEY=VALUE
ldm env [project] --remove KEY
ldm env # Interactive manager (view and edit all)
```
### `cloud-fetch` (Fetch Cloud State)
Synchronize an **existing local project** with data, logs, and configuration from Liferay Cloud (LCP). This is used for local debugging and state hydration, not for importing source code.
> [!NOTE]
> **Prerequisite:** You must have the [LCP CLI](https://customer.liferay.com/documentation/cloud/latest/en/reference/command-line-tool.html) installed and authenticated (`lcp login`).
```bash
# 1. Discover available cloud environments
ldm cloud-fetch --list-envs
# 2. Stream remote logs from UAT to your local terminal
ldm cloud-fetch [project] uat liferay --logs
# 3. Pull the latest Cloud backups (DB/Data) into your local project snapshots
ldm cloud-fetch [project] uat --download
# 4. Sync Cloud environment variables to your local project metadata
ldm cloud-fetch [project] uat --sync-env
```
### `log-level`
Manage Liferay internal logging levels (Log4j2) without restarts.
```bash
# List current custom levels
ldm log-level --list
# Set a specific category to DEBUG
ldm log-level [project] --bundle portal --category com.liferay.portal --level DEBUG
# Interactive configuration
ldm log-level
```
### `doctor`
Verify host environment health, Docker resources (CPUs/Memory), and project dependencies.
```bash
ldm doctor # Health check for current/selected project
ldm doctor --all # Batch validate every project in your workspace
```
### `status` (alias: `ps`)
Lightweight summary of all active global services and running projects.
```bash
ldm status
ldm ps
```
### `browser` (alias: `open`)
Launch the project URL in your system browser. If no project is specified, LDM will present a list of currently running projects to select from.
```bash
ldm browser [project]
ldm open [project]
```
### `upgrade`
Automatically download and install the latest version of LDM for your architecture. Includes integrity verification.
```bash
ldm upgrade # Standard upgrade to latest
ldm upgrade --repair # Re-download current version to fix integrity issues
```
### `renew-ssl`
Refresh project-specific SSL certificates immediately.
```bash
ldm renew-ssl # Interactive selector
ldm renew-ssl demo # Renew for 'demo' specifically
ldm renew-ssl --all # Renew certificates for every project
```
### `init-common`
Initialize or recreate the baseline global configuration (`common/` folder) from internal resources.
```bash
ldm init-common
```
### `infra-setup`, `infra-down`, `infra-restart`
Independently manage global infrastructure services (Traefik proxy, Search sidecar, Bridge).
```bash
ldm infra-setup # Start global services manually
ldm infra-setup --search # Also initialize the Global Search container
ldm infra-down # Stop and remove global services
ldm infra-restart # Reset all global services in one go
```
> [!TIP]
> **Sidecar Fallback**: If the Global Search (ES8) container is not running, `ldm` will automatically default to Liferay's internal **Sidecar** search. It also cleans up global ES configurations in your project to ensure the Sidecar initializes correctly.
### `migrate-search`
Migrates a project from using the internal Sidecar search to the shared **Global Search container**.
```bash
ldm migrate-search [project]
```
**What it does:**
1. Verifies the project is stopped.
2. Ensures the Global Search container is running (offers to start it).
3. Deletes internal indices (`data/elasticsearch7` or `data/elasticsearch8`).
4. Re-syncs Global ES configurations from `common/`.
5. Offers to restart the project immediately.
### `reset`
Surgically clear project data folders. This command requires the project to be stopped.
```bash
ldm reset [project] [target]
```
**Available Targets:**
- **`state`** (Default): Clears the `osgi/state` folder.
- **`search`**: Clears internal Sidecar indices.
- **`db`**: Clears the Hypersonic database (if used).
- **`global-search`**: Deletes the project's indices from the shared Global Search container.
- **`all`**: Performs all of the above.
**Examples:**
```bash
ldm reset demo state # Clear OSGi state for 'demo'
ldm reset demo search,db # Clear local search and DB
ldm reset demo all # Total project data wipe
```
### `prune`
Identify and remove orphaned resources. This command scans your Docker environment for containers and global search snapshots that no longer have a matching project folder on your disk.
```bash
ldm prune
```
**What it cleans:**
- **Orphaned Containers**: Any container with the `com.liferay.ldm.managed` label whose project folder was manually deleted.
- **Orphaned Search Snapshots**: Leftover Elasticsearch 8.x snapshots in the global vault from deleted projects.
- **Temporary Files**: Residual `.*.tmp` files left behind by interrupted sync or build operations.
### `clear-cache`
Clears the local Docker Hub tag cache. LDM caches Liferay tags for 24 hours to improve performance; use this command to force a fresh fetch from the registry.
```bash
ldm clear-cache
```
### `config`
View or set global LDM configuration settings (stored in `~/.ldmrc`).
```bash
ldm config # View all global settings
ldm config key value # Set a global preference
ldm config key --remove # Remove a preference
```
---
## Configuration Files
- **`logging.json`**: Managed via `log-level` command.
- **`common/`**: Files here (configs, XML licenses, LPKG files) are synced to all project stacks.
- **`services/`**: Place standalone `Dockerfile` directories here for orchestration.
---
## Prerequisites
- **Docker Engine**: Docker Desktop, Colima, or native WSL2.
- **Docker Compose**: **v2 (Plugin)** is mandatory. Legacy v1 standalone is not supported.
- **Resources**: Recommended **4 CPUs and 8GB RAM** allocated to Docker.
- *Note*: `ldm doctor` expects these minimums. If you allocate exactly 8GB, Docker may report ~7.7GB due to system overhead; the tool accounts for this by allowing a 7.5GB threshold.
- **Python**: 3.10+ (if not using binary)
- **mkcert**: (Optional) For automated local SSL.
### Increasing Resources in Colima
If `ldm doctor` reports insufficient resources in Colima, you can increase them with these commands:
```bash
colima stop
colima start --cpu 4 --memory 8
```
---
## Interactive Mode Tips
- **Smart Project Detection**: `ldm` prioritizes project detection in this order:
1. Positional argument (e.g., `ldm run my-project`).
2. CLI flag (e.g., `ldm run -p my-project`).
3. The current working directory (if it's an LDM project).
4. An interactive list of all discovered projects.
- **Quick Quit**: You can type `q` at any interactive prompt to safely abort the current command.
- **Bypass Prompts**: Use the `-y` or `--non-interactive` flag to skip all confirmations and use default values. This is ideal for scripts and CI/CD pipelines.
- **Tag Discovery**: When running `ldm run` without a version tag, the tool will offer to fetch the latest available tags from Docker Hub based on your release type preference (LTS, QR, etc.).
---
## 🛠️ Development & Building
If you want to contribute to LDM or test your changes locally, follow these steps.
### 1. Run from Source (Live Development)
The easiest way to develop is to install LDM in "editable" mode. This allows your changes to the `ldm_core` package to take effect immediately.
```bash
# Clone the repo
git clone https://github.com/peterrichards-lr/liferay-docker-manager.git
cd liferay-docker-manager
# Install in editable mode
pip install -e .
# Run the entry point
python3 liferay_docker.py --help
```
### 2. Building Standalone Binaries
You can build a single-file executable to test how the tool behaves as a binary.
#### **Option A: Shiv (Official CI Method)**
Used for macOS and Linux. Fast and lightweight, but requires `python3` to be present on the host.
```bash
# Build only
./scripts/package-shiv.sh
# Build and install to /usr/local/bin/ldm (requires sudo)
./scripts/package-shiv.sh --install
```
#### **Option B: PyInstaller (True Standalone)**
Bundles the Python interpreter inside the file. Works even on machines without Python installed.
```bash
# Build only
./scripts/package-pyinstaller.sh
# Build and install to /usr/local/bin/ldm (requires sudo)
./scripts/package-pyinstaller.sh --install
```
The resulting binary will be found in the `dist/` folder (for PyInstaller) or the root (for Shiv).
## License
MIT © Peter Richards