mirror of
https://github.com/coollabsio/coolify.git
synced 2026-08-28 18:14:35 -05:00
Add comprehensive Docker registry management system that allows users to configure, manage, and sync Docker registry authentication through the Coolify UI instead of manual SSH configuration. Key features: - Database-backed registry storage with encrypted credentials - Full CRUD operations via Livewire component - Auto-sync to server's ~/.docker/config.json before deployments - Credential validation with test connection functionality - Import existing registries from server config - Quick-add presets for common registries (Docker Hub, GHCR, GitLab, AWS ECR, etc.) - Enable/disable registries without deletion - Dark mode support Technical changes: - New DockerRegistry model with encrypted password field - Migration for docker_registries table with unique constraint - Server relationship and active scope - Helper functions for config.json generation, sync, import, and validation - Integration with ApplicationDeploymentJob for automatic sync - Comprehensive unit and feature tests - Server sidebar menu item and routing This replaces the manual docker login requirement on servers and provides a centralized way to manage private registry access across deployments. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
106 lines
3.0 KiB
PHP
106 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class DockerRegistry extends BaseModel
|
|
{
|
|
protected $fillable = [
|
|
'server_id',
|
|
'name',
|
|
'registry_url',
|
|
'username',
|
|
'password',
|
|
'is_active',
|
|
'last_validated_at',
|
|
];
|
|
|
|
protected $casts = [
|
|
'password' => 'encrypted',
|
|
'is_active' => 'boolean',
|
|
'last_validated_at' => 'datetime',
|
|
];
|
|
|
|
protected static function booted(): void
|
|
{
|
|
static::saving(function ($registry) {
|
|
$registry->registry_url = rtrim($registry->registry_url, '/');
|
|
|
|
if (empty($registry->name)) {
|
|
$registry->name = $registry->registry_url;
|
|
}
|
|
|
|
if (self::registryExists($registry->server_id, $registry->registry_url, $registry->id)) {
|
|
throw ValidationException::withMessages([
|
|
'registry_url' => ['This registry already exists for this server.'],
|
|
]);
|
|
}
|
|
});
|
|
}
|
|
|
|
public function server(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Server::class);
|
|
}
|
|
|
|
public static function registryExists(int $serverId, string $registryUrl, ?int $excludeId = null): bool
|
|
{
|
|
$query = self::where('server_id', $serverId)
|
|
->where('registry_url', $registryUrl);
|
|
|
|
if ($excludeId) {
|
|
$query->where('id', '!=', $excludeId);
|
|
}
|
|
|
|
return $query->exists();
|
|
}
|
|
|
|
public function scopeActive($query)
|
|
{
|
|
return $query->where('is_active', true);
|
|
}
|
|
|
|
public static function getCommonRegistries(): array
|
|
{
|
|
return [
|
|
[
|
|
'name' => 'Docker Hub',
|
|
'registry_url' => 'https://index.docker.io/v1/',
|
|
'placeholder_username' => 'your-dockerhub-username',
|
|
],
|
|
[
|
|
'name' => 'GitHub Container Registry',
|
|
'registry_url' => 'ghcr.io',
|
|
'placeholder_username' => 'your-github-username',
|
|
],
|
|
[
|
|
'name' => 'GitLab Container Registry',
|
|
'registry_url' => 'registry.gitlab.com',
|
|
'placeholder_username' => 'your-gitlab-username',
|
|
],
|
|
[
|
|
'name' => 'Amazon ECR',
|
|
'registry_url' => 'AWS_ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com',
|
|
'placeholder_username' => 'AWS',
|
|
],
|
|
[
|
|
'name' => 'Google Container Registry',
|
|
'registry_url' => 'gcr.io',
|
|
'placeholder_username' => '_json_key',
|
|
],
|
|
[
|
|
'name' => 'Azure Container Registry',
|
|
'registry_url' => 'YOUR_REGISTRY.azurecr.io',
|
|
'placeholder_username' => 'your-registry-name',
|
|
],
|
|
[
|
|
'name' => 'Quay.io',
|
|
'registry_url' => 'quay.io',
|
|
'placeholder_username' => 'your-quay-username',
|
|
],
|
|
];
|
|
}
|
|
}
|