Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ require_once 'vendor/autoload.php';

use Utopia\Orchestration\Orchestration;
use Utopia\Orchestration\Adapter\DockerCLI;
use Utopia\Orchestration\Mount;

// Initialise Orchestration with Docker CLI adapter.
$orchestration = new Orchestration(new DockerCLI());
Expand Down Expand Up @@ -102,7 +103,11 @@ Once you have initialised your Orchestration object the following methods can be
['echo', 'hello world!'],
'entrypoint',
'workdir',
['tmp:/tmp:rw', 'cooldirectory:/home/folder:rw'],
[
'tmp:/tmp:rw',
Mount::bind('/host/cache', '/cache'),
Mount::volume('openruntimes-build-cache', '/cache', subpath: 'cache-key'),
],
['ENV_VAR' => 'value'],
'/tmp',
['label' => 'value'],
Expand Down Expand Up @@ -139,7 +144,7 @@ Once you have initialised your Orchestration object the following methods can be

- `volumes` [Array]

The volumes to attach to the container.
The volumes to attach to the container. String values are passed as legacy Docker volume binds. `Mount::bind(...)` and `Mount::volume(...)` values are rendered as Docker mounts. For bind mounts, `subpath` is appended to the host source path. Docker volume subpaths use Docker's native subpath support and must already exist; callers are responsible for preparing them before running the container.

- `env` [Array]

Expand Down
2 changes: 1 addition & 1 deletion src/Orchestration/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ abstract public function list(array $filters = []): array;
* On fail it will throw an exception.
*
* @param string[] $command
* @param string[] $volumes
* @param array<int, string|Mount> $volumes
* @param array<string, string> $vars
* @param array<string, string> $labels
*/
Expand Down
17 changes: 15 additions & 2 deletions src/Orchestration/Adapter/DockerAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Utopia\Orchestration\Container\Stats;
use Utopia\Orchestration\Exception\Orchestration;
use Utopia\Orchestration\Exception\Timeout;
use Utopia\Orchestration\Mount;
use Utopia\Orchestration\Network;

class DockerAPI extends Adapter
Expand Down Expand Up @@ -475,7 +476,7 @@ public function list(array $filters = []): array
* On fail it will throw an exception.
*
* @param string[] $command
* @param string[] $volumes
* @param array<int, string|Mount> $volumes
* @param array<string, string> $vars
* @param array<string, string> $labels
*/
Expand Down Expand Up @@ -511,6 +512,17 @@ public function run(
$labels[$this->namespace.'-type'] = 'runtime';
$labels[$this->namespace.'-created'] = (string) time();

$binds = [];
$mounts = [];

foreach ($volumes as $volume) {
if ($volume instanceof Mount) {
$mounts[] = $volume->toDockerAPI();
} else {
$binds[] = $volume;
}
}

$body = [
'Hostname' => $hostname,
'Entrypoint' => $entrypoint,
Expand All @@ -520,7 +532,8 @@ public function run(
'Labels' => (object) $labels,
'Env' => array_values($vars),
'HostConfig' => [
'Binds' => $volumes,
'Binds' => $binds,
'Mounts' => $mounts,
'CpuQuota' => floatval($this->cpus) * 100000,
'CpuPeriod' => 100000,
'Memory' => intval($this->memory) * 1e+6, // Convert into bytes
Expand Down
57 changes: 44 additions & 13 deletions src/Orchestration/Adapter/DockerCLI.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Utopia\Orchestration\Container\Stats;
use Utopia\Orchestration\Exception\Orchestration;
use Utopia\Orchestration\Exception\Timeout;
use Utopia\Orchestration\Mount;
use Utopia\Orchestration\Network;

class DockerCLI extends Adapter
Expand Down Expand Up @@ -387,7 +388,7 @@ public function list(array $filters = []): array
* On fail it will throw an exception.
*
* @param string[] $command
* @param string[] $volumes
* @param array<int, string|Mount> $volumes
* @param array<string, string> $vars
* @param array<string, string> $labels
*/
Expand All @@ -409,6 +410,42 @@ public function run(
$output = '';
$stderr = '';

$dockerCommand = $this->getRunCommand($image, $name, $command, $entrypoint, $workdir, $volumes, $vars, $mountFolder, $labels, $hostname, $remove, $network, $restart);

$result = Console::execute($dockerCommand, '', $output, $stderr, 30);

if ($result !== 0) {
$error = empty($stderr) ? $output : $stderr;
throw new Orchestration("Docker Error: {$error}");
}

// Use first line only, CLI can add warnings or other messages
$output = \explode("\n", $output)[0];

return rtrim($output);
}

/**
* @param string[] $command
* @param array<int, string|Mount> $volumes
* @param array<string, string> $vars
* @param array<string, string> $labels
*/
protected function getRunCommand(
string $image,
string $name,
array $command = [],
string $entrypoint = '',
string $workdir = '',
array $volumes = [],
array $vars = [],
string $mountFolder = '',
array $labels = [],
string $hostname = '',
bool $remove = false,
string $network = '',
string $restart = self::RESTART_NO
): Command {
$time = time();

$dockerCommand = new Command('docker');
Expand Down Expand Up @@ -451,7 +488,11 @@ public function run(
}

foreach ($volumes as $volume) {
$dockerCommand->option('--volume', $volume);
if ($volume instanceof Mount) {
$dockerCommand->option('--mount', $volume->toDockerCLI());
} else {
$dockerCommand->option('--volume', $volume);
}
}

foreach ($labels as $labelKey => $label) {
Expand All @@ -477,17 +518,7 @@ public function run(
$dockerCommand->argument($value);
}

$result = Console::execute($dockerCommand, '', $output, $stderr, 30);

if ($result !== 0) {
$error = empty($stderr) ? $output : $stderr;
throw new Orchestration("Docker Error: {$error}");
}

// Use first line only, CLI can add warnings or other messages
$output = \explode("\n", $output)[0];

return rtrim($output);
return $dockerCommand;
}

/**
Expand Down
82 changes: 82 additions & 0 deletions src/Orchestration/Mount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Utopia\Orchestration;

class Mount
{
public const TYPE_BIND = 'bind';

public const TYPE_VOLUME = 'volume';

private function __construct(
private string $type,
private string $source,
private string $target,
private bool $readOnly = false,
private string $subpath = ''
) {
}

public static function bind(string $source, string $target, bool $readOnly = false, string $subpath = ''): self
{
return new self(self::TYPE_BIND, $source, $target, $readOnly, $subpath);
}

/**
* Docker volume subpaths use native volume subpath support. Docker requires the subpath to already exist.
*/
public static function volume(string $source, string $target, bool $readOnly = false, string $subpath = ''): self
{
return new self(self::TYPE_VOLUME, $source, $target, $readOnly, $subpath);
}

/**
* @return array<string, array<string, string>|bool|string>
*/
public function toDockerAPI(): array
{
$mount = [
'Type' => $this->type,
'Source' => $this->getSource(),
'Target' => $this->target,
'ReadOnly' => $this->readOnly,
];

if ($this->type === self::TYPE_VOLUME && $this->subpath !== '') {
$mount['VolumeOptions'] = [
'Subpath' => $this->subpath,
];
}

return $mount;
}

public function toDockerCLI(): string
{
$mount = [
'type='.$this->type,
'source='.$this->getSource(),
'target='.$this->target,
];

if ($this->readOnly) {
$mount[] = 'readonly';
}

if ($this->type === self::TYPE_VOLUME && $this->subpath !== '') {
$mount[] = 'volume-subpath='.$this->subpath;
}

return \implode(',', $mount);
}

private function getSource(): string
{
if ($this->type !== self::TYPE_BIND || $this->subpath === '') {
return $this->source;
}

// Bind subpaths are regular host path suffixes, not Docker native subpaths.
return \rtrim($this->source, '/').'/'.\ltrim($this->subpath, '/');
}
Comment thread
greptile-apps[bot] marked this conversation as resolved.
}
2 changes: 1 addition & 1 deletion src/Orchestration/Orchestration.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public function list(array $filters = []): array
* On fail it will throw an exception.
*
* @param string[] $command
* @param string[] $volumes
* @param array<int, string|Mount> $volumes
* @param array<string, string> $labels
* @param array<string, string> $vars
*/
Expand Down
Loading
Loading