REGRESAR

Metadatos

ACTUALIZADO EL 05/11/2024

Introducción a Makefile

Como desarrollador de software a veces me encuentro en la situación de ejecutar los mismos comandos una y otra vez, con algún parámetro personalizado o ligeramente diferente y a mí personalmente me cuesta recordarlos. Por suerte tenemos los ficheros Makefile, que nos permiten automatizar el proceso de construcción y gestión de nuestros proyectos además de organizar y simplificar la ejecución de dichos comandos mediante unos pasos o steps que nosotros definamos.


Introducción

Este curso se ha diseñado como una guía práctica de introducción a ficheros Makefile donde se podrá...

  • Comprender los conceptos básicos de los ficheros Makefile.
  • Crear ficheros Makefile.

¿A quién va dirigido?

Esta formación está orientada principalmente a desarrolladores/as de software que deseen adentrarse en la cultura DevOps/GitOps y quieran ser más ágiles en su operativa diaria.

Metodología del curso

La metodología de este curso se basa en:

  • Teoría y conceptos, con explicaciones claras y concisas de los puntos clave.
  • Demostraciones, con ejemplos reales y cotidianos.

Herramientas y requisitos

Para aprovechar al máximo este curso se necesita:

  • Un equipo con acceso a Internet.
  • Privilegios de administrador para instalar software.
  • Conocimientos básicos de desarrollo web.


¿Qué es un fichero Makefile?

Un fichero Makefile es un archivo de texto que permite agrupar comandos en pasos o targets y ejecutarlos mediante un nombre fácil de recordar.

Requisitos para ejecutar ficheros Makefile

Para procesar los ficheros Makefile se utiliza la herramienta make, que permite validar el Makefile y ejecutar los pasos en el órden que hayamos definido.

Los ficheros Makefile tienen una identación basada en tabuladores.

Estructura de un fichero Makefile

Un Makefile está compuesto por:

Reglas
Definen qué comandos ejecutar así como las dependencias de los mismos.
Variables
Guardan valores reutilizables como nombres de archivos o flags de compilación.
Comentarios
Empiezan con # y sirven para documentar el archivo.

Ejemplo de fichero Makefile

Primero debemos crear un fichero Makefile

vi Makefile

Y añadimos el siguiente contenido:

.DEFAULT_GOAL := main
CLEAR = clear
HOST_USER_ID := $(shell id --user)
# Esto es un comentario
.PHONY: limpiar-terminal
limpiar-terminal:
@$(CLEAR)
# Esto es un comentario
.PHONY: cual-es-mi-usuario
cual-es-mi-usuario:
@echo "Este es tu ID de usuario"
@echo $(HOST_USER_ID)
# Este es el comando principal
.PHONY: main
main: limpiar-terminal cual-es-mi-usuario
@echo "That's all falks!"

Una vez guardado, ejecutamos el comando make de la siguiente manera:

Sin especificar target Especificando el target
make
Este es tu ID de usuario
1000
That's all falks!
make main
Este es tu ID de usuario
1000
That's all falks!
Ambos comandos son equivalentes ya que, tal y como hemos definido en la línea 1 del Makefile, si no se especifica ningún target se usará el main por defecto.
En la línea 17 podemos ver que el target se define como main: limpiar-terminal cual-es-mi-usuario. Esto permite que, cada vez que ejecutemos el target main, primero se ejecute limpiar-terminal, luego se ejecute cual-es-mi-usuario y por último los comandos definidos en el propio target. Que, en este ejemplo, es un @echo "That's all falks!"

Caso de uso real

Hasta aquí puede parecer que los ficheros Makefile pueden no ser del todo útiles, pero veamos un caso de uso real.

Dockerizando una aplicación

Cuando trabajamos con aplicaciones dockerizadas (si no sabes de lo que hablo, aquí tienes una Introducción a Docker) tenemos que ejecutar prácticamente los mismos comandos una y otra vez pero hay algunos que son comunes a prácticamente todos los proyectos dockerizados:

Construir la imágen
Cuando trabajamos con imágenes Docker personalizadas debemos construir las imágenes antes de poder usarlas.
Levantar la infraestructura
Una vez construídas las imágenes, ya podemos levantar la infraestructura de nuestra aplicación.
Reiniciar algún contenedor
A veces es necesario reiniciar uno o varios contenedores para, por ejemplo, comprobar la estabilidad de nuestra infraestructura.
Tumbar la infraestructura
Cuando ya no necesitemos de dicha infraestructura la paramos y apagamos para que no siga consumiendo recursos innecesariamente.
Acceder a un contenedor via shell
En fase de depuración es bastante frecuente la necesidad de acceder mediante una terminal shell a un contenedor y navegar por su sistema de archivos...
Ver los logs
O bien, ver qué trazas y logs está volcando ese contenedor.

Comandos que siempre se necesitan

Estos son algunos pasos que siempre se necesitan cuando dockerizamos una aplicación por lo que, en vez de memorizar todos los comandos y sus opciones, uso un fichero Makefile que me permita automatizar estos comandos mediante steps sencillos, como por ejemplo:

.DEFAULT_GOAL := help
HOST_USER_ID := $(shell id --user)
HOST_USER_NAME := $(shell id --user --name)
HOST_GROUP_ID := $(shell id --group)
HOST_GROUP_NAME := $(shell id --group --name)
DOCKER_BUILD_ARGUMENTS = --build-arg="HOST_USER_ID=$(HOST_USER_ID)" --build-arg="HOST_USER_NAME=$(HOST_USER_NAME)" --build-arg="HOST_GROUP_ID=$(HOST_GROUP_ID)" --build-arg="HOST_GROUP_NAME=$(HOST_GROUP_NAME)"
# DOCKER RELATED
.PHONY: build
build:
@docker compose build $(DOCKER_BUILD_ARGUMENTS)
.PHONY: up
up:
@docker compose up --remove-orphans --detach
.PHONY: down
down:
@docker compose down --remove-orphans
.PHONY: restart
restart:
@docker compose restart
.PHONY: logs
logs:
@docker compose logs -f
.PHONY: shell
shell:
@docker compose app sh

De este modo para interactuar con la infraestructura de mis proyectos me basta con ejecutar los siguientes comandos:

Equivalencias usando ficheros Makefile
Step Comando
make build docker compose build --build-arg=...
make up docker compose up --remove-orphans --detatch
make down docker compose down --remove-orphans
make logs docker compose logs
... ...

Plantilla de ficheros Makefile

Puedes descargar una plantilla para ficheros Makefile que puedes personalizar a tu gusto 😁

Comandos diponibles

make
╔════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║                                                                                                        ║
║                                        .: AVAILABLE COMMANDS :.                                        ║
║                                                                                                        ║
╚════════════════════════════════════════════════════════════════════════════════════════════════════════╝
· SERVICE(s) ... app
· USER ......... (1000) alcidesramos
· GROUP ........ (1000) alcidesramos

· build                               Docker: builds the service
· up                                  Docker: starts the service
· restart                             Docker: restarts the service
· down                                Docker: stops the service
· logs                                Docker: exposes the service logs
· shell                               Docker: establish a shell session into main container
· health                              Docker: inspect the health for specific service
· init                                Application: initializes the application

Para saber más...

Puedes profundizar en la creación y personalización de ficheros Makefile en Learn Makefiles with the tastiest examples, un gran recurso lleno de ejemplos y casuísticas.

That's all falks!

También te puede interesar...

¿Te has quedado con ganas de más? Relacionado con este curso tienes el de Introduccion a Docker que seguro te resultará igual de interesante.