En un post anterior ya vimos qué es Docker y sus principales características. En este artículo vamos a ver cómo instalar Docker, primeros pasos, los comandos básicos, las imágenes y contenedores.

Lo primero que me gustaría comentar es que el motor de Docker está compuesto por 2 partes:

  • un demonio, que es un proceso que se encarga de manejar todos los contenedores.

  • un cliente, que es el que interactua con demonio.


Cómo instalar Docker

Vamos echar una ojeada rápida sobre cómo instalar Docker en Ubuntu 14.04, OSX y Windows. Es decir, no tienes excusa para no probar esta excelente herramienta.

Unbutu 14.04 LTS (64-bit)

En mi caso, voy a partir de una instalación vacía de Ubuntu 14.04 creada en la capa gratuíta de AWS. No voy a explicar qué pasos he seguido para crearme una cuenta en AWS porque está fuera del alcance de este artículo, pero haciendo una búsqueda rápida en Google encontrarás cientos de tutoriales.

Lo primero que haremos es actualizar Ubuntu. Para ello, ejecutamos:

$ > sudo apt-get update

Instalamos Docker:

$ > sudo apt-get install docker.io

Llegados a este punto, ya podemos verificar que la instalación está bien hecha ejecutando nuestro primer contenedor de prueba:

$ > sudo docker run -i -t ubuntu /bin/bash

NOTA: El comando anterior descarga la imagen de ubuntu y ejecuta el shell bash en modo interactivo. Más abajo puedes ver qué significa cada uno de los parámetros del comando.

OSX

El motor de Docker utiliza las características específicas del kernel de Linux. Por tanto, en caso de que no seamos usuarios de alguna distro de Linux (Ubuntu, CentOS, Debian, etc…) tendremos que utilizar la máquina virtual Boot2docker.

Para instalarlo en OSX, sólo hay que descargarse el instalador del repositorio oficial de Boot2Docker y ejecutarlo.

Para poder utilizar Docker, tenemos que arrancar la máquina virtual. Para ello, lo primero que tenemos que hacer es inicializarla. Podemos hacelor de 2 formas:

  1. Haciendo doble click sobre la app boot2docker que tendrás en la carpeta Aplicaciones.

  2. Desde el terminal. Tanto docker como los binarios de boot2docker los puedes encontrar /usr/local/bin por lo que podemos arrancarlo a través del terminal ejecuntando:

    $ > cd /usr/local/bin
    $ > boot2docker init 
    

A continuación, sólo tenemos que ejecutar el siguiente comando para arrancar la MV y el demonio de Docker.

$ > boot2docker start

Waiting for VM and Docker daemon to start...
...............................
Started.
Writing /Users/koldo/.boot2docker/certs/boot2docker-vm/ca.pem
Writing /Users/koldo/.boot2docker/certs/boot2docker-vm/cert.pem
Writing /Users/koldo/.boot2docker/certs/boot2docker-vm/key.pem

To connect the Docker client to the Docker daemon, please set:
    export DOCKER_HOST=tcp://192.168.59.103:2376
    export DOCKER_CERT_PATH=/Users/koldo/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1

Cuando arrancamos la máquina virtual boot2docker, debemos exportar las variables de entorno que nos indica para poder ejecutar cualquier contenedor.

NOTA: Cada vez que cerremos la sesión del terminal, tendremos que volver a exportar las variables de entorno, a menos que las añadamos al bin/bash

Una vez tenemos arrancada la máquina virtual y hemos exportado las variables de entorno, ya podemos ejecutar comandos de Docker para bucar imágenes, montarlas, etc…

Para probar que todo funciona bien, ejecutamos el siguiente comando:

$ > docker run hello-world

, que lo que hace es descargarnos una imagen muy ligera y

Para acceder al sistema de ficheros de la máquina virtual, ejecutamos el siguiente comando:

$ > boot2docker ssh

Un tema interesante es que cuando hemos accedido por ssh a la máquina virtual, podemos acceder al sistema de ficheros del sistema operativo anfitrión, es decir, nuestro OSX. Para ello, podemos ejecutar el siguiente comando:

    $ > ls /Users/koldo/Desktop

, que lista todos los ficheros y carpetas que tiene el usuario koldo en el escritorio.

Si usamos el comando uname -a puede verse que aunque el contenedor usa el sistema de archivos de una distribución debian el kernel empleado es el del sistema anfitrión, esto es así porque los contenedores docker en esencia no son más que procesos dentro del sistema.

Windows

Al igual que con OSX, para utilizar Docker sobre Windows necesiteremos instalar la máquina virtual Boot2Docker. Hay que descargarse el instalador del repositorio oficial y ejecutarlo.

Una vez hecho esto, para acceder a la máquina virtual sólo tienes que ejecutar la aplicación Boot2Docker Start.

Para acceder al sistema de ficheros de Windows, ejecutamos el siguiente comando:

$ > ls /c/Users/mi_usuario_win/Desktop

, y nos listará todos los ficheros y carpetas que tiene el usuario mi_usuario_win en el escritorio.

Actualizando Boot2Docker

Si queremos actualizar la instalación de boot2docker, tendremos que ejecutar el siguiente comando:

$ > boot2docker stop
$ > boot2docker download
$ > boot2docker up

, auque también podemos actualizas la máquina virtual de boot2docker sin perder datos ejecutando:

$ > boot2docker upgrade


Comandos de Docker

Para ver los argumentos soportados por docker, ejecutamos:

$ > docker

    attach    Attach to a running container
    build     Build a container from a Dockerfile
    commit    Create a new image from a container's changes
    diff      Inspect changes on a container's filesystem
    export    Stream the contents of a container as a tar archive
    history   Show the history of an image
    images    List images
    import    Create a new filesystem image from the contents of a tarball
    info      Display system-wide information
    insert    Insert a file in an image
    inspect   Return low-level information on a container
    kill      Kill a running container
    login     Register or Login to the Docker registry server
    logs      Fetch the logs of a container
    port      Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
    ps        List containers
    pull      Pull an image or a repository from the Docker registry server
    push      Push an image or a repository to the Docker registry server
    restart   Restart a running container
    rm        Remove a container
    rmi       Remove an image
    run       Run a command in a new container
    search    Search for an image in the Docker index
    start     Start a stopped container
    stop      Stop a running container
    tag       Tag an image into a repository
    version   Show the Docker version information
    wait      Block until a container stops, then print its exit code

Se puede consultar la documentación oficial de los comandos en el siguiente enlace:

http://docs.docker.com/reference/commandline/cli/

Creando un contenedor

El primer comando que debemos conocer es run que permite crear y ejecutar un contenedor.

El comando run permite pasarle una serie de parámetros con los que le podemos asignar memoria, cpu, variables de entorno, servidor DNS, etc…

Para ejecutar un contenedor, lo primero que necesitamos es una imagen.

$ > docker run -i -t ubuntu /bin/echo Bienvenido! Este es mi primer contenedor de Docker

    Unable to find image 'ubuntu' locally
    ubuntu:latest: The image you are pulling has been verified
    511136ea3c5a: Pull complete
    01bf15a18638: Pull complete
    30541f8f3062: Pull complete
    e1cdf371fbde: Pull complete
    9bd07e480c5b: Pull complete
    Status: Downloaded newer image for ubuntu:latest
    Bienvenido! Este es mi primer contenedor de Docker

¿Qué hace el comando run anterior?

  1. Comprueba que tenemos la imagen solicitada en nuestro entorno local.

    • Si la tenemos, la utiliza.

    • Si no la tenemos, la descarga del respositorio Docker Hub.

  2. Crea un nuevo contenedor.

  3. Le asigna espacio para el sistema de archivos y monta / añade una capa de lectura y escritura a la imágen.

  4. Crea y asigna una interfaz de red / puente que permite al contenedor la comunicación con el host local.

  5. Detecta y concede una dirección IP disponible desde un grupo de IPs.

  6. Ejecuta ejecuta el comando especificado.

En el ejemplo anterior, el contenedor tras ejecutar el comando echo automaticamente se detiene, ya que dicho comando imprime un resultado por pantalla y termina el proceso. Por lo tanto Docker entiende que ya el contenedor debe detenerse.

Parámetros de interés

Si queremos ver la lista lista completa de parámetros que acepta el comando run ejecutamos:

$ > docker run -h

A continuación, voy a listar unos cuantos parámetros de uso común al ejecutar el comando run:

  • -rm: elimina el contenedor una vez haya finalizado su ejecución.

  • -t: asigna un emulador de terminal al comando.

  • -d: ejecuta el contenedor en modo background. Por ejemplo, si ejecutamos el siguiente comando estaremos pintando de forma infinita cada segundo el mensaje "hello world".

    $ > sudo docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
    

    Pero sólo podremos ver el resultado de dicha ejecución si examinamos lo ejecutado con:

    $ > sudo docker logs <contenedor_id>
    
  • -i: hace que la ejecución de los comandos sea interactiva, mostrando por pantalla los resultados de la ejecución del comando sobre el contenedor.

  • -P: cuando pasamos este parámetro al comando run, Docker mapea todos los puertos expuestos en nuestra imagen a nuestro host.

¿Dónde se guardan las imágenes?

En caso de estar utilizando boot2docker, las imagenes de Docker se guardan dentro de la máquina virtual. En caso contrario, las puedes encontrar en /var/lib/docker/graph/<id>/layer.

Hay que tener en cuenta que las imágenes sólo contienen las diferencias hechas respecto a la imagen original. El id de la imagen original se guarda en el fichero json que contiene la metaimformación de la imagen (/var/lib/docker/graph/<id>/json)


Otros comandos comunes

  • Ver las imagenes que tenemos en la maquina virtual ejecutando:

    $ > docker images
    
  • Ver las instancias de los contenedores iniciadas

    $ > docker ps
    
  • Ver las instancias de los contenedores iniciadas y las no iniciadas

    $ > docker ps -a
    
  • Eliminar las instancias de una imagen (contenedores)

    $ > docker rm <contenedor_id>
    
  • Eliminar las imágenes que no estén siendo usadas por ningún contenedor (si están siendo usadas deberemos eliminar primero el contenedor)

    $ > docker rmi <imagen_id>
    
  • Arrancar un contenedor parado

    $ > docker start -a <contenedor_id>
    


Aspectos importantes a tener en cuenta

Hay que saber que Docker inicia un único proceso y que cuando finaliza la ejecución de dicho proceso, el contenedor se detiene. Esto lo hemos explicado en el ejemplo de los apartados anteriores: una vez el proceso ha mostrado el mesaje por la consola, el contenedor se detiene.

Para evitar que un contenedor se detenga, podemos utilizar un proceso inicial que se encargue de arrancar otros procesos.

Si usásemos alguna imagen de ubuntu y quisiésemos iniciar varios procesos en el contenedor deberíamos usar un gestor de procesos para Linux tipo Supervisord o Runit.

En cambio, existe una imagen llamada Phusion que ofrece un sistema de inicio adaptado al funcionamiento de docker y que ya ofrece esta funcionalidad de forma más sencilla (la gestión de los procesos está basada en Runit)