-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
feat: custom docker entrypoint #7097
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Conversation
|
Hi @adiologydev! 👋 It appears to us that you are adding a new feature to Coolify. Coolify Docs Repository: https://github.com/coollabsio/coolify-docs |
|
@coderabbitai review this PR |
|
@adiologydev, I'll review the changes in this PR that adds custom docker entrypoint support to the ✅ Actions performedReview triggered.
|
WalkthroughThe 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
Sequence DiagramsequenceDiagram
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
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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--entrypointparsingWhen 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 onlypython -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
📒 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.phpbootstrap/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
| 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'", | ||
| ]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
Changes
convertDockerRunToCompose()to parse and convert--entrypointoptionsNotes
--entrypoint /bin/sh--entrypoint "sh -c 'npm start'"--entrypoint=valueand--entrypoint valuesyntaxWhy?
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:

Issues
Summary by CodeRabbit