The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Eixo::Docker - Suite of Perl modules to interact with Docker

SYNOPSIS

First we need docker api server running in a tcp socket

- For example, to run api in localhost:4243, add this line to /etc/default/docker

    DOCKER_OPTS="-H 127.0.0.1:4243 -d"

- And restart docker service

    $ sudo service docker restart

Now to interact with it, instantiate a docker api client with the tcp socket url of the docker API:

    use Eixo::Docker::Api;
    
    my $a = Eixo::Docker::Api->new('http://127.0.0.1:4243'); 

    # TO USE https

    my $a = Eixo::Docker::Api->new(

        host => '1.1.1.1:2376', # default to $ENV{DOCKER_HOST},
        tls_verify => 1,        # default to $ENV{DOCKER_TLS_VERIFY}
        ca_file => 'ca.pem',    # path to ca cert file, default to $ENV{DOCKER_CERT_PATH}/ca.pem,
        cert_file =>'cert.pem', # path to client cert file, default to $ENV{DOCKER_CERT_PATH}/cert.pem,
        key_file => 'key.pem',  # path to client key file, default to $ENV{DOCKER_CERT_PATH}/key.pem

    );

    # OR

    my $a = Eixo::Docker::Api->new(
        'https://1.1.1.1:2376'

        ca_file => 'ca.pem',
        cert_file =>'cert.pem',
        key_file => 'key.pem',
    );

From now on you can call all the Docker api methods throught api products (containers and images), passing the args indicated in api documentation:

Interacting with containers

Getting a container

    #
    # CONTAINERS
    #
    
    ## get (by id)
    my $c = $a->containers->get(id => "340f03a2c2cfxx");
    
    ## getByName
    my $c = $a->containers->getByName("testing123");

Creating a container

    # create
    # to see all available params 
    # http://docs.docker.io/en/latest/api/docker_remote_api_v1.10/#create-a-container
    my $c = $a->container->create(
        Hostname => 'test',
        Memory   => 128,
        Cmd => ["ls","-l"],
        Image => "ubuntu",
        Name => "testing123"
    );

Creating a container (asynchronous version)

    #
    #  Closure to get the created container
    # 
    my $new_container;

    $api->containers->createAsync(
        
        %args_creation,

        onSuccess=> sub {

                $new_container = $_[0];

        }

    );

    #
    # Waiting for the job to complete
    #
    $api->waitForJobs;

Start/stop/restart/kill a container

   $container->start();

   $container->stop();

   $container->restart();

   $container->kill();

Binding a container port to a host interface

The container must be created with 'NetworkDisabled' = 'false' and 'ExposedPorts' defined

    my $c = $a->containers->create(
        Hostname => 'test',
        Cmd => ["nc", "-l", '0.0.0.0', '5555'],
        Image => "ubuntu",
        Name => "testing123",
        NetworkDisabled => "false",
        ExposedPorts => {
                 "5555/tcp" =>  {}  
         },
    );

When starting the container the 'PortBindings' must be defined

    $c->start(
         "PortBindings" => { 
                 "5555/tcp" =>  [{"HostIp" =>  "0.0.0.0", "HostPort" =>  "11022" }] 
         },
    );

Attaching volumes to containers

Similar to ports, Volumes must be specified in creation as 'Binds' inside 'HostConfig' (since api v1.19)

    my $c = $a->containers->create(
        Hostname => 'test',
        Cmd => ["nc", "-l", '0.0.0.0', '5555'],
        Image => "ubuntu",
        Name => $name,
        HostConfig => {
            Binds => {
                '/mnt:/tmp',
                '/usr:/usr:ro'
            },
        }
    );

When starting the container the volumes will be seen as 'Mounts' (since docker api v1.20)

  "Mounts": [
        {
            "Source": "/mnt",
            "Destination": "/tmp",
            "Mode": "",
            "RW": true
        },
        {
            "Source": "/usr",
            "Destination": "/usr",
            "Mode": "",
            "RW": false
        }

    ],
    

Deleting a container

    ## delete
    $container->delete();

Deleting a container (asynchronous version)

    my $job_id = $container->deleteAsync(

        onSuccess=>sub {

                # 
                # Container has been deleted
                #
        }

    );

    # Others things to do...
    #

    #
    # We wait for the specific job to finish
    #   
    $api->waitForJob($job_id);

Interacting with images

Getting an image

    ## get
    my $image = $a->images->get(id => "busybox");

Getting an image history

    ## history 
    print Dumper($image->history);

Create an image pulling it from registry

    ## create
    my $image = $a->images->create(
    
        fromImage=>'busybox',
    
        onSuccess=>sub {
            
            print "FINISHED\n";     
    
        },
    
        onProgress=>sub{
    
            print $_[0] . "\n";
        }
    );
    

Building images (from a Dockerfile)

    ## build
    my $image = $a->images->build(
        t => "my_image",
        Dockerfile => join("\n", <DATA>),
    );
    
    ## build_from_dir
    my $image = $a->images->build_from_dir(
        t => "my_image",
        DIR => "/tmp/directory_with_a_Dockerfile"
    );

Deleting an image

    ## delete
    $image->delete();

DESCRIPTION

The purpose of this library is to provide a set of modules to interact in a simple, but powerful way, with the Docker remote api

Containers supported methods:

  • get

  • getByName

  • getAll

  • create

  • delete

  • status

  • start

  • stop

  • restart

  • kill

  • copy

  • attach

  • top

Images supported methods:

  • get

  • getAll

  • history

  • create

  • build

  • build_from_dir

  • delete

DEPENDENCIES

Currently this module has the following dependencies:

  • Eixo::Base >= 1.200,

  • Eixo::Rest >= 1.020,

    To support https we use LWP::Protocol::https module that needs ssl dev libraries installed in system.

    In ubuntu/debian:

       apt-get install libssl-dev
  • JSON >= 2.50,

  • Net::HTTP >= 6.06,

  • HTTP::Server::Simple::CGI (for testing purpose)

CAVEATS

- No unix socket support, currently only supports tcp connections to Docker API.

DEVELOPMENT

To setup development environment:

Ubuntu 12.04 64bits:

Install kernel 3.8

    # install the backported kernel
    sudo apt-get update
    sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring
    
    # reboot
    sudo reboot

Install docker:

    curl -s https://get.docker.io/ubuntu/ | sudo sh

Setup docker daemon listening in localhost:4243 tcp port:

  • Add this line to /etc/default/docker

        DOCKER_OPTS="-H 127.0.0.1:4243 -d"
  • restart docker service:

        $ sudo service docker restart
  • export DOCKER_TEST_HOST var to run integration tests

        export DOCKER_TEST_HOST=http://127.0.0.1:4243

More info at http://docs.docker.io

AUTHOR

Francisco Maseda, <frmadem@gmail.com>

Javier Gomez, <alambike@gmail.com>

COPYRIGHT AND LICENSE

Copyright (C) 2014, Francisco Maseda

Copyright (C) 2014, Javier Gómez

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.