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.
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:
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:
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!