API-Docker
view release on metacpan or search on metacpan
lib/API/Docker.pm view on Meta::CPAN
package API::Docker;
# ABSTRACT: Perl client for the Docker Engine API
our $VERSION = '0.004';
use Moo;
use Carp qw( croak );
use Log::Any qw( $log );
use API::Docker::API::System;
use API::Docker::API::Containers;
use API::Docker::API::Images;
use API::Docker::API::Networks;
use API::Docker::API::Volumes;
use API::Docker::API::Exec;
use API::Docker::API::Distribution;
use API::Docker::API::Secrets;
use API::Docker::API::Configs;
use API::Docker::API::Plugins;
use namespace::clean;
has host => (
is => 'ro',
default => sub { $ENV{DOCKER_HOST} // 'unix:///var/run/docker.sock' },
);
has api_version => (
is => 'rwp',
default => undef,
);
has tls => (
is => 'lazy',
);
sub _build_tls {
my ($self) = @_;
# The docker CLI's own rule, read off cli/flags/options.go:
# dockerTLSVerify = os.Getenv(client.EnvTLSVerify) != ""
# Every non-empty value turns TLS on, DOCKER_TLS_VERIFY=0 included. Perl
# truthiness would read that '0' as off and disagree with the CLI on exactly
# the value a user is most likely to type for "off", so the test is
# defined-and-not-empty rather than a boolean one.
return 0 unless defined $ENV{DOCKER_TLS_VERIFY}
&& $ENV{DOCKER_TLS_VERIFY} ne '';
# And the CLI ignores TLS on a socket host without saying so
# (cli/context/docker/load.go, "there's no need to configure TLS for a
# socket connection"). Ignoring it here is not politeness: BUILD croaks on
# tls => 1 with a non-tcp:// host, so a host-blind default would make a bare
# API::Docker->new die on every unix:// machine that exports the variable.
return $self->host =~ m{^tcp://} ? 1 : 0;
}
has cert_path => (
is => 'ro',
default => sub { $ENV{DOCKER_CERT_PATH} },
);
has tls_insecure => (
is => 'ro',
default => 0,
);
sub BUILD {
my ($self) = @_;
# Both checks are here rather than at connect time so that a request for
# encryption that cannot be honoured is refused before the caller has a
# client to hand credentials to.
croak __PACKAGE__ . '->new tls_insecure => 1 without tls => 1 does '
. 'nothing: verification is only reachable on a connection that has TLS '
. 'to verify. Set tls => 1 as well, or drop the option'
if $self->tls_insecure && !$self->tls;
return unless $self->tls;
my $host = $self->host;
croak __PACKAGE__ . '->new tls => 1 is only meaningful for a tcp:// host, '
. 'and this one is ' . $host . '. A Unix socket is a file rather than a '
. 'wire and carries nothing to encrypt, so honouring the option is not '
. 'possible and ignoring it would answer a request for an encrypted '
. 'transport with an unencrypted one'
unless $host =~ m{^tcp://};
lib/API/Docker.pm view on Meta::CPAN
host => 'tcp://dockerhost:2376',
tls => 1,
cert_path => '/home/me/.docker',
);
The default follows the C<docker> CLI rather than the Go SDK's C<FromEnv>: the
CLI reads the variable as C<< != "" >>, so B<every non-empty value turns TLS
on> -- C<DOCKER_TLS_VERIFY=0> included, and so are C<false>, C<no> and C<off>.
Only unset, or the empty string, is off. That is deliberately not Perl
truthiness: C<'0'> is the value most likely to be typed for "off" and is
precisely where the two rules would part company. An explicit C<< tls => ... >>
passed to the constructor outranks the variable in both directions.
The variable is B<ignored on a socket host>, as the CLI ignores it -- a
C<unix://>, C<npipe://> or C<fd://> connection carries nothing to encrypt.
Without that exception a shell exporting C<DOCKER_TLS_VERIFY> would make a bare
C<< API::Docker->new >> croak on every machine talking to a local socket, since
C<< tls => 1 >> on a non-C<tcp://> host is a construction error (below).
C<DOCKER_TLS_VERIFY> with no L</cert_path> and no C<DOCKER_CERT_PATH> beside it
is TLS against the system trust store, not an error; the CLI asks for no
certificates either, and non-empty there means encrypt B<and> verify.
With C<< tls => 1 >> the transport opens an L<IO::Socket::SSL> connection
instead of an L<IO::Socket::INET> one and nothing above the socket changes.
The daemon's certificate is B<verified>, and so is its hostname; L</cert_path>
supplies the trust anchor and this client's own certificate.
With no certificates at all it still means encrypt and verify, against the
system trust store -- see
L<API::Docker::Role::HTTP/"TLS with no certificates at all">
for why that rather than an error. To switch verification off, and to read
what that gives away, see L</tls_insecure>.
C<< tls => 1 >> on a C<unix://> host croaks at construction. A Unix socket is
a file, not a wire; there is nothing on it to encrypt, and accepting the
option would mean answering a request for an encrypted transport with an
unencrypted one -- which is the failure this attribute previously had.
L<IO::Socket::SSL> is a recommended rather than a required dependency, loaded
when the first TLS connection is opened; C<< tls => 1 >> without it installed
croaks naming it. See
L<API::Docker::Role::HTTP/"TLS on a tcp:// connection"> for the whole of the
policy.
=head2 cert_path
Directory holding the TLS certificates, in the layout the C<docker> CLI
writes: F<ca.pem> as the trust anchor, F<cert.pem> and F<key.pem> as this
client's certificate and key. Defaults to C<$ENV{DOCKER_CERT_PATH}>.
Each file is used if it is there. F<ca.pem> alone is a daemon this client
verifies but does not authenticate to; F<cert.pem> without F<key.pem> or the
reverse is a croak, since half a client certificate is an accident rather than
a mode. A C<cert_path> naming something that is not a directory croaks too.
B<Read only when L</tls> is set.> The default comes from the environment, and
C<DOCKER_CERT_PATH> is exported on plenty of machines that run the C<docker>
CLI, so a client that never asked for TLS is unaffected by having it set. A
TLS client that wants the system trust store rather than the CLI's private one
on such a machine passes C<< cert_path => undef >> explicitly.
=head2 tls_insecure
Turn certificate verification off. Default C<0>. Only read when L</tls> is
set, and named for what it does.
C<< tls_insecure => 1 >> sets C<SSL_VERIFY_NONE> and drops the hostname check,
which leaves a connection encrypted against a passive listener and against
nothing else: whoever answers it chooses the certificate, so anyone able to
redirect the connection reads and rewrites everything on it -- registry
credentials, image contents, the commands containers are started with.
It exists for a self-signed daemon certificate whose CA is not to hand. The
better answer is nearly always L</cert_path>: a self-signed certificate is its
own CA and works as F<ca.pem> directly.
Setting it without L</tls> croaks, rather than being accepted and doing
nothing.
=head2 system
Returns L<API::Docker::API::System> instance for system operations like
C<info>, C<version>, C<ping>, and C<events>.
=head2 containers
Returns L<API::Docker::API::Containers> instance for container operations like
C<list>, C<create>, C<start>, C<stop>, and C<remove>.
=head2 images
Returns L<API::Docker::API::Images> instance for image operations like
C<list>, C<pull>, C<push>, and C<remove>.
=head2 networks
Returns L<API::Docker::API::Networks> instance for network operations like
C<list>, C<create>, C<connect>, and C<disconnect>.
=head2 volumes
Returns L<API::Docker::API::Volumes> instance for volume operations like
C<list>, C<create>, and C<remove>.
=head2 exec
Returns L<API::Docker::API::Exec> instance for executing commands in containers.
=head2 distribution
Returns L<API::Docker::API::Distribution> instance for registry manifest
lookups: C<inspect> and C<exists>.
=head2 secrets
Returns L<API::Docker::API::Secrets> instance for secret operations: C<list>,
C<create>, C<inspect>, C<update> and C<remove>.
=head2 configs
( run in 3.372 seconds using v1.01-cache-2.11-cpan-d80b1682f3f )