Overview of the Problem
ColdFusion running in a Docker container sometimes fails to start or exits immediately after launch. This typically means the container process (Tomcat/ColdFusion runtime) encountered a fatal error before reaching a steady “listening” state. Failures on startup can stem from misconfigured environment variables (like EULA acceptance or admin password), invalid JVM memory options, missing dependencies, file permissions on mounted volumes, port conflicts, or customizations (server.xml, package installs) that break the boot sequence.
When this happens, you’ll often see the container cycling in “restarting” status, sitting in “unhealthy,” or exiting with a non-zero code. The root cause is almost always visible in container logs, Tomcat logs, or ColdFusion logs—if you know where and how to look.
Symptoms and What Startup Failure Looks Like
- Container exits within seconds or repeatedly restarts.
- Health check stays “starting” then flips to “unhealthy.”
- No response on the expected port (e.g., 8500 or 8080).
- “docker logs” shows a stack trace, a password/EULA error, or a Tomcat bind exception.
- ColdFusion log files show OutOfMemoryError, permission errors, or module install failures.
Examples from logs:
SEVERE: Failed to initialize end point associated with ProtocolHandler [“http-nio-8500”]
java.net.BindException: Address already in use: bind
Startup aborted. EULA must be accepted. Set environment variable acceptEULA=YES
java.lang.OutOfMemoryError: Java Heap space
java.io.FileNotFoundException: /opt/coldfusion/cfusion/logs/coldfusion-out.log (Permission denied)
Possible Causes
- Missing or invalid required environment variables (e.g., EULA acceptance, admin password).
- Ports already in use on the host (bind conflicts).
- JVM options misconfigured (heap too big or invalid flags).
- File permission or ownership problems on mounted volumes (logs, config, webroot).
- SELinux/AppArmor contexts blocking writes to mounted paths.
- ColdFusion package installs failing during startup (network/proxy issues).
- Custom server.xml misconfiguration or connector conflicts.
- Architecture mismatch (running amd64 image on arm64 hosts) or unsupported base image tag.
- Resource limits too low (memory/CPU/ulimits) causing immediate termination.
- Application code forced to run during startup (e.g., onServerStart) that fails hard.
Quick hints:
- If it exits instantly: check EULA/password variables and container logs.
- If it runs but is “unhealthy”: check application logs and Health check endpoint.
- If it binds to port but not accessible: verify host port mapping and firewall.
Step-by-Step Troubleshooting Guide
Step 1: Confirm container state and basic logs
- Check the container’s current state:
docker ps -a
docker inspect -f ‘{{.State.Status}} {{.State.ExitCode}}’
docker logs –tail=200
Look for explicit errors: EULA, password complexity, OutOfMemoryError, BindException, or permission denied.
- If using Docker Compose:
Docker Compose ps
docker compose logs -f
Step 2: Extract ColdFusion/Tomcat logs inside the container
If the container is still running (even partially), exec into it:
docker exec -it
Look at:
- Tomcat logs: /opt/coldfusion/cfusion/logs/catalina.out or /opt/coldfusion/cfusion/logs/colfusion-error.log
- ColdFusion logs: /opt/coldfusion/cfusion/logs/coldfusion-out.log, application.log, exception.log
Common indicators:
- “Password does not meet complexity requirements”
- “EULA must be accepted”
- “java.lang.OutOfMemoryError”
- “Permission denied” on logs directory
- “BindException: Address already in use”
Step 3: Validate environment variables
Adobe ColdFusion images typically require:
- acceptEULA=YES
- An admin password variable (name varies by image and version; often “password”)
- Optional secure profile flags
Verify what your image expects in its documentation, then confirm:
docker inspect
Fix by recreating the container with correct variables:
docker run -d –name cf \
-p 8500:8500 \
-e acceptEULA=YES \
-e password=’Str0ng&P@ssw0rd!’ \
adobecoldfusion/coldfusion:2023.x
Notes:
- Use a strong password that satisfies secure profile rules (length and complexity).
- Avoid special characters that your shell may interpret; quote your password.
Step 4: Check volumes, file permissions, and SELinux
ColdFusion needs to write to log directories and read Configuration paths. If you mounted host volumes:
- Ensure the directory exists on the host.
- Set proper ownership to the user inside the container (varies by image; often non-root).
- For SELinux, add :z or :Z to volume mounts, or explicitly set context.
Example:
mkdir -p /data/cf/logs
chown -R 1000:1000 /data/cf/logs # Replace 1000 with the container’s CF user UID/GID
docker run -d \
-v /data/cf/logs:/opt/coldfusion/cfusion/logs:Z \
…
If you see:
java.io.FileNotFoundException: …/logs/… (Permission denied)
fix ownership and try again.
Step 5: Confirm port mappings and conflicts
If Tomcat tries to bind to 8500 but the host already uses that port:
- Change the host port or stop the conflicting service:
lsof -i :8500
or on Windows:
netstat -ano | findstr 8500
- Adjust mapping:
docker run -p 8501:8500 …
If the logs show “Address already in use: bind,” the port conflict is the cause.
Step 6: Verify JVM memory and startup options
Overly aggressive memory flags or invalid options can prevent startup:
- Check JAVA_ARGS or JVM config in /opt/coldfusion/cfusion/bin/jvm.config.
- Ensure heap fits in container memory (e.g., Xmx ≤ 75% of container memory).
- Example fix:
jvm.config snippet
-XX:+UseG1GC
-Xms512m
-Xmx2048m
-XX:MaxMetaspaceSize=512m
- If you’re using Docker memory limits:
docker run –memory=3g –memory-swap=3g …
Make sure -Xmx does not exceed the memory limit.
Step 7: Check ColdFusion Package Manager (cfpm) scripts and network
If you install packages during startup, failures can abort the boot:
- Look in logs for package install errors or repository timeouts.
- Test connectivity or configure proxy:
curl -I https://www.adobe.com/ # from inside container
export HTTPS_PROXY=http://proxy:8080
- Consider deferring package installation to the image build (Dockerfile RUN step) so startup is simpler and faster.
Step 8: Validate Tomcat/HTTP connector Configuration (server.xml)
Custom server.xml or context configs can break Tomcat:
- Check for duplicate connectors on the same port.
- Validate XML Syntax and attributes.
- Example working HTTP connector:
<Connector port=”8500″ protocol=”org.apache.coyote.http11.Http11NioProtocol”
address=”0.0.0.0″
connectionTimeout=”20000″
redirectPort=”8443″
maxThreads=”200″
URIEncoding=”UTF-8″ />
If you mounted a custom server.xml, temporarily revert to the default to confirm whether the file is the issue.
Step 9: Confirm image tag, Architecture, and platform
- Ensure you’re using a supported ColdFusion image tag that matches your expectations (e.g., 2023.x).
- On Apple Silicon (arm64), some images are amd64-only. Use the proper platform or a compatible tag:
docker run –platform=linux/amd64 …
Emulation can be slow and unstable; prefer a native arm64 image when available.
Step 10: Minimal reproduction and rebuild
Reduce complexity to isolate the issue:
- Start the container with no volumes, default server.xml, and only required env vars:
docker run -d –name cf-min \
-p 8500:8500 \
-e acceptEULA=YES \
-e password=’Str0ng&P@ssw0rd!’ \
adobecoldfusion/coldfusion:2023.x
- If this works, reintroduce volumes and customizations one at a time until the failure reappears.
- Fix the last change that reintroduced the problem.
Recovery steps worth knowing
- Reset the admin password by recreating the container with the correct env var, or clear persisted configuration if you’ve mounted it and it’s corrupted.
- If Application.cfc or onServerStart logic crashes on boot, temporarily deploy a blank app to confirm the platform starts, then fix the application code.
- Add extra logging (log4j settings, CF logging level) to expose startup sequence failures.
Quick reference: Cause / Solution
- Missing EULA acceptance — Set env var acceptEULA=YES; recreate container.
- Missing/weak admin password — Provide a strong password in the required env var; recreate container.
- Port conflict — Change host port or stop the conflicting service; verify with lsof/netstat.
- Permission denied on logs/config — Fix host directory ownership (chown) and SELinux context (:Z); ensure directories exist.
- OutOfMemoryError — Reduce Xmx or increase container memory; verify jvm.config.
- Invalid JVM flags — Remove unsupported flags; test minimal G1GC + Xmx/Xms.
- Package install failures (cfpm) — Add/properly configure proxy or preinstall in Dockerfile; verify network.
- Broken server.xml — Revert to default; verify ports and XML validity.
- Architecture mismatch — Choose correct platform (amd64 vs arm64) or proper image tag.
- App code crashes on startup — Temporarily disable or fix onServerStart/Application.cfc; watch application.log.
Configuration Examples
Minimal docker run
docker run -d –name cf \
-p 8500:8500 \
-e acceptEULA=YES \
-e password=’Str0ng&P@ssw0rd!’ \
adobecoldfusion/coldfusion:2023.x
Docker Compose example
services:
coldfusion:
image: adobecoldfusion/coldfusion:2023.x
container_name: cf
ports:
- “8500:8500”
environment: - acceptEULA=YES
- password=Str0ng&P@ssw0rd!
– https_proxy=http://proxy:8080
– http_proxy=http://proxy:8080
volumes:
- ./webroot:/app:Z
- ./logs:/opt/coldfusion/cfusion/logs:Z
restart: unless-stoppedplatform: linux/amd64 # if needed on Apple Silicon
JVM configuration (jvm.config snippet)
Example, adjust to your container memory
-XX:+UseG1GC
-Xms512m
-Xmx1536m
-XX:MaxMetaspaceSize=384m
-Djava.Security.egd=file:/dev/./urandom
Health check and logs
If the image provides a health check, watch status:
docker ps
docker inspect -f ‘{{json .State.Health}}’ cf | jq
If health is “unhealthy,” check logs:
docker logs cf
docker exec -it cf tail -n 200 /opt/coldfusion/cfusion/logs/coldfusion-out.log
Common mistakes and How to Avoid Them
- Forgetting to set acceptEULA=YES or setting a weak admin password. Avoid by always providing these in your Compose file or run script, and validate with docker inspect.
- Mounting a host directory over /opt/coldfusion/cfusion/logs without proper ownership and SELinux context. Avoid by chowning to the container user and using :Z on SELinux hosts.
- Assuming host free ports. Avoid by checking with lsof/netstat before binding standard ports like 8500/8080/8443.
- Setting Xmx larger than container memory. Avoid by sizing Xmx to about 50–75% of container memory and using docker run –memory limits.
- Editing server.xml without backups. Avoid by storing the default file, testing changes in a staging container, and validating XML Syntax.
- Running package installs at every boot. Avoid by baking dependencies into the image during build (Dockerfile) and keeping startup lean.
- Overlooking architecture differences (arm64 vs amd64). Avoid by using correct image tags and platforms.
Prevention Tips / Best practices
- Pin image versions. Use explicit tags (e.g., 2023.6.0) to prevent surprise updates.
- Bake config and modules into a custom image. Use a Dockerfile to preinstall packages (cfpm) and set JVM defaults.
- Store environment variables in Compose or secrets, not ad-hoc shell commands. Keep strong passwords in secrets.
- Implement readiness and liveness probes. If using orchestrators, configure health checks to restart unhealthy containers.
- Centralize and persist logs. Mount a logs volume with correct permissions and forward to a centralized log system if possible.
- Set resource limits. Define memory and CPU constraints and tune JVM accordingly.
- Keep server.xml minimal. Only change what you must and validate any TLS/connector changes.
- Test on the same architecture as production. Avoid last-minute platform surprises.
- Use minimal startup application code. Don’t run heavy initialization in onServerStart unless it’s resilient and well-logged.
- Document your runbook. Include commands for logs, exec, and common fixes so anyone on your team can respond quickly.
Key Takeaways or Summary Points
- Most ColdFusion-on-Docker startup failures are configuration or environment issues—start with container logs and ColdFusion/Tomcat logs.
- Ensure required env vars (EULA acceptance, strong admin password) and correct permissions on mounted volumes.
- Check ports, JVM memory, and server.xml before Debugging application code.
- Keep startup minimal: bake packages into the image, avoid heavy boot-time tasks, and pin image versions.
- Validate architecture compatibility and size resources to match JVM settings.
FAQ
How do I find the exact reason the ColdFusion container exited immediately?
- First run: docker logs
and check the last 200–500 lines. If empty, the process may have died very early—try docker events and inspect the container ExitCode. If the container is still up, exec into it and read /opt/coldfusion/cfusion/logs/coldfusion-out.log and catalina.out. Look for EULA/password errors, BindException, or OutOfMemoryError.
Can I run ColdFusion on Apple Silicon (M1/M2) hosts?
- Yes, but verify the image supports arm64. If not, run with –platform=linux/amd64. Be aware that emulation can be slower. For best stability and Performance, use an image with a native arm64 build or run on an amd64 host.
How can I enable remote Debugging to troubleshoot startup?
- Add the appropriate JDWP options in jvm.config, for example:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
Then publish the port: -p 5005:5005. Confirm the port is not blocked by firewalls. Restart the container and attach your debugger to host:5005.
My container is “unhealthy” but seems to be running. What should I check?
- Inspect the health check definition with docker inspect. Ensure the health endpoint aligns with your application (e.g., /healthcheck). Check application logs for exceptions during boot or cold starts. You may need to increase initialDelay or timeout values if the app is slow to warm up.
How do I persist the admin password and settings across restarts?
- Persist ColdFusion configuration (where supported) on a mounted volume or use a provisioning step at container start (e.g., cfsetup/CLI scripts) to apply settings idempotently. Avoid interactive setup by providing required env vars and using scripted configuration so the container remains immutable and reproducible.
