Mapa de la ruta
Contenido detallado
🐳 Docker básico
Docker es una maleta: colocas la app y todo lo que necesita dentro de un contenedor, y funciona igual en cualquier máquina, sin el «en la mía funciona».
Un contenedor es una caja cerrada que lleva la app y todo lo que necesita para funcionar: código, bibliotecas y configuraciones. Es como una maleta lista que se abre igual en cualquier lugar.
Acaba con el «en mi máquina funciona». Si corre en el contenedor, corre en el servidor, en la laptop de tu colega y en la nube, exactamente igual.
El contenedor no es una máquina virtual: es más liviano y se inicia en segundos. Cada contenedor está aislado de los demás, pero comparte el sistema del servidor.
El paso para descargar e instalar Docker: Docker Desktop en Windows y Mac, o el script oficial / administrador de paquetes en Linux de tu servidor.
Sin Docker instalado, no se ejecuta ningún contenedor. Instalarlo una vez deja listo el motor para el resto de la ruta.
Revisa con docker --version e docker run hello-world. En Linux, agrega tu usuario al grupo docker para no necesitar sudo siempre.
El comando docker run descarga una imagen (si hace falta) y crea un contenedor a partir de ella. Con él pones un servidor web en línea con un comando.
Es el comando que más vas a usar. En segundos tienes una base de datos, un sitio o una herramienta en funcionamiento, sin instalar nada en tu máquina.
-d se ejecuta en segundo plano, -p 8080:80 conecta uno de sus puertos al puerto del contenedor, --name le da un apodo. docker ps lista lo que está en ejecución.
La imagen es el molde congelado (la receta lista); el container es una copia viva que se ejecuta a partir de ese molde. De una imagen puedes crear tantos containers como quieras.
Confundir los dos genera desorden. Entender la diferencia ayuda a saber qué borrar, qué reutilizar y por qué el contenedor desaparece, pero la imagen permanece.
docker images lista plantillas; docker ps -a lista contenedores. La imagen es la clase; el contenedor, el objeto. Las imágenes provienen de Docker Hub.
O Dockerfile y es un archivo de texto con la receta de tu imagen: de qué base partir, qué copiar, qué instalar y qué comando ejecutar al iniciarse.
Es cómo empaquetas TU app, en lugar de limitarte a usar las que ya están listas. Con un Dockerfile, cualquier persona puede crear la misma imagen con un solo comando.
Instrucciones en mayúsculas: FROM (base), COPY, RUN (instala), EXPOSE (puerto), CMD (comando de inicio). Cada línea se convierte en una capa.
O docker build convierte el Dockerfile en una imagen real; el docker push envía esta imagen a un registro (como Docker Hub) para usarla en cualquier servidor.
Es el ciclo completo: desde la receta hasta la app publicada. Con la imagen en el registro, hacer deploy se convierte en solo un docker pull en el servidor.
docker build -t usuario/app:1.0 . genera y nombra (tag). Haz docker login antes de hacer push. La etiqueta latest y es la versión predeterminada.
🎼 Docker Compose
Compose es el director de orquesta: en lugar de iniciar cada contenedor a mano, describes toda la orquesta de servicios en un archivo y lo inicias todo junto con un comando.
Docker Compose es una herramienta para definir y ejecutar varios contenedores juntos. Describes toda la aplicación (app + base de datos + caché) en un solo archivo.
Las apps reales rara vez son un solo contenedor. Sin Compose, iniciar la app + la base de datos se convierte en una tediosa secuencia de comandos largos y frágiles.
Toda la stack está en un docker-compose.yml. docker compose up inicia todo, down se cae. Un archivo versionado = entorno reproducible.
Un archivo en formato YAML que enumera los servicios de tu aplicación. Cada servicio apunta a una imagen (o a una compilación) y sus configuraciones.
Es el corazón de Compose. Entender la estructura básica te permite leer y escribir cualquier stack que encuentres.
YAML usa sangría (espacios, nunca Tab). Empieza por services: y, debajo de él, cada servicio con image o build e ports.
Los servicios son los contenedores; las redes permiten que se comuniquen entre sí por nombre; los volúmenes guardan datos que deben sobrevivir cuando se vuelve a crear el contenedor.
Sin volumen, pierdes la base de datos con cada reinicio. Sin la red correcta, la app no encuentra la base de datos. Estos tres conceptos sostienen cualquier stack.
Los contenedores de la misma stack se encuentran por el nombre del servicio (p. ej., db). Los volúmenes conectan una carpeta persistente. Los datos del contenedor desaparecen; los del volumen permanecen.
El momento de unirlo todo: definir un servicio de app y uno de base de datos en el mismo archivo y levantar la aplicación completa con un solo docker compose up.
Es el escenario más común en la práctica. Cuando subes la app y la base de datos juntas, ya puedes ejecutar una aplicación completa en tu servidor.
docker compose up -d se inicia en segundo plano. La app encuentra la base de datos por el nombre del servicio. Usa depends_on para definir el orden de inicio.
Las herramientas para ver qué está haciendo cada contenedor: logs muestra la salida, ps muestra el estado y exec entra al contenedor.
Cuando algo no se inicia, el registro explica por qué. Si no sabes leer registros, te quedas adivinando; con ellos, lo resuelves en minutos.
docker compose logs -f sigue en tiempo real. docker compose exec app sh abre una terminal dentro del contenedor para investigar.
El flujo para actualizar la aplicación: descargar la nueva imagen, recrear los contenedores y, si algo sale mal, volver (rollback) a la versión anterior.
Toda app evoluciona. Saber actualizarla sin que todo se caiga y volver atrás rápidamente evita ese susto de "rompí producción y no sé cómo deshacerlo".
docker compose pull descarga el nuevo, up -d recrea solo lo que cambió. Fijar la etiqueta de la imagen (y no usar solo latest) hace que el rollback sea sencillo.
⚙️ Systemd
El systemd es el encargado de guardia de Linux: inicia tus servicios al arrancar, vigila si se caen y los reinicia automáticamente. Servicios que nunca se detienen.
El systemd es el sistema que inicia y administra todo lo que se ejecuta en Linux: es el primer programa que se carga al arrancar y el responsable de iniciar los demás servicios.
Es lo que mantiene tu app en línea las 24 horas. Sin systemd, tendrías que reiniciar todo manualmente cada vez que se reiniciara el servidor.
La unidad básica es el "service" (.service). Te comunicas con systemd mediante el comando systemctl. Casi todas las distribuciones modernas de Linux usan systemd.
Un archivo .service que describe tu app para systemd: qué comando ejecutar, en qué carpeta, con qué usuario y qué hacer si se cae.
Es cómo conviertes un script independiente en un servicio de verdad, gestionado por el sistema, que se inicia solo y se trata como algo serio.
Tres secciones: [Unit] (descripción y dependencias), [Service] (ExecStart, usuario) y [Install]. Los archivos quedan en /etc/systemd/system/.
Los comandos del día a día: start inicia, stop se apaga, restart reinicia y enable garantiza que el servicio se inicie al arrancar.
Son los botones de control de tu servicio. Con ellos lo inicias, lo detienes y lo reinicias sin reiniciar todo el servidor.
Diferencia clave: start inicia ahora; enable inicia en cada arranque. Usa systemctl status nome para comprobar si está activo (active/running).
O journalctl y es el centro de logs de systemd. Guarda todo lo que escribió cada servicio, con fecha y hora, para que lo consultes cuando lo necesites.
Cuando falla un servicio, el registro cuenta la historia. Saber filtrar el journal es lo que marca la diferencia entre «no sé qué pasó» y «encontré el error en 30 segundos».
journalctl -u nome filtra por servicio; -f sigue en vivo; -e salta hasta el final. Combínalo con --since para un intervalo.
La forma de decirle a systemd que un servicio depende de otro: por ejemplo, tu app solo debe iniciarse después de que la base de datos esté lista.
Sin el orden correcto, la app se inicia antes que la base de datos y falla al arrancar. Definir las dependencias garantiza que todo se inicie en la secuencia correcta, de forma automática.
En el [Unit]: After= define el orden; Requires= obliga al otro a estar activo; Wants= es una dependencia ligera (recomendada).
La configuración que hace que systemd reinicie automáticamente un servicio que se bloqueó o se cayó, sin que tengas que estar despierto para eso.
Las apps se caen. Con el reinicio automático, el servidor se recupera solo y tu app vuelve a estar en línea en segundos, incluso a las 3 de la mañana.
En el [Service]: Restart=always (o on-failure) e RestartSec=5 (espera antes de volver a intentarlo). Después de editar, ejecuta systemctl daemon-reload.
⏰ Tareas cron
Cron es el despertador del servidor: programas tareas para que se ejecuten solas en horarios fijos, como copias de seguridad todos los días de madrugada o limpiezas semanales.
Cron es un programador de tareas que se ejecuta todo el tiempo en Linux y vigila el reloj. Cuando llega la hora programada, ejecuta el comando que programaste.
Es la forma clásica de automatizar tareas repetitivas: copias de seguridad, informes, limpiezas. Lo configuras una vez y lo hace para siempre, por sí solo.
Cada tarea programada es un «cron job». La lista de jobs vive en una tabla llamada «crontab». Cron se ejecuta en segundo plano y no necesita que nadie haya iniciado sesión.
La línea de un cron job empieza con cinco campos que definen cuándo ejecutarse: minuto, hora, día del mes, mes y día de la semana, seguidos del comando.
Equivocarse en la sintaxis es el error más común. Entender los cinco campos marca la diferencia entre «ejecutarse todos los días a las 3 h» y «ejecutarse cada minuto sin parar».
Orden: min hora dia mes diasemana. O * significa "todo". 0 3 * * * = todos los días a las 3 h. Usa el sitio crontab.guru para comprobarlo.
El comando crontab -e abre, en un editor, tu tabla de tareas programadas. Cada línea que escribes allí se convierte en un job activo al guardar.
Es la puerta de entrada para crear, editar y eliminar tus jobs. Sin esto, no puedes programar nada en el servidor.
crontab -e edita, crontab -l lista. Cada usuario tiene su propia crontab. Usa rutas absolutas en los comandos para evitar sorpresas.
Casos reales de cron jobs: una copia de seguridad de la base de datos todas las madrugadas, una limpieza de archivos temporales cada semana, un script de mantenimiento mensual.
Ver ejemplos listos acelera todo. Con pocos modelos a mano, los adaptas a cualquier rutina que tu servidor necesite.
Copia de seguridad: 0 2 * * * llama a un script de volcado. Limpieza: 0 4 * * 0 (el domingo) elimina los archivos temporales. Apunta siempre a un script, no a un comando enorme.
Las formas de saber si se ejecutó un cron job y qué hizo: redirigir la salida del comando a un archivo de registro y consultar el registro del sistema.
Cron se ejecuta en silencio. Sin registros, nunca sabes si la copia de seguridad se hizo realmente, hasta el día en que la necesitas y descubres que fallaba desde hacía meses.
Agrega >> /var/log/meujob.log 2>&1 al final de la línea para guardar la salida y los errores. En el journal, filtra por journalctl -u cron (o crond).
Los systemd timers son la alternativa moderna a cron: un archivo .timer programa cuando un .service debe ejecutarse, integrado con systemd.
Los timers tienen registros en el journal, saben recuperar ejecuciones perdidas y se integran con los servicios. En servidores modernos, muchas veces son la mejor opción.
Un par: el .service hace la tarea, el .timer di cuándo. OnCalendar= define el horario; systemctl list-timers muestra los próximos disparos.