view release on metacpan or search on metacpan
API-Docker-*
.build
# Claude Code â commit: skills/, agents/, hooks/, settings.json
# Ignore: local overrides, credentials, session data
.claude/*.local.*
.claude/local/
.claude/.credentials.json
.claude/statsig/
.claude/todos/
.claude/projects/
lib/API/Docker/API/Containers.pm view on Meta::CPAN
has client => (
is => 'ro',
required => 1,
weak_ref => 1,
);
sub _wrap {
my ($self, $data) = @_;
return API::Docker::Container->new(
client => $self->client,
%$data,
);
}
sub _wrap_list {
my ($self, $list) = @_;
return [ map { $self->_wrap($_) } @$list ];
}
sub list {
my ($self, %opts) = @_;
lib/API/Docker/API/Images.pm view on Meta::CPAN
has client => (
is => 'ro',
required => 1,
weak_ref => 1,
);
sub _wrap {
my ($self, $data) = @_;
return API::Docker::Image->new(
client => $self->client,
%$data,
);
}
sub _wrap_list {
my ($self, $list) = @_;
return [ map { $self->_wrap($_) } @$list ];
}
sub list {
my ($self, %opts) = @_;
lib/API/Docker/API/Images.pm view on Meta::CPAN
=item * C<digests> - Include digest information
=item * C<filters> - Hashref of filters
=back
=head2 build
# Build from a tar archive
my $tar_data = path('context.tar')->slurp_raw;
my $result = $docker->images->build(
context => $tar_data,
t => 'myimage:latest',
dockerfile => 'Dockerfile',
);
# Build with build args
my $result = $docker->images->build(
context => $tar_data,
t => 'myapp:v1',
buildargs => { APP_VERSION => '1.0' },
nocache => 1,
);
Build an image from a tar archive containing a Dockerfile and build context.
The C<context> parameter is required and must contain the raw bytes of a tar
archive (or a scalar reference to one).
lib/API/Docker/API/Networks.pm view on Meta::CPAN
has client => (
is => 'ro',
required => 1,
weak_ref => 1,
);
sub _wrap {
my ($self, $data) = @_;
return API::Docker::Network->new(
client => $self->client,
%$data,
);
}
sub _wrap_list {
my ($self, $list) = @_;
return [ map { $self->_wrap($_) } @$list ];
}
sub list {
my ($self, %opts) = @_;
lib/API/Docker/API/System.pm view on Meta::CPAN
=item * C<until> - Show events created before this timestamp
=item * C<filters> - Hashref of filters (e.g., C<< { type => ['container', 'image'] } >>)
=back
=head2 df
my $usage = $system->df;
Get data usage information (disk usage by images, containers, and volumes).
Returns hashref with C<LayersSize>, C<Images>, C<Containers>, and C<Volumes> arrays.
=head1 SEE ALSO
=over
=item * L<API::Docker> - Main Docker client
=back
lib/API/Docker/API/Volumes.pm view on Meta::CPAN
has client => (
is => 'ro',
required => 1,
weak_ref => 1,
);
sub _wrap {
my ($self, $data) = @_;
return API::Docker::Volume->new(
client => $self->client,
%$data,
);
}
sub _wrap_list {
my ($self, $list) = @_;
return [ map { $self->_wrap($_) } @$list ];
}
sub list {
my ($self, %opts) = @_;
lib/API/Docker/Image.pm view on Meta::CPAN
has SharedSize => (is => 'ro');
has VirtualSize => (is => 'ro');
has Labels => (is => 'ro');
has Containers => (is => 'ro');
has Architecture => (is => 'ro');
has Os => (is => 'ro');
has Config => (is => 'ro');
has RootFS => (is => 'ro');
has Metadata => (is => 'ro');
sub inspect {
my ($self) = @_;
return $self->client->images->inspect($self->Id);
}
sub history {
my ($self) = @_;
return $self->client->images->history($self->Id);
lib/API/Docker/Role/HTTP.pm view on Meta::CPAN
$self->_clear_socket;
my ($status_code, $status_text, $headers, $body) = @$response;
$log->debugf("Response: %s %s", $status_code, $status_text);
if ($status_code >= 400) {
my $error_msg = $body;
if ($body && $body =~ /^\s*[\{\[]/) {
eval {
my $data = decode_json($body);
$error_msg = $data->{message} // $body;
};
}
croak "Docker API error ($status_code): $error_msg";
}
if ($status_code == 204 || !defined($body) || $body eq '') {
return undef;
}
if ($body =~ /^\s*[\{\[]/) {
lib/API/Docker/Role/HTTP.pm view on Meta::CPAN
my $read = 0;
while ($read < $chunk_size) {
my $buf;
my $n = read($sock, $buf, $chunk_size - $read);
last unless $n;
$chunk .= $buf;
$read += $n;
}
$body .= $chunk;
# Read trailing \r\n after chunk data
<$sock>;
}
return $body;
}
sub _uri_encode {
my ($str) = @_;
$str =~ s/([^A-Za-z0-9\-_.~:\/])/sprintf("%%%02X", ord($1))/ge;
return $str;
lib/API/Docker/Role/HTTP.pm view on Meta::CPAN
package MyDockerClient;
use Moo;
has host => (is => 'ro', required => 1);
has api_version => (is => 'ro');
with 'API::Docker::Role::HTTP';
# Now use get, post, put, delete_request methods
my $data = $self->get('/containers/json');
=head1 DESCRIPTION
This role provides HTTP transport for the Docker Engine API. It implements
HTTP/1.1 communication over Unix sockets and TCP sockets without depending on
heavy HTTP client libraries like LWP.
Features:
=over
lib/API/Docker/Role/HTTP.pm view on Meta::CPAN
=item * Request/response logging via L<Log::Any>
=item * Automatic connection management
=back
Consuming classes must provide C<host> and C<api_version> attributes.
=head2 get
my $data = $client->get($path, %opts);
Perform HTTP GET request. Returns decoded JSON or raw response body.
Options: C<params> (hashref of query parameters),
C<headers> (hashref of extra HTTP headers, e.g. C<< { 'X-Registry-Auth' => $b64 } >>).
=head2 post
my $data = $client->post($path, $body, %opts);
Perform HTTP POST request. C<$body> is automatically JSON-encoded if provided.
Options: C<params> (hashref of query parameters),
C<headers> (hashref of extra HTTP headers).
=head2 put
my $data = $client->put($path, $body, %opts);
Perform HTTP PUT request. C<$body> is automatically JSON-encoded if provided.
Options: C<params> (hashref of query parameters).
=head2 delete_request
my $data = $client->delete_request($path, %opts);
Perform HTTP DELETE request.
Options: C<params> (hashref of query parameters).
=head1 SEE ALSO
=over
=item * L<API::Docker> - Main client using this role
t/fixtures/volumes_list.json view on Meta::CPAN
{
"Volumes": [
{
"Name": "my-data",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/my-data/_data",
"CreatedAt": "2025-01-10T08:00:00Z",
"Status": {},
"Labels": {
"project": "test"
},
"Scope": "local",
"Options": {}
},
{
"Name": "postgres-data",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/postgres-data/_data",
"CreatedAt": "2025-01-11T09:00:00Z",
"Status": {},
"Labels": {},
"Scope": "local",
"Options": {}
}
],
"Warnings": []
}
$tar .= $dockerfile;
$tar .= "\0" x (512 - ($size % 512)) if $size % 512;
$tar .= "\0" x 1024;
my $tag = 'api-docker-test-build:latest';
my $result = $docker->images->build(context => $tar, t => $tag, q => 1);
ok($result, 'build returned result');
register_cleanup(sub { eval { $docker->images->remove($tag, force => 1) } });
} else {
my $result = $docker->images->build(
context => 'fake-tar-data',
t => 'myapp:latest',
dockerfile => 'Dockerfile',
);
ok($result, 'build returned a result');
like($result->{stream}, qr/Successfully built/, 'build output contains success');
$docker->images->pull(fromImage => 'nginx', tag => 'latest');
pass('pull completed');
$docker->images->tag('nginx:latest', repo => 'myrepo/nginx', tag => 'v1');
my $docker = test_docker(
'GET /system/df' => {
LayersSize => 1000000000,
Images => [
{ Id => 'sha256:abc', Size => 500000000, SharedSize => 200000000 },
],
Containers => [
{ Id => 'abc123', SizeRw => 10000, SizeRootFs => 500000000 },
],
Volumes => [
{ Name => 'my-data', UsageData => { Size => 100000000 } },
],
},
);
my $df = $docker->system->df;
ok(defined $df->{LayersSize}, 'has LayersSize');
is(ref $df->{Images}, 'ARRAY', 'has Images array');
is(ref $df->{Containers}, 'ARRAY', 'has Containers array');
is(ref $df->{Volumes}, 'ARRAY', 'has Volumes array');
t/volumes.t view on Meta::CPAN
is(ref $volumes, 'ARRAY', 'returns array');
if (@$volumes) {
isa_ok($volumes->[0], 'API::Docker::Volume');
ok($volumes->[0]->Name, 'has Name');
}
unless (is_live()) {
is(scalar @$volumes, 2, 'two volumes');
my $first = $volumes->[0];
is($first->Name, 'my-data', 'volume name');
is($first->Driver, 'local', 'volume driver');
is($first->Scope, 'local', 'volume scope');
is_deeply($first->Labels, { project => 'test' }, 'volume labels');
like($first->Mountpoint, qr{/var/lib/docker/volumes/my-data}, 'mountpoint');
}
};
# --- Write Tests (mock always, live only with WRITE) ---
subtest 'volume lifecycle' => sub {
skip_unless_write();
my $docker = test_docker(
'POST /volumes/create' => sub {
my ($method, $path, %opts) = @_;
is($opts{body}{Name}, 'test-vol', 'volume name in body') unless is_live();
return {
Name => 'test-vol',
Driver => 'local',
Mountpoint => '/var/lib/docker/volumes/test-vol/_data',
CreatedAt => '2025-01-15T12:00:00Z',
Labels => {},
Scope => 'local',
Options => {},
};
},
'GET /volumes/test-vol' => {
Name => 'test-vol',
Driver => 'local',
Mountpoint => '/var/lib/docker/volumes/test-vol/_data',
CreatedAt => '2025-01-10T08:00:00Z',
Labels => {},
Scope => 'local',
Options => {},
},
'DELETE /volumes/test-vol' => undef,
);
my $name = is_live() ? 'api-docker-test-vol-' . $$ : 'test-vol';
my $volume = $docker->volumes->create(Name => $name);