Docker, una breve introducción.
Se dice que Docker y los contenedores son el futuro y la ultima innovación en el campo de la virtualizacion y demás, pero la “tecnología” que impulsa a estas innovaciones esta con nosotros desde los 80's.
Docker como tal es una api de contenedores de linux , cosa que tenemos desde 1982 pero en la actualidad Docker como su máximo exponente la ha echo popular.
Inicialmente uno de los creadores del Unix de BSD , Bill Joy, ideo la creación de chroot() una llamada al sistema que le permitía realizar las pruebas en la misma computadora donde desarrollaba y de esta forma tener control sobre sus entornos (desarrollo y pruebas), concretamente esta llamada se limita a restringir el sistema de archivos. En el 2000 la versión 4 de FreeBSD lo implemento con el nombre jails. De esta forma si un proceso tras invocar a chroot(/home/user/dev) ejecuta cd / el sistema operativo lo llevara a /home/user/ dev.
La virtualización a nivel sistema operativo implica que los contenedores engañarán a los procesos huéspedes presentándoles una vista limitada en los siguientes aspectos:
- Tablas de procesos
- Señales y comunicación entre procesos (IPC)
- Interfaces de red
- Dispositivos de hardware
- Límites en el consumo de recursos (espacio en disco,memoria, o ciclos de CPU)
- Información del sistema, como el nombre del equipo o la hora actual
Entonces el chiste esta en que tu Sistema Operativo puede crear entornos controlados donde yo puedo hacer cosas como por ejemplo:
Mi maquina tiene python 2.7 y creo un entorno usando chroot en donde tengo python 3.0 el entorno que cree utilizando chroot tiene sus propios permisos, usuarios, carpetas, etc, pero no interactua con los procesos de mi maquina a pesar de que es el sistema operativo fue quien lo creo, hasta aquí alguna duda???
La idea como tal, nos hace remitir nuestras mentes a las maquina virtuales, pero en este caso en particular no necesitas un hypervisor y los recursos no están limitados, los procesos que ejecutes en ese entorno son procesos del sistema acceden a todos los recursos de la maquina pero no pueden interferir con los procesos de la maquina anfitriona por cuestión de usuarios y permisos.
Ahora para que no tengas que andar con tus lineas de comandos porque es muy aburrido, la gente de Docker dijo entonces “vamos a crear una capa de abstracción para que todo el mundo pueda utilizar los contenedores de forma practica” (por cierto la mascota se llama Moby Dock), de esta manera aparecen 2 conceptos:
- Imagen
- Contenedor
El contenedor es el entorno que habíamos mencionado hace un momento con procesos corriendo, usuarios , etc y la imagen son todas las instrucciones que permiten que el contenedor este listo para ser utilizado ya sean descargas de paquetes , compilaciones, etc; la configuración del contenedor.
Existen 2 formas de obtener una imagen, desde Internet, o desde un Dockerfile, para el primer caso utilizamos el comando:
docker pull nombre_de_la_imagen
y en el segundo, es un archivo donde se escriben las instrucciones que serán ejecutadas en el contenedor, con previa conversión a una imagen, por ejemplo:
FROM debian:jessie
RUN apt-get update
RUN apt-get install -y curl git \
build-essential ruby1.9.3
ADD carpeta_en_host /app/carpeta_en_contenedor
WORKDIR /app/carpeta_en_contenedor
- FROM indica el nombre de la imagen en la cual nos estamos basando para hacer la nuestra, puede ser debian , ubuntu , arch, windows , etc
en este caso debian 8, - RUN indica las instrucciones a ejecutar como tal,
- ADD se emplea para copiar archivos o carpetas de archivos de la maquina anfitriona al contenedor, también existe el comando COPY que realiza la misma función con la diferencia que se si se emplea ADD a un archivo comprimido en automático se descomprime una vez copiado al contenedor para el caso de ejemplo da igual usar uno u otro. En el caso de ADD . /var/www/html especifica que todos los archivos ( . ) que están en la carpeta donde esta el Dockerfile sean copiados a la ubicación /var/www/html del contenedor.
- WORKDIR establece el directorio de trabajo es como si se hiciera un cd permanente o constante
Bueno entonces tenemos un Dockerfile listo, para construir la imagen usamos el comando:
docker build -t hola .
donde :
- -t : indica nombre que tendrá la imagen (tag) en este ejemplo sera hola
- . : indica que el dockerfile esta en el directorio donde se ejecuta el comando si esta en otra parte o tiene un nombre diferente a dockerfile usamos el parámetro -f /ruta/nombrearchivo
Las imágenes se pueden etiquetar, versionar, subir a un repositorio de imágenes de docker y almacenar como un archivo .tar, para visualizar las imagenes que hay en nuestro equipo utilizamos el comando :
docker images
para eliminar una imagen usamos:
docker rmi nombre_de_la_imagen o IMAGE_ID
rmi = remove image
ya que tenemos una imagen podemos crear n cantidad de contenedores en base a ella, para iniciar un contenedor usamos:
docker run nombre_imagen
si usamos ese comando se creara un contenedor y se le sera asignado un nombre al azar, podemos saber su nombre usando el comando :
docker ps
(para ver los contenedores que estan corriendo en nuestro equipo)
o
docker ps -a
(para ver TODOS los contenedores tanto encendidos como apagados )
o en su defecto nosotros podemos nombrarlo usando el parámetro — name
docker run --name micontenedor nombre_imagen
entonces este contenedor se llama micontenedor, ya que tiene nombre o sabemos su nombre podemos detenerlo , reiniciarlo o apagarlo, usando :
docker start micontenedor
docker stop micontenedor
docker restart micontenedor
al momento de crear o arrancar un contenedor se ejecutara en automático el comando que se indico en el dockerfile con CMD, de esta forma si en el dockerfile escribimos:
CDM ls
cuando ejecute :
docker run --name micontenedor nombre_imagen
o
docker start micontenedor
se ejecutara el comando ls.
Si quiero ejecutar el comando bash en lugar del ls, usaremos :
docker run --name micontenedor nombre_imagen bash
pero tenemos que usar el parámetro -it, para que se habilite el búfer de entrada y salida de lo contrario no veremos nada en pantalla ni podremos escribir tampoco, de esta forma el comando queda como:
docker run --name micontenedor -it nombre_imagen bash
de esta forma se ejecutara el bash y no el ls.
La información y los cambios almacenados en un contenedor persisten, una vez creado un contenedor, esté conserva su estado.
Para eliminar un contenedor usamos :
docker rm nombre_contenedor o CONTAINER ID
una imagen se puede eliminar siempre y cuando no este siendo usado por un contenedor aunque existe el force.
Existen muchos comandos mas de docker que son de utilidad tales como montar volumenes (cargar carpetas de nuestro sistema dentro del contenedor) usando
-v “carpetalocal”:”carpeta_del_contenedor”
habilitar puertos
-p puerto_local: puerto_del_contenedor
, etc.
Pero los de docker dijeron “ok, tenemos todo estos comandos pero cuando hay que interconectar contenedores, el numero de comandos a ejecutar se multiplica ya que hay que repetir los mismos pasos para 2 contenedores , 3 contenedores o n contenedores que necesitamos correr” entonces les llegó una idea:
“hay que hacerlo mas fácil!!!”
y crearon docker-compose pero eso será en otro post.
Si has notado algún error en este artículo o sientes que se puedes hacer mejoras, por favor házmelo saber en la sección de comentarios, ¡lo aprecio mucho!
Si ha disfrutado de este artículo y siente que ha aprendido algo valioso, por favor compártalo.
¡Gracias por leer!
Referencias
- Wolf, Gunnar.(octubre de 2016). Contenedores, UN POCO DE HISTORIA.SOFTWARE GURU,52, 44–45.