File Coverage

blib/lib/WWW/Docker/API/Containers.pm
Criterion Covered Total %
statement 67 103 65.0
branch 23 88 26.1
condition 1 2 50.0
subroutine 16 23 69.5
pod 2 17 11.7
total 109 233 46.7


line stmt bran cond sub pod time code
1             package WWW::Docker::API::Containers;
2             # ABSTRACT: Docker Engine Containers API
3              
4 10     10   64 use Moo;
  10         18  
  10         66  
5 10     10   8606 use WWW::Docker::Container;
  10         40  
  10         454  
6 10     10   155 use Carp qw( croak );
  10         18  
  10         850  
7 10     10   56 use namespace::clean;
  10         15  
  10         52  
8              
9             our $VERSION = '0.101';
10              
11             =head1 SYNOPSIS
12              
13             my $docker = WWW::Docker->new;
14              
15             # List containers
16             my $containers = $docker->containers->list(all => 1);
17             for my $container (@$containers) {
18             say $container->Id;
19             say $container->Status;
20             }
21              
22             # Create and start a container
23             my $result = $docker->containers->create(
24             Image => 'nginx:latest',
25             name => 'my-nginx',
26             ExposedPorts => { '80/tcp' => {} },
27             );
28             $docker->containers->start($result->{Id});
29              
30             # Inspect container details
31             my $container = $docker->containers->inspect($result->{Id});
32             say $container->Name;
33              
34             # Stop and remove
35             $docker->containers->stop($result->{Id}, timeout => 10);
36             $docker->containers->remove($result->{Id});
37              
38             # View logs
39             my $logs = $docker->containers->logs($result->{Id}, tail => 100);
40              
41             =head1 DESCRIPTION
42              
43             This module provides methods for managing Docker containers including creation,
44             lifecycle operations (start, stop, restart), inspection, logs, and more.
45              
46             All C and C methods return L objects
47             for convenient access to container properties and operations.
48              
49             Accessed via C<< $docker->containers >>.
50              
51             =cut
52              
53             has client => (
54             is => 'ro',
55             required => 1,
56             weak_ref => 1,
57             );
58              
59             =attr client
60              
61             Reference to L client. Weak reference to avoid circular dependencies.
62              
63             =cut
64              
65             sub _wrap {
66 3     3   8 my ($self, $data) = @_;
67 3         99 return WWW::Docker::Container->new(
68             client => $self->client,
69             %$data,
70             );
71             }
72              
73             sub _wrap_list {
74 1     1   3 my ($self, $list) = @_;
75 1         4 return [ map { $self->_wrap($_) } @$list ];
  2         5060  
76             }
77              
78             sub list {
79 1     1 0 1448 my ($self, %opts) = @_;
80 1         3 my %params;
81 1 50       9 $params{all} = $opts{all} ? 1 : 0 if defined $opts{all};
    50          
82 1 50       5 $params{limit} = $opts{limit} if defined $opts{limit};
83 1 0       4 $params{size} = $opts{size} ? 1 : 0 if defined $opts{size};
    50          
84 1 50       4 $params{filters} = $opts{filters} if defined $opts{filters};
85 1         14 my $result = $self->client->get('/containers/json', params => \%params);
86 1   50     26 return $self->_wrap_list($result // []);
87             }
88              
89             =method list
90              
91             my $containers = $containers->list(%opts);
92              
93             List containers. Returns ArrayRef of L objects.
94              
95             Options:
96              
97             =over
98              
99             =item * C - Show all containers (default shows just running)
100              
101             =item * C - Limit results to N most recently created containers
102              
103             =item * C - Include size information
104              
105             =item * C - Hashref of filters
106              
107             =back
108              
109             =cut
110              
111             sub create {
112 1     1 0 30 my ($self, %config) = @_;
113 1         2 my %params;
114 1 50       5 $params{name} = delete $config{name} if defined $config{name};
115 1         11 my $result = $self->client->post('/containers/create', \%config, params => \%params);
116 1         15 return $result;
117             }
118              
119             =method create
120              
121             my $result = $containers->create(
122             Image => 'nginx:latest',
123             name => 'my-nginx',
124             Cmd => ['/bin/sh'],
125             Env => ['FOO=bar'],
126             );
127              
128             Create a new container. Returns hashref with C and C.
129              
130             The C parameter is extracted and passed as query parameter. All other
131             parameters are Docker container configuration (see Docker API documentation).
132              
133             Common config keys: C, C, C, C, C.
134              
135             =cut
136              
137             sub inspect {
138 2     2 0 670 my ($self, $id) = @_;
139 2 100       228 croak "Container ID required" unless $id;
140 1         18 my $result = $self->client->get("/containers/$id/json");
141 1         40 return $self->_wrap($result);
142             }
143              
144             =method inspect
145              
146             my $container = $containers->inspect($id);
147              
148             Get detailed information about a container. Returns L object.
149              
150             =cut
151              
152             sub start {
153 2     2 0 1700 my ($self, $id) = @_;
154 2 100       175 croak "Container ID required" unless $id;
155 1         13 return $self->client->post("/containers/$id/start", undef);
156             }
157              
158             =method start
159              
160             $containers->start($id);
161              
162             Start a container.
163              
164             =cut
165              
166             sub stop {
167 2     2 0 1533 my ($self, $id, %opts) = @_;
168 2 100       104 croak "Container ID required" unless $id;
169 1         2 my %params;
170 1 50       5 $params{t} = $opts{timeout} if defined $opts{timeout};
171 1 50       5 $params{signal} = $opts{signal} if defined $opts{signal};
172 1         10 return $self->client->post("/containers/$id/stop", undef, params => \%params);
173             }
174              
175             =method stop
176              
177             $containers->stop($id, timeout => 10);
178              
179             Stop a container.
180              
181             Options:
182              
183             =over
184              
185             =item * C - Seconds to wait before killing (default 10)
186              
187             =item * C - Signal to send (default SIGTERM)
188              
189             =back
190              
191             =cut
192              
193             sub restart {
194 0     0 0 0 my ($self, $id, %opts) = @_;
195 0 0       0 croak "Container ID required" unless $id;
196 0         0 my %params;
197 0 0       0 $params{t} = $opts{timeout} if defined $opts{timeout};
198 0         0 return $self->client->post("/containers/$id/restart", undef, params => \%params);
199             }
200              
201             =method restart
202              
203             $containers->restart($id, timeout => 10);
204              
205             Restart a container. Optionally specify C in seconds.
206              
207             =cut
208              
209             sub kill {
210 0     0 0 0 my ($self, $id, %opts) = @_;
211 0 0       0 croak "Container ID required" unless $id;
212 0         0 my %params;
213 0 0       0 $params{signal} = $opts{signal} if defined $opts{signal};
214 0         0 return $self->client->post("/containers/$id/kill", undef, params => \%params);
215             }
216              
217             =method kill
218              
219             $containers->kill($id, signal => 'SIGKILL');
220              
221             Send a signal to a container. Default signal is C.
222              
223             =cut
224              
225             sub remove {
226 1     1 0 638 my ($self, $id, %opts) = @_;
227 1 50       5 croak "Container ID required" unless $id;
228 1         3 my %params;
229 1 0       4 $params{v} = $opts{volumes} ? 1 : 0 if defined $opts{volumes};
    50          
230 1 0       4 $params{force} = $opts{force} ? 1 : 0 if defined $opts{force};
    50          
231 1 0       4 $params{link} = $opts{link} ? 1 : 0 if defined $opts{link};
    50          
232 1         17 return $self->client->delete_request("/containers/$id", params => \%params);
233             }
234              
235             =method remove
236              
237             $containers->remove($id, force => 1, volumes => 1);
238              
239             Remove a container.
240              
241             Options:
242              
243             =over
244              
245             =item * C - Force removal (kill if running)
246              
247             =item * C - Remove associated volumes
248              
249             =item * C - Remove specified link
250              
251             =back
252              
253             =cut
254              
255             sub logs {
256 0     0 1 0 my ($self, $id, %opts) = @_;
257 0 0       0 croak "Container ID required" unless $id;
258 0         0 my %params;
259 0 0       0 $params{stdout} = defined $opts{stdout} ? ($opts{stdout} ? 1 : 0) : 1;
    0          
260 0 0       0 $params{stderr} = defined $opts{stderr} ? ($opts{stderr} ? 1 : 0) : 1;
    0          
261 0 0       0 $params{since} = $opts{since} if defined $opts{since};
262 0 0       0 $params{until} = $opts{until} if defined $opts{until};
263 0 0       0 $params{timestamps} = $opts{timestamps} ? 1 : 0 if defined $opts{timestamps};
    0          
264 0 0       0 $params{tail} = $opts{tail} if defined $opts{tail};
265 0         0 return $self->client->get("/containers/$id/logs", params => \%params);
266             }
267              
268             =method logs
269              
270             my $logs = $containers->logs($id, tail => 100, timestamps => 1);
271              
272             Get container logs.
273              
274             Options:
275              
276             =over
277              
278             =item * C - Include stdout (default 1)
279              
280             =item * C - Include stderr (default 1)
281              
282             =item * C - Show logs since timestamp
283              
284             =item * C - Show logs before timestamp
285              
286             =item * C - Include timestamps
287              
288             =item * C - Number of lines from end (e.g., C<100> or C)
289              
290             =back
291              
292             =cut
293              
294             sub top {
295 1     1 0 352 my ($self, $id, %opts) = @_;
296 1 50       7 croak "Container ID required" unless $id;
297 1         2 my %params;
298 1 50       4 $params{ps_args} = $opts{ps_args} if defined $opts{ps_args};
299 1         9 return $self->client->get("/containers/$id/top", params => \%params);
300             }
301              
302             =method top
303              
304             my $processes = $containers->top($id, ps_args => 'aux');
305              
306             List running processes in a container. Returns hashref with C and C arrays.
307              
308             =cut
309              
310             sub stats {
311 1     1 0 1331 my ($self, $id, %opts) = @_;
312 1 50       6 croak "Container ID required" unless $id;
313 1         3 my %params;
314 1         4 $params{stream} = 0;
315 1         3 $params{'one-shot'} = 1;
316 1         11 return $self->client->get("/containers/$id/stats", params => \%params);
317             }
318              
319             =method stats
320              
321             my $stats = $containers->stats($id);
322              
323             Get container resource usage statistics (CPU, memory, network, I/O). Returns one-shot statistics.
324              
325             =cut
326              
327             sub wait {
328 0     0 1 0 my ($self, $id, %opts) = @_;
329 0 0       0 croak "Container ID required" unless $id;
330 0         0 my %params;
331 0 0       0 $params{condition} = $opts{condition} if defined $opts{condition};
332 0         0 return $self->client->post("/containers/$id/wait", undef, params => \%params);
333             }
334              
335             =method wait
336              
337             my $result = $containers->wait($id, condition => 'not-running');
338              
339             Block until container stops, then return exit code. Optional C parameter.
340              
341             =cut
342              
343             sub pause {
344 1     1 0 873 my ($self, $id) = @_;
345 1 50       3 croak "Container ID required" unless $id;
346 1         6 return $self->client->post("/containers/$id/pause", undef);
347             }
348              
349             =method pause
350              
351             $containers->pause($id);
352              
353             Pause all processes in a container.
354              
355             =cut
356              
357             sub unpause {
358 1     1 0 522 my ($self, $id) = @_;
359 1 50       7 croak "Container ID required" unless $id;
360 1         12 return $self->client->post("/containers/$id/unpause", undef);
361             }
362              
363             =method unpause
364              
365             $containers->unpause($id);
366              
367             Unpause all processes in a container.
368              
369             =cut
370              
371             sub rename {
372 0     0 0   my ($self, $id, $name) = @_;
373 0 0         croak "Container ID required" unless $id;
374 0 0         croak "New name required" unless $name;
375 0           return $self->client->post("/containers/$id/rename", undef, params => { name => $name });
376             }
377              
378             =method rename
379              
380             $containers->rename($id, 'new-name');
381              
382             Rename a container.
383              
384             =cut
385              
386             sub update {
387 0     0 0   my ($self, $id, %config) = @_;
388 0 0         croak "Container ID required" unless $id;
389 0           return $self->client->post("/containers/$id/update", \%config);
390             }
391              
392             =method update
393              
394             $containers->update($id, Memory => 314572800);
395              
396             Update container resource limits and configuration.
397              
398             =cut
399              
400             sub prune {
401 0     0 0   my ($self, %opts) = @_;
402 0           my %params;
403 0 0         $params{filters} = $opts{filters} if defined $opts{filters};
404 0           return $self->client->post('/containers/prune', undef, params => \%params);
405             }
406              
407             =method prune
408              
409             my $result = $containers->prune(filters => { until => ['24h'] });
410              
411             Delete stopped containers. Returns hashref with C and C.
412              
413             =cut
414              
415             =seealso
416              
417             =over
418              
419             =item * L - Main Docker client
420              
421             =item * L - Container entity class
422              
423             =item * L - Execute commands in containers
424              
425             =back
426              
427             =cut
428              
429             1;