Este es uno de los capítulos del tutorial Tutorial de Docker. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.
En los capítulos anteriores del tutorial de docker, has realizado un barrido por lo mas básico sobre docker. Que son las imágenes docker, que son los contenedores docker y sobre todo, como poder levantar contenedores docker. La otra pieza, que también has visto es como relacionarte con Docker Hub para poder subir tus propias imágenes. Sin embargo solo has visto, un medio, bastante rudimentario para crear tus propias imágenes docker. Precisamente, esto es lo que vas a abordar en este capítulo del tutorial sobre docker, es decir, como crear tus propias imágenes docker.
Como verás a lo largo del presente capítulo, esto que a priori, te puede sonar como complicado, no lo es. Crear tus propias imágenes docker, no es nada complicado. Y no solo es que no sea complicado, sino que además te ayudará a mejorar tu flujo de trabajo. Te permitirá crear imágenes docker personalizadas que se adapten enteramente a tus necesidades.
Como vengo haciendo en los anteriores capítulos del tutorial, en este también encontrarás un buen número de ejemplos. Si bien, me reservo para el siguiente capítulo del tutorial, en el que te mostraré el proceso completo para crear una imagen con tu propia aplicación. Y no solo esto, también te contaré como puedes hacerlo para generar de forma automática la imagen a partir del Dockerfile.
Crear tus propias imágenes docker
La instrucción fundamental para crear tus propias imágenes docker es docker buid
. El uso de esta instrucción es tan sencillo como,
docker build <opciones> [path | url]
Con esta sencilla instrucción construirás tu propia imagen a partir de un Dockerfile
y un contexto. ¿Que es eso de un contexto?. Un contexto no es mas que un conjunto de archivos que se encuentran en una ruta,path o en una dirección url.
Esa dirección url
, puede ser perfectamente un repositorio git.Pero no solo esto, sino que te puedes referir incluso a una rama y un directorio concreto. Por ejemplo,
docker build https://github.com/atareao/repositorio.git#rama:directorio
También es posible indicar una dirección, url
en la que se encuetra un archivo comprimido en formato tar.gz
.
Las capas
Tienes que pensar en una imagen como una cebolla. Si, lo has leído bien, como una cebolla. Una cebolla, donde cada una de las operaciones que realices para construir la imagen es una capa de la cebolla.
Esto de las capas tiene varias ventajas. Para construir una imagen solo crea las capas que necesita y que no estén creadas, pudiendo compartir capas con otras imágenes. Así, si tu creaste dos imágenes docker que partían de Ubuntu, la primera capa, la capa de Ubuntu, se comparte por las dos imágenes docker.
Pero no solo esto, sino que además si estás construyendo tu nueva imagen por segunda vez, solo se recrearán aquellas capas que hayan sufrido alguna modificación. De esta manera, permanecen inalteradas las que no se han modificado anteriormente.
Dockerfile
Como ya te has podido imaginar, la pieza principal de este pequeño rompecabezas, no es, ni mas ni menos, que el Dockerfile
. Este archivo está compuesto por una serie de comandos que te indicaré a continuación, y que son los responsables de la construcción de la imagen.
ADD
copia un archivo del host al contenedorCMD
el agumento que pasas por defectoENTRYPOINT
el comando que se ejecuta por defecto al arrancar el contenedorENV
permite declarar una variable de entorno en el contenedorEXPOSE
abre un puerto del contenedorFROM
indica la imagen base que utilizarás para construir tu imagen personalizada. Esta opción es obligatoria, y además debe ser la primera instrucción delDockerfile
.MAINTAINER
es una valor opcional que te permite indicar quien es el que se encarga de mantener elDockerfile
ONBUILD
te permite indicar un comando que se ejecutará cuando tu imagen sea utilizada para crear otra imagen.RUN
ejecuta un comando y guarda el resultado como una nueva capa.USER
define el usuario por defecto del contenedorVOLUME
crea un volumen que es compartido por los diferentes contenedores o con el hostWORKDIR
define el directorio de trabajo para el contenedor.
Un ejemplo sencillo. Se trata de construir una imagen docker con Python 3. Vamos paso a paso para que veas como conforme vamos añadiendo capas, se va completando tu nueva imagen.
El primer paso
Como primer paso, tal y como te he indicado anteriormente con las instrucciones, se trata de partir de una imagen previa utilizando la instrucción FROM
. En este caso, y como no podía ser de otra forma, voy a partir de la última versión de Ubuntu. Así, el contenido de tu Dockerfile
, tendrá un aspecto como el que puedes ver a continuación,
FROM ubuntu:latest
Para construir tu imagen, tendrás que ejecutar la siguiente instrucción,
docker build -t atareao/ubuntu-python3:latest .
Si la ejecutas dos veces, observarás que en la segunda no se hace nada. Por otro lado, lanza un contenedor y entra en él, para ver que te encuentras. Para ello, ejecuta la siguiente instrucción,
docker run -it --name paso1 atareao/ubuntu-python3 bash
Si ahora dentro del contenedor intentas iniciar Python verás que lamentablemente no lo encuentras.
Añadiendo Python a tu imagen
Así, como siguiente paso, añadiremos las instrucciones necesarias para contar con Python en nuestro contenedor. En concreto vamos a instalar Python 3, por aquello de que la versión anterior pierde su soporte en el 2020.
Así ahora el contenido del Dockerfile
tendrá el siguiente aspecto,
FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3
Como ves lo primero es actualizar la lista de paquetes disponibles, y el siguiente paso es instalar Python 3.
Es posible que te llame la atención el hecho de que utilice apt-get
en lugar de apt
, con lo que yo he dado la paliza con este tema. La razón es sencilla, y es que para los scripts la herramienta que tienes que utilizar es apt-get
.
Por supuesto tienes que utilizar la opción -y
para no tener que responder a nada, porque la construcción no es interactiva.
Ejecutar un archivo
Ahora quieres ejecutar un archivo Python aprovechando que ya tienes tu imagen con Python. Para esto, crea un archivo llamado hola.py
, con el siguiente contendio,
#!/usr/bin/env python3
print('Hola mundo')
Puedes pensar que la solución está en ejecutar,
docker run atareao/ubuntu-python hola.py
Sin embargo esto te arrojará un error, python3: can't open file 'hola.py': [Errno 2] No such file or directory
. Esto es así, porque este archivo no existe en el contenedor.
Así que tienes que modificar tu Dockerfile
e incorporar ese archivo a tu imagen. De esta manera, tu Dockerfile
tendrá el siguiente aspecto,
FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3
ENTRYPOINT ["python3"]
COPY hola.py .
Ahora si levantas tu docker se comportará como esperas. Si, por otro lado, entras en el contenedor, verás que allí se encuentra el archivo hola.py
.
Ejecutar el archivo por defecto
Por último, quedaría ejecutar el archivo hola.py
por defecto al correr tu contenedor. En este caso, debes modificar de nuevo el contenedor, de forma que quedará con un aspecto como el que puedes ver a continuación,
FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3
WORKDIR /home
COPY hola.py /home
ENTRYPOINT ["python3"]
CMD ["hola.py"]
En este caso, encontrarás el archivo hola.py
en el directorio /home
, y cuando levantes el contenedor directamente obtendrás el Hola mundo
tan esperado,
docker run atareao/ubuntu-python
Conclusión
Con este cuarto capítulo, ya tienes unos primeros pasos para crear tus propias imágenes docker. En el siguiente capítulo te mostraré como hacer una aplicación de principio a fin. Y no solo esto, sino también como aprovechar las facilidades que Docker Hub pone a tu disposición.
Imagen de portada de Randy Fath en Unsplash