Skip to content

Conversation

@adiologydev
Copy link
Contributor

@adiologydev adiologydev commented Nov 3, 2025

Changes

  • Extended convertDockerRunToCompose() to parse and convert --entrypoint options

Notes

  • Supports simple entrypoints: --entrypoint /bin/sh
  • Supports quoted commands: --entrypoint "sh -c 'npm start'"
  • Supports both --entrypoint=value and --entrypoint value syntax

Why?

Many images, such as ServerSideUp PHP offers multiple docker entrypoints for inertia, horizon, worker, scheduler, etc. Without a custom entrypoint option, we'd have to manually build the image with each entrypoint already specified.

Here's it working properly without custom image:
image

Issues

Summary by CodeRabbit

  • New Features
    • Docker entrypoint options are now properly supported when converting Docker run commands to Docker Compose format, handling various quoting styles and option formats while maintaining compatibility with other Docker options.

@Cinzya Cinzya added the 🛠️ Feature Issues requesting a new feature. label Nov 3, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Nov 3, 2025

Hi @adiologydev! 👋

It appears to us that you are adding a new feature to Coolify.
We kindly ask you to also update the Coolify Documentation to include information about this new feature.
This will help ensure that our documentation remains accurate and up-to-date for all users.

Coolify Docs Repository: https://github.com/coollabsio/coolify-docs
How to Contribute to the Docs: https://coolify.io/docs/get-started/contribute/documentation

@adiologydev
Copy link
Contributor Author

@coderabbitai review this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

@adiologydev, I'll review the changes in this PR that adds custom docker entrypoint support to the convertDockerRunToCompose() function.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

Walkthrough

The changes add Docker entrypoint option support to the Docker run to Compose conversion system. The implementation includes parsing --entrypoint flags from custom_docker_run_options with support for various quoting styles and integrating the parsed values into the composition phase. Comprehensive test coverage validates the conversion across multiple entrypoint formats and interactions with other Docker options.

Changes

Cohort / File(s) Summary
Docker Entrypoint Support
bootstrap/helpers/docker.php
Introduces --entrypoint mapping and parsing logic. Extracts entrypoint values from custom_docker_run_options supporting quoted (single/double) and unquoted forms, selecting the first non-empty value. Persists entrypoint into options structure and integrates handling into composition phase. Maintains compatibility with existing options.
Entrypoint Conversion Tests
tests/Feature/DockerCustomCommandsTest.php
Adds test cases verifying Docker entrypoint conversion to Compose format. Covers plain, equals-sign, quoted, single-quoted, and combined option formats. Tests interactions with other flags (cap_add, privileged) and complex nested quoting scenarios.

Sequence Diagram

sequenceDiagram
    actor User
    participant Parser as Option Parser
    participant Handler as Entrypoint Handler
    participant Composer as Compose Builder

    User->>Parser: custom_docker_run_options<br/>(--entrypoint "cmd")
    Parser->>Parser: Detect --entrypoint flag
    Parser->>Parser: Extract value<br/>(handle quotes)
    Parser->>Handler: Return parsed values
    Handler->>Handler: Select first non-empty
    Handler->>Composer: Store in options
    Composer->>Composer: Assign to compose field
    Composer-->>User: Docker Compose config
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

  • Focus on parsing logic in docker.php for correct quote handling across all formats (single, double, unquoted)
  • Verify uniqueness enforcement and first-value selection logic
  • Cross-reference test cases with implementation to ensure all quoting scenarios are properly handled
  • Confirm compatibility with existing option handling patterns and other Docker flags

Poem

🐰 A little rabbit hops with glee,
For entrypoints now run wild and free,
With quotes both single, double, plain,
Docker commands dance in the code's domain,
Conversion flows like morning dew,
From run to Compose, tried and true!

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: custom docker entrypoint' accurately describes the main feature addition to support custom Docker entrypoint options in the run-to-Compose conversion.
Description check ✅ Passed The description includes the required Changes section and Issues section with a link, providing sufficient context about the feature and motivation.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
bootstrap/helpers/docker.php (1)

946-983: Handle escaped quotes in --entrypoint parsing

When the entrypoint is double-quoted and contains escaped quotes (e.g. --entrypoint "python -c \"print('hi')\""), the current regex stops at the first escaped " and stores only python -c \. Docker Compose then receives a truncated entrypoint and the container fails to start. Please parse the argument with escape awareness and skip the fallback branch so we don’t add the broken token back in.

         '--hostname' => 'hostname',
         '--entrypoint' => 'entrypoint',
     ]);
     foreach ($matches as $match) {
         $option = $match[1];
@@
-        if ($option === '--entrypoint') {
-            // Match --entrypoint=value or --entrypoint value
-            // Handle quoted strings: --entrypoint "sh -c 'command'" or --entrypoint='command'
-            // Try double quotes first, then single quotes, then unquoted
-            if (preg_match('/--entrypoint(?:=|\s+)"([^"]+)"/', $custom_docker_run_options, $entrypoint_matches)) {
-                $value = $entrypoint_matches[1];
-            } elseif (preg_match("/--entrypoint(?:=|\s+)'([^']+)'/", $custom_docker_run_options, $entrypoint_matches)) {
-                $value = $entrypoint_matches[1];
-            } elseif (preg_match('/--entrypoint(?:=|\s+)([^\s]+)/', $custom_docker_run_options, $entrypoint_matches)) {
-                $value = $entrypoint_matches[1];
-            } else {
-                $value = null;
-            }
-            if ($value && ! empty(trim($value))) {
-                $options[$option][] = $value;
-                $options[$option] = array_unique($options[$option]);
-            }
-        }
+        if ($option === '--entrypoint') {
+            if (preg_match(
+                '/--entrypoint(?:=|\s+)(?<raw>"(?:\\\\.|[^"])*"|\'(?:\\\\.|[^\'])*\'|[^\s]+)/',
+                $custom_docker_run_options,
+                $entrypoint_matches
+            )) {
+                $rawValue = $entrypoint_matches['raw'];
+                if (str_starts_with($rawValue, '"') && str_ends_with($rawValue, '"')) {
+                    $inner = substr($rawValue, 1, -1);
+                    $value = preg_replace('/\\\\(["$`\\\\])/', '$1', $inner);
+                } elseif (str_starts_with($rawValue, "'") && str_ends_with($rawValue, "'")) {
+                    $value = substr($rawValue, 1, -1);
+                } else {
+                    $value = $rawValue;
+                }
+            }
+
+            if (isset($value) && trim($value) !== '') {
+                $options[$option][] = $value;
+                $options[$option] = array_values(array_unique($options[$option]));
+            }
+
+            continue;
+        }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d291d85 and f89b864.

📒 Files selected for processing (2)
  • bootstrap/helpers/docker.php (3 hunks)
  • tests/Feature/DockerCustomCommandsTest.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
tests/Feature/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Place integration/request lifecycle tests under tests/Feature

tests/Feature/**/*.php: Feature tests (tests/Feature) may use database connections (migrations, models, factories)
Feature tests that touch the database must use the RefreshDatabase trait

Files:

  • tests/Feature/DockerCustomCommandsTest.php
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

**/*.php: Follow PSR-12 coding standards for all PHP code
Format PHP code with Laravel Pint configuration
Run static analysis with PHPStan to ensure type safety in PHP code
Document complex methods with PHPDoc blocks including parameters, return types, and thrown exceptions

**/*.php: Follow PSR-12 PHP coding standards across the codebase
Prefer eager loading and query optimization to prevent N+1 issues in database interactions
Use Laravel best practices for structure, services, and policies

**/*.php: Always use curly braces for control structures in PHP, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and avoid empty constructors
Always declare explicit return types for functions and methods; add appropriate parameter type hints
Prefer PHPDoc blocks over inline comments; only add inline code comments for very complex logic
When documenting arrays, add useful array shape types in PHPDoc where appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)

Files:

  • tests/Feature/DockerCustomCommandsTest.php
  • bootstrap/helpers/docker.php
tests/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

Write feature tests for API endpoints using Pest; mock external services and assert JSON responses and side effects

Add tests validating that components respect authorization (e.g., unauthorized users see disabled inputs; checkbox instantSave becomes false)

Include security tests covering SQL injection resistance, XSS validation, and enforcement of team isolation (403 on cross-team access).

Write tests using Pest (feature/unit) and include Laravel Dusk for browser scenarios as needed

Prefer Pest PHP as the primary testing framework for writing tests

Files:

  • tests/Feature/DockerCustomCommandsTest.php
tests/**

📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)

Keep automated tests (Pest/Dusk) under tests

Files:

  • tests/Feature/DockerCustomCommandsTest.php
tests/{Feature,Unit}/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)

tests/{Feature,Unit}/**/*.php: All tests must be written using Pest and live under tests/Feature or tests/Unit
Use specific response assertion helpers (e.g., assertForbidden, assertNotFound) instead of generic assertStatus
Use datasets in Pest to reduce duplication where suitable (e.g., validation tests)
Write or update unit/feature tests for every change and run the affected tests

Files:

  • tests/Feature/DockerCustomCommandsTest.php
bootstrap/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Initialization/bootstrap code should reside under bootstrap/ (e.g., app bootstrapping)

Files:

  • bootstrap/helpers/docker.php

Comment on lines +145 to +175
test('ConvertEntrypointWithArguments', function () {
$input = '--entrypoint "sh -c npm install"';
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => 'sh -c npm install',
]);
});

test('ConvertEntrypointWithSingleQuotes', function () {
$input = "--entrypoint 'memcached -m 256'";
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => 'memcached -m 256',
]);
});

test('ConvertEntrypointWithOtherOptions', function () {
$input = '--entrypoint /bin/bash --cap-add SYS_ADMIN --privileged';
$output = convertDockerRunToCompose($input);
expect($output)->toHaveKeys(['entrypoint', 'cap_add', 'privileged'])
->and($output['entrypoint'])->toBe('/bin/bash')
->and($output['cap_add'])->toBe(['SYS_ADMIN'])
->and($output['privileged'])->toBe(true);
});

test('ConvertEntrypointComplex', function () {
$input = '--entrypoint "sh -c \'npm install && npm start\'"';
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => "sh -c 'npm install && npm start'",
]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add coverage for escaped double quotes

Please add a case where the entrypoint contains escaped quotes (e.g. --entrypoint "python -c \"print('hi')\"") so the parser can’t regress on real-world commands that embed quoted scripts.

 test('ConvertEntrypointComplex', function () {
     $input = '--entrypoint "sh -c \'npm install && npm start\'"';
     $output = convertDockerRunToCompose($input);
     expect($output)->toBe([
         'entrypoint' => "sh -c 'npm install && npm start'",
     ]);
 });
+
+test('ConvertEntrypointWithEscapedQuotes', function () {
+    $input = "--entrypoint \"python -c \\\"print('hello')\\\"\"";
+    $output = convertDockerRunToCompose($input);
+    expect($output)->toBe([
+        'entrypoint' => "python -c \"print('hello')\"",
+    ]);
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test('ConvertEntrypointWithArguments', function () {
$input = '--entrypoint "sh -c npm install"';
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => 'sh -c npm install',
]);
});
test('ConvertEntrypointWithSingleQuotes', function () {
$input = "--entrypoint 'memcached -m 256'";
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => 'memcached -m 256',
]);
});
test('ConvertEntrypointWithOtherOptions', function () {
$input = '--entrypoint /bin/bash --cap-add SYS_ADMIN --privileged';
$output = convertDockerRunToCompose($input);
expect($output)->toHaveKeys(['entrypoint', 'cap_add', 'privileged'])
->and($output['entrypoint'])->toBe('/bin/bash')
->and($output['cap_add'])->toBe(['SYS_ADMIN'])
->and($output['privileged'])->toBe(true);
});
test('ConvertEntrypointComplex', function () {
$input = '--entrypoint "sh -c \'npm install && npm start\'"';
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => "sh -c 'npm install && npm start'",
]);
test('ConvertEntrypointWithArguments', function () {
$input = '--entrypoint "sh -c npm install"';
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => 'sh -c npm install',
]);
});
test('ConvertEntrypointWithSingleQuotes', function () {
$input = "--entrypoint 'memcached -m 256'";
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => 'memcached -m 256',
]);
});
test('ConvertEntrypointWithOtherOptions', function () {
$input = '--entrypoint /bin/bash --cap-add SYS_ADMIN --privileged';
$output = convertDockerRunToCompose($input);
expect($output)->toHaveKeys(['entrypoint', 'cap_add', 'privileged'])
->and($output['entrypoint'])->toBe('/bin/bash')
->and($output['cap_add'])->toBe(['SYS_ADMIN'])
->and($output['privileged'])->toBe(true);
});
test('ConvertEntrypointComplex', function () {
$input = '--entrypoint "sh -c \'npm install && npm start\'"';
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => "sh -c 'npm install && npm start'",
]);
});
test('ConvertEntrypointWithEscapedQuotes', function () {
$input = "--entrypoint \"python -c \\\"print('hello')\\\"\"";
$output = convertDockerRunToCompose($input);
expect($output)->toBe([
'entrypoint' => "python -c \"print('hello')\"",
]);
});
🤖 Prompt for AI Agents
In tests/Feature/DockerCustomCommandsTest.php around lines 145 to 175, add a new
test that covers entrypoints containing escaped double quotes so the parser
handles embedded quoted scripts; add a test input like --entrypoint "python -c
\"print('hi')\"" (and similar with single-quote wrapping), call
convertDockerRunToCompose($input) and assert the returned array contains
'entrypoint' => 'python -c "print(\'hi\')"' (i.e. the inner quotes preserved and
properly unescaped), ensuring the parser returns the correct single string
rather than truncated or mis-parsed tokens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🛠️ Feature Issues requesting a new feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants