Uso de Docker para desarrolladores (Parte 1 – Conceptos y primeros pasos)

Home  >>  DevOps  >>  Uso de Docker para desarrolladores (Parte 1 – Conceptos y primeros pasos)

Uso de Docker para desarrolladores (Parte 1 – Conceptos y primeros pasos)

On diciembre 6, 2017, Posted by , In DevOps,Docker,Linux,Programación,Sistemas,Vagrant, With No Comments

docker_vertical_large

En este articulo veremos una pequeña comparativa de conceptos ente Docker y Vagrant y aprenderemos a:

  • Arrancar una imagen de Docker
  • Compilar nuestra imagen de Docker personalizada
  • Subirla a DockerHub y compartirla con el equipo

Empecemos…

Como comenté en el artículo de Uso de vagrant para desarrolladores, es importante tener una capa de abstracción en nuestro ordenador de desarrollo que nos permita tener un fiel reflejo de lo que nuestro código se va a encontrar en nuestro servidor de producción.

Desde hace unos años que Docker ha aparecido como alternativa en sistemas Linux y actualmente se puede usar en cualquier plataforma.

Si bien el resultado desde el punto de vista de “objetivo principal” puede llegar a confundirnos en la elección de uno u otro. En realidad son productos bastante diferenciados como para que debamos hacer una reflexión sobre los detalles de cada uno.

Diferenciando Vagrant de Docker

Vagrant:

Vagrant es un gestor de máquinas virtuales. Es capaz de conectarse a varios gestores de máquinas virtuales y usando el Vagrantfile aprovisionarnos una máquina según nuestras características. Básicamente consta de un Provider (que nos da la máquina virtual) y un Provisioner (que ejecuta instrucciones que definan su singularidad a nivel de sistema operativo y paquetes que debe tener esa máquina virtual en concreto.

vagrant_virualization

Docker:

Docker no emula un sistema operativo completo. Su objetivo es poner en marcha las librerías y ficheros necesarios para darnos un entorno virtual concreto. En este caso se basa en el sistema de Linux Containers y el sistema de archivos por capas (auFS)

docker_virtualization

Lo que hace Docker en este caso es ir un paso más allá en nuestras posibilidades de versatilidad de pasar de un entorno de desarrollo a uno de producción. Ya que el mismo contenedor que hemos creado para desarrollar nuestra aplicación lo podemos desplegar directamente en nuestro entorno de producción…. (si… tal cual suena)

Una tabla comparativa siempre ayuda…

En la tabla siguiente hay una pequeña comparativa de las características que los definen a cada uno. La más destacable después de la antes mencionada es que consume lo justo para ejecutar las librerías que necesita el contenedor. No reserva RAM ni encapsula recursos dedicados, y su particular forma de enfocar el entorno virtual hace que sea muy rápido levantar dichos contenedores.

 

Característica Docker Vagrant
Tipo de virtualización Contenedores Máquina virtual
Tipo de aislamiento Bajo Muy alto
Tiempo de creación < 5 minutos > 5 minutos
Tamaño de despliegue 14Mb las versiones “alpine”, mínimo 100mb las normales Mínimo 1gb
Tiempo de arranque Segundos Minutos
Impacto del sistema Muy bajo Alto
Garantiza recursos No Si
Cuantos se pueden albergar a la vez >50 <10
Principal ventaja Rápido y ligero Emula un SO completo. Bien adaptado a entorno de empresa.
Principal desventaja Sólo emula sistemas Linux Las típicas de emular un SO completo. Muy pesado.

 

Viendo esta tabla parecería que todo son ventajas… Pero ese no es el objetivo. Los dos cumplen una función concreta. Vagrant ofrece un nivel de encapsulado que a veces es necesario. Y Docker es bueno levantando servicios aislados de nuestro sistema operativo anfitrión.

Otra cuestión importante a tener en cuenta es que en Docker los cambios de datos son efímeros. No guarda los cambios producidos después de apagar la máquina. Dichos cambios se pierden. Con lo que hay que jugar con el concepto de volúmenes para persistir ciertas cosas fuera del contenedor (por ejemplo, los ficheros de una base de datos).

En definitiva y resumiendo.

  • Docker para entornos Linux y que la velocidad sea clave.
  • Vagrant para entornos con sistemas operativos heterogéneos y que necesitan un nivel de aislamiento más elevado (a nivel de IP por ejemplo).

Ahora si… Vamos “al turrón” del asunto.

Diferenciados los dos productos ahora ya podemos seguir con el tema principal.

1- Nos creamos una cuenta en DockerHub

El objetivo es poder luego subir nuestros propios contenedores a nuestro repositorio privado y así compartirlo con el equipo de desarrollo.

 

2- Nos instalamos Docker siguiendo las instrucciones según sea nuestro sistema operativo.

Aquí ya cada uno deberá echar de sus habilidades leyendo el documento y actuando en consecuencia para conseguir instalarlo. La verdad es que está muy bien documentado y no hay complejidad alguna (por lo menos en Debian).

 

3- Creamos un DockerFile que defina nuestras necesidades

En este caso partimos de un Debian 9.2 y su objetivo es darnos servicio de http por el puerto 80 y 443.

# Imagen base de Docker Hub
FROM debian:9.2

# Etiqueta del responsable de la imagen nueva
LABEL maintainer="faparicio@fernandoaparicio.net"

# Acciones a realizar en la nueva imagen
RUN apt-get update &amp;&amp; apt-get install -y \
wget \
apache2 \
php \
mc

#Puertos que dejaremos accesibles a nuestra imagen
EXPOSE 80 443

# Arrancamos apache
CMD apachectl -D FOREGROUND

Una vez definido el nuevo contenedor,  lo creamos ejecutando el siguiente comando en el directorio donde está el fichero Dockerfile

docker build -t debian9-webserver:1.0 .

Después de unos momentos, ya tendremos el contenedor listo para usar.

# docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian9-webserver   1.0                 4bfd6e266e75        9 seconds ago       270MB
debian              9.2                 6d83de432e98        2 weeks ago         100MB

Y podemos estrenar el nuevo contenedor con apache instalado y levantado.

# docker run -p 80:80 -d debian9-webserver:1.0 
29ec549538567374f115e197503d151e3160f667cfdd91b41996b8410b948b8e

# docker ps
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                         NAMES
29ec54953856        debian9-webserver:1.0   "/bin/sh -c 'apach..."   3 seconds ago       Up 3 seconds        0.0.0.0:80-&gt;80/tcp, 443/tcp   wonderful_lumiere

Y pararlo usando el ID que hemos visto en el listado de contenedores activos de docker.

# docker stop 29ec54953856
29ec54953856

 

4- ¿Ya tenemos contenedor… y ahora cómo lo compartimos en el equipo?

En ese caso usaremos el repositorio privado que nos ofrece de forma gratuita DockerHub.

Etiquetamos nuestra imagen para usarla en DockerHub.

# docker tag debian9-webserver:1.0 faparicior/devel:debian9-webserver
# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
faparicior/devel               debian9-webserver   3dce53a1d5dd        17 minutes ago      270MB
debian9-webserver              1.0                 3dce53a1d5dd        17 minutes ago      270MB
debian                         9.2                 6d83de432e98        2 weeks ago         100MB

En este caso hemos creado una referencia a debian9-webserver:1.0. No es una imagen real. El tag nos sirve para identificar el user y repositorio de destino de DockerHub.

Y ya podemos publicarlo en nuestro repositorio.

# docker push faparicior/devel:debian9-webserver
The push refers to a repository [docker.io/faparicior/devel]
f38f274c0e8c: Pushed 
a75caa09eb1f: Mounted from library/debian 
debian9-webserver: digest: sha256:02b4e5fa0a041abaef9e66109cce172ca13c80754e879c03a933bcc8ea24200b size: 741

Y en las máquinas de tu equipo sólo falta bajarse la imagen del contenedor y levantarla.

# docker pull faparicior/devel:debian9-webserver
debian9-webserver: Pulling from faparicior/devel
3e17c6eae66c: Pull complete 
b0036f982d56: Pull complete 
Digest: sha256:02b4e5fa0a041abaef9e66109cce172ca13c80754e879c03a933bcc8ea24200b
Status: Downloaded newer image for faparicior/devel:debian9-webserver

# docker run -p 80:80 -d faparicior/devel:debian9-webserver 
cb66548d46c80d485017cab9b8eb1984cc07b02b6cb1209b37284bef72c344e6
# docker ps
CONTAINER ID        IMAGE                                COMMAND                  CREATED             STATUS              PORTS               NAMES
cb66548d46c8        faparicior/devel:debian9-webserver   "/bin/sh -c 'apach..."   10 seconds ago      Up 9 seconds        80/tcp, 443/tcp     zealous_booth

 

5- Fantástico!… pero…. ¿cómo pongo mi código dentro del webserver?

El tema se resuelve de tres maneras posibles. Pero para nuestro caso práctico, como developers, usaremos el primer caso, ya que nos ofrece la posibilidad de cambiar el código desde nuestra máquina y que nuestro contenedor lo ejecute.

types-of-mounts-bind

  • Bind mount: Depende de la infraestructura de carpetas del host. Usado preferiblemente para desarrollo.
  • Volume: Totalmente gestionado por Docker. Sólo los contenedores pueden acceder a la información contenida. Usado preferiblemente en el entorno final de producción o test.
  • Tmpfs mount: Usado en el caso de querer un storage no persistente y veloz, ya que en estos casos usa la memoria RAM del host.

Para ver cómo funciona, nos podemos crear en nuestro ordenador una carpeta llamada html, con un fichero index.html. Usaremos esa carpeta como punto de montaje de nuestro host al contenedor. La única limitación que tiene es que necesita un path absoluto. No acepta paths relativos. Pero lo podemos resolver con la instrucción pwd de linux a la hora de generar el path en el script.

 

# docker run -p 80:80 -d --mount type=bind,source="$(pwd)"/html,target=/var/www/html faparicior/devel:debian9-webserver

Ahora puede que te lo estés preguntando… ¿Y la base de datos?

En ese caso, iremos al siguiente Post para verlo. Pero te adelanto que será juntar dos contenedores. Uno de webserver que ya tenemos y otro que nos de servicio de base de datos.

 

Cheatsheet de los comandos usandos en este post:

Comando Utilidad
docker build -t debian9-webserver:1.0 . Compila una imagen nueva con el tag debian9-webserver:1.0
docker run -p 80:80 -d debian9-webserver:1.0 Inicia una imagen del tipo debian9-webserver:1.0 y expone el puerto 80
docker ps Lista los procesos arrancados por docker
docker stop 29ec54953856 Para un proceso de docker usando su id
docker tag debian9-webserver:1.0 faparicior/devel:debian9-webserver Crea un tag a partir de una imagen existente
docker images Lista las imágenes que tiene docker en local
docker login Se logue al repositorio de docker (en docker hub por ejemplo)
docker push faparicior/devel:debian9-webserver Publica una imagen de docker (en docker hub por ejemplo)
docker pull faparicior/devel:debian9-webserver Baja una imagen del repositorio de docker

 

Links y recursos

Dockerfile reference

Docker y volúmenes de datos

 

Fernando Aparicio
Full Stack Developer. Entusiasta del Open Source, métodos de organización y colaboración ágiles.

Actualmente estoy en busca de otras formas de mejorar en mi trabajo. Aprovechar el talento innato y la colaboración en equipo.

Lean, Kanban, Scrum ... Descubrir las pequeñas cosas que dan calidad al proceso a través de las personas usando PNL. Renovar los esquemas para motivar la colaboración.

Nuevos tiempos, nuevas soluciones.
Comments are closed.