Docker Básico

Qué es docker

Es una herramienta que permite crear contenedores portátiles y de poco peso que puedan encapsular nuestra aplicación y correr bajo una máquina que posea Docker instalado. Esto independientemente del sistema operativo de la máquina

Principalmente el objetivo detrás de todo este esquema, es facilitar la portabilidad y el despliegue de nuestras aplicaciones, minimizando las dependencias requeridas sujetas al sistema operativo en la que se encuentre la misma.

Básicamente, Docker lleva el concepto de “encapsulamiento” proporcionado por las VM (Virtual Machines) a otro nivel. La gran diferencia radica en que teniendo nuestra aplicación en máquinas virtuales, dichas máquinas necesitan emular todo un sistema operativo por completo, independientemente de si usemos o nos todos los componentes del mismo.

Si tomamos en consideración todo lo que ello implica, nos encontraremos con una gran sobrecarga y gasto de recursos. Docker, por el contrario, utiliza solo contenedores y los mismos comparten un mismo sistema operativo y no sólo eso, sino que además por su forma modular, pueden compartir librerías entre sí, eliminando el “overhead” que implica emular todo un sistema operativo por cada parte que queramos encapsular de nuestra aplicación.

En la imagen previa, podemos apreciar la arquitectura entre un sistema compuesto por VM’s vs uno construido en con Docker.

Instalar Docker

Comencemos a trabajar, para ello debemos instalar Docker.

Podemos descargar Docker desde la página oficial

https://docs.docker.com/engine/installation/

Instalamos Docker y el set de herramientas que trae.

Abrimos Kitematic y luego le damos click Docker CLI, enseguida se nos abrirá una consola donde ejecutaremos nuestros comandos de docker.

Principalmente, Docker está dividido en dos grandes partes, el deamon y el client. Veamos un poco acerca de ellos.

Docker Daemon

Se refiere al proceso demonizado o “background process” que corre dentro de la capa de “Docker Engine” o “Motor de Docker”. El mismo se encarga de escuchar y ejecutar las instrucciones provenientes de un cliente (más adelante lo veremos con detalle). Estos comandos sirven para crear/detener/eliminar los contenedores donde se alojarán nuestras aplicaciones.

Docker Client

Contiene todos los comandos necesarios para manipular nuestros contenedores de docker. Estas instrucciones están expuesta al usuario y nos permitirá manejar toda nuestra infraestructura.

Comencemos

Correr contenedor “Hello Word”

Para crear contenedores de docker se usa el comando docker run

$ docker run busybox echo hello world

Con este comando creamos un contenedor con la imagen busybox que imprima un “hello word” dentro. Luego, el contenedor se detiene, se puede asemejar como a una especie de “job”.

Imagen de Docker

Pero si nos preguntamos, qué son docker images. Simple, una imagen de docker se pueden asemejar a una plantilla base que se usa para crear el contenedor, en la misma, están las dependencias que necesitan nuestras aplicaciones.

Actualmente hay muchas imágenes públicas, por ejemplo, imágenes de Apache, Nginx, Java, entre otras, las cuáles se pueden descargar y utilizar para crear nuestro contenedor. De esta forma, fácilmente podemos crear un contenedor con un servidor de apache ya configurado usando una imagen ya pública.

Para listar nuestras imágenes usamos el comando.

$ docker images  
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE  
busybox                          latest              efe10ee6727f        2 weeks ago         1.13MB

Actualmente no tenemos ninguna creada. La de busybox fue traída del registro público de imágenes de docker.

Correr un contenedor interactivo

$ docker run -t -i alpine /bin/bash
  • -t: Aloca una tty

  • -i: Nos comunicamos con el contenedor de modo interactivo.

Ahora podremos ejecutar comandos en la consola dentro de nuestro contenedor.

Al salir del modo interactivo, el contenedor se detendrá. Intentalo con Ctrl+C o Command + C.

Correr un contenedor en modo “background”

Vimos cómo crear un contenedor para ejecutar una instrucción o interactuar con él, teniendo en cuenta que el mismo se detiene luego de finalizar la acción, pero qué sucede si deseamos crear un pequeño servidor web. Nos interesa que el contenedor quede corriendo de fondo aceptando nuestras peticiones.

Creemos un servidor web simple usando python 3.5

$ docker run -d -p 1234:1234 python:3.5 python -m http.server 1234

Este comando crea un servidor de python usando SimpleHTTPServer en el puerto 1234. El argumento-p 1234:1234 le indica a docker que tiene que hacer un port forwarding del puerto 1234 del host al 1234 del contenedor.

El flag -d le indica a Docker que debe crear ese contenedor en segundo plano, es decir, que aunque nos salgamos, el contenedor seguirá corriendo. Esto es importante porque nos va permitir ejecutar comandos dentro del contenedor mientras corre.

Ya tenemos nuestro primer servidor de python, para abrirlo

En Linux:

$ google-chrome localhost:1234

En Mac:

$ open "http://$(docker-machine ip default):1234"

Entrar a modo interactivo sobre un contenedor en segundo plano

Digamos que deseamos entrar a nuestro contenedor y ejecutar algunos comandos en la consola. Para ello usamos el comando

$ docker exec -ti <container-id> /bin/bash

Pero cómo obtenemos el id del contenedor. Simple

$ docker ps
CONTAINER ID        IMAGE        COMMAND                CREATED         STATUS          PORTS                    
c4489be8b466        python:3.5   "python -m http.se..." 48 seconds ago  Up 46 seconds   0.0.0.0:4321->4321/tcp

Esto nos listará los contenedores que actualmente están corriendo.

Copiamos el id de nuestro contenedor de python y ejecutamos el comando. En este caso sería

$ docker exec -ti c4489be8b466 /bin/bash

Se nos abrirá una consola y ahí podemos ejecutar cualquier instrucción que deseemos.

Verifiquemos la versión de python del contenedor. Ejecutamos

python -V
>>Python 3.5.3

Salimos del contenedor con el comando exit

Ciclo de vida de un contenedor

Ya sabemos como crear un contenedor, pero Docker ofrece mucho más opciones a la hora de manejar nuestros contenedores. A un contenedor podemos crearlo, pararlo y eliminarlo. Para ello, tenemos a nuestra disposición una serie de comandos como docker create, start, stop, kill y rm.

Nota: docker create equivale a docker run -d pero con la diferencia que nosotros mismos debemos arrancar el contenedor usando docker start, algo que ya docker run -d hace.

Creemos un nuevo contenedor con otro servidor python en el puerto 8002

$ docker create -P --expose=8002 python:3.5 python -m http.server

Listamos nuestros contenedores, pero agregamos el flag -a, esto nos listarás los contenedores que hemos corrido, creado o los que ya no están corriendo.

$ docker ps -a
CONTAINER ID   IMAGE       COMMAND                 CREATED         STATUS             PORTS                   ..  
2c349246e9f3   python:3.5  "python -m http.se..."  30 seconds ago  Created                                    ..  
c4489be8b466   python:3.5  "python -m http.se..."  5 minutes ago   Up 5 minutes       0.0.0.0:4321->4321/tcp  ..  
0b785f6b937d   busybox     "echo hello world"      40 minutes ago  Exited (0) 40 minutes ago

Arrancamos nuestro contenedor recien creado, tomando el ID del mismo, en este caso tendrá el estatus created

$ docker start 2c349246e9f3

Ahora, si queremos detener el contenedor para que no siga corriendo. Tenemos dos opciones, kill o stop.

  • $ docker kill a842945e2414(envía SIGKILL)

  • $ docker stop a842945e2414(envía SIGTERM)

Si lo que deseamos es reiniciar nuestro contenedor, utilizamos docker restart contenedor_id

$ docker restart a842945e2414

Ahora, si necesitamos eliminarlo, usamos el comando docker rm contenedor_id

$ docker rm a842945e2414

Nota: Para eliminar nuestro contenedor, el mismo debe estar detenido.

Crear nuestra primera imagen de Docker

Ya vimos el uso que se le dan a las imágenes de Docker. Hasta el momento solo hemos utilizados imágenes públicas ya creadas, pero qué sucede si necesitamos crear nuestra propia imagen para manejar nuestra aplicación y todas las dependencias especiales que pudiéramos requerir.

Para hacer una propia, debemos crear un archivo llamado Dockerfile. En el cual, debemos definir secuencialmente todas las instrucciones necesarias para correr nuestro contenedor, como: instalación de dependencias, creación de directorios, creación de variable de entornos, entre otros.

Vamos a crear una imagen para solamente definir una variable de entorno.

Comenzamos:

$ mkdir primera_imagen && cd primera_imagen        
$ touch Dockerfile

Abrimos nuestro Dockerfile y escribimos:

FROM alpine        
ENV bar=foo

NOTA: Para la creación del Dockerfile, Docker nos proporciona una serie de comandos, en este ejemplo, utilizamos ENV y FROM, pero hay muchos más disponibles. Pueden revisarlos acá en la documentación oficial:

https://docs.docker.com/engine/reference/builder/

Luego para construir nuestra imagen usando el archivo Dockerfile previamente definido, utilizamos el comando build

$ docker build -t primera_imagen .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM alpine
latest: Pulling from library/alpine
88286f41530e: Pull complete
Digest: sha256:1072e499f3f655a032e88542330cf75b02e7bdf673278f701d7ba61629ee3ebe
Status: Downloaded newer image for alpine:latest
 ---> 7328f6f8b418
Step 2/2 : ENV bar foo
 ---> Running in 2fc17f32ae5c
 ---> 4c9f74bc4a67
Removing intermediate container 2fc17f32ae5c
Successfully built 4c9f74bc4a67
Successfully tagged primera_imagen:latest

Para verificar que tenemos nuestra imagen, las listamos.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
primera_imagen      latest              4c9f74bc4a67        22 minutes ago      3.97MB
python              3.5                 56b15234ac1d        10 days ago         684MB
busybox             latest              efe10ee6727f        2 weeks ago         1.13MB
alpine              latest              7328f6f8b418        5 weeks ago         3.97MB

Deberíamos tener nuestra imagen creada.

results matching ""

    No results matching ""