Learning path map
Detailed Content
🐳 Docker Basics
Docker is a suitcase: you put the app and everything it needs inside a container, and it runs the same on any machine, without the "it works on my machine" problem.
A container is a closed box that carries the app and everything it needs to run: code, libraries, and settings. It's like a packed suitcase that opens the same way anywhere.
It puts an end to “it works on my machine.” If it runs in the container, it runs on the server, your colleague’s laptop, and in the cloud, exactly the same way.
A container is not a virtual machine: it's lighter and starts in seconds. Each container is isolated from the others, but shares the server's system.
The step of downloading and installing Docker: Docker Desktop on Windows and Mac, or the official script / package manager on Linux on your server.
Without Docker installed, no container can run. Installing it once gets the engine ready for the rest of the learning path.
Check with docker --version e docker run hello-world. On Linux, add your user to the group docker to avoid needing sudo always.
The command docker run downloads an image (if needed) and starts a container from it. With it, you can bring a web server online with one command.
It’s the command you’ll use most. In seconds, you can have a database, website, or tool running without installing anything on your machine.
-d runs in the background, -p 8080:80 maps one of your ports to the container's port, --name give it a nickname. docker ps lists what's running.
The image is the frozen template (the finished recipe); the container is a live copy running from that template. You can create as many containers as you want from one image.
Confusing the two creates a mess. Understanding the difference helps you know what to delete, what to reuse, and why the container disappears while the image remains.
docker images lists templates; docker ps -a lists containers. Image = class, container = object. Images come from Docker Hub.
O Dockerfile is a text file with the recipe for your image: which base to start from, what to copy, what to install, and which command to run when it starts.
It’s how you package YOUR app instead of just using ready-made ones. With a Dockerfile, anyone can build the same image with a single command.
Instructions in uppercase: FROM (database), COPY, RUN (installs), EXPOSE (port), CMD (startup command). Each line becomes a layer.
O docker build turns the Dockerfile into an actual image; the docker push push this image to a registry (such as Docker Hub) to use it on any server.
It’s the full cycle: from the recipe to the published app. With the image in the registry, deploying becomes just a docker pull on the server.
docker build -t usuario/app:1.0 . generates and names (tag). Do docker login before pushing. The tag latest and the default version.
🎼 Docker Compose
Compose is the conductor: instead of starting each container by hand, you describe the whole service orchestra in one file and start everything together with one command.
Docker Compose is a tool for defining and running multiple containers together. You describe the entire application (app + database + cache) in a single file.
Real apps rarely consist of a single container. Without Compose, bringing up an app + database becomes a tedious sequence of long, fragile commands.
The entire stack lives in a docker-compose.yml. docker compose up starts everything, down brings it down. One versioned file = reproducible environment.
A YAML file that lists your application's services. Each service points to an image (or a build) and its settings.
It’s the heart of Compose. Understanding the basic structure lets you read and write any stack you come across.
YAML uses indentation (spaces, never Tab). Start with services: and under it, each service with image or build e ports.
Services are the containers; networks let them communicate with each other by name; volumes store data that needs to survive when the container is recreated.
Without a volume, you lose the database with every restart. Without the right network, the app can’t find the database. These three concepts underpin any stack.
Containers in the same stack find each other by service name (e.g., db). Volumes map to a persistent folder. Data in the container disappears; data in the volume stays.
The moment to put it all together: define an app service and a database service in the same file, then start the full application with a single docker compose up.
It’s the most common real-world scenario. When you bring up an app and database together, you can already run a complete application on your server.
docker compose up -d runs in the background. The app finds the database by the service name. Use depends_on to define the startup order.
The tools for seeing what each container is doing: logs shows the output, ps shows the status and exec goes inside the container.
When something won’t start, the log explains why. Without knowing how to read logs, you’re left guessing; with them, you can fix it in minutes.
docker compose logs -f tracks it in real time. docker compose exec app sh opens a terminal inside the container to investigate.
The application update workflow: download the new image, recreate the containers, and, if something goes wrong, roll back to the previous version.
Every app evolves. Knowing how to update it without taking everything down and how to roll back quickly prevents that "I broke production and don’t know how to undo it" panic.
docker compose pull downloads the new one, up -d recreates only what changed. Pin the image tag (and don’t use just latest) makes rollback easy.
⚙️ Systemd
systemd is Linux’s on-call manager: it starts your services at boot, watches for them to go down, and restarts them automatically. Services that never stop.
systemd is the system that starts and manages everything that runs on Linux: it’s the first program to start at boot and is responsible for starting the other services.
It’s what keeps your app running 24/7. Without systemd, you’d have to restart everything manually every time the server restarted.
The basic unit is the "service" (.service). You interact with systemd using the command systemctl. Almost every modern Linux system uses systemd.
A file .service that describes your app to systemd: which command to run, in which directory, as which user, and what to do if it crashes.
It’s how you turn a standalone script into a real service managed by the system, one that starts on its own and is treated as a serious component.
Three sections: [Unit] (description and dependencies), [Service] (ExecStart, user) and [Install]. The files are in /etc/systemd/system/.
The everyday commands: start starts, stop shuts down, restart restarts and enable ensures the service starts at boot.
They're the control buttons for your service. Use them to start, stop, and restart it without restarting the entire server.
Key difference: start starts now; enable starts on every boot. Use systemctl status nome to check whether it's active (active/running).
O journalctl and the systemd log center. It stores everything each service wrote, with the date and time, for you to check whenever you need.
When a service fails, the log tells the story. Knowing how to filter the journal is what separates “I don’t know what happened” from “I found the error in 30 seconds.”
journalctl -u nome filter by service; -f tracks it live; -e skips to the end. Combine with --since for an interval.
The way to tell systemd that one service depends on another: for example, your app should only start after the database is ready.
Without the right order, the app starts before the database and fails on boot. Defining dependencies ensures everything starts in the right sequence, automatically.
Node [Unit]: After= sets the order; Requires= requires the other one to be active; Wants= is a soft dependency (recommended).
The configuration that makes systemd automatically restart a service that has stalled or crashed, without you needing to be awake.
Apps crash. With automatic restart, the server heals itself and your app is back online in seconds, even at 3 a.m.
Node [Service]: Restart=always (or on-failure) e RestartSec=5 (wait before trying again). After editing, run systemctl daemon-reload.
⏰ Cron Jobs
Cron is the server’s alarm clock: you schedule tasks to run automatically at set times, such as daily overnight backups or weekly cleanup jobs.
Cron is a scheduler that runs on Linux all the time, watching the clock. When the scheduled time arrives, it runs the command you scheduled.
It’s the classic way to automate repetitive tasks: backups, reports, cleanup. You set it up once, and it runs on its own forever.
Each scheduled task is a "cron job." The list of jobs lives in a table called "crontab." Cron runs in the background and doesn't require anyone to be logged in.
A cron job line starts with five fields that define when to run: minute, hour, day of the month, month, and day of the week, followed by the command.
Getting the syntax wrong is the most common mistake. Understanding the five fields makes the difference between "running every day at 3 a.m." and "running every minute nonstop."
Order: min hora dia mes diasemana. O * means “all.” 0 3 * * * = every day at 3 a.m. Use crontab.guru to check.
The command crontab -e opens your schedule table in an editor. Each line you write there becomes an active job when you save.
It’s your gateway to creating, editing, and removing your jobs. Without it, you can’t actually schedule anything on the server.
crontab -e edits, crontab -l lists. Each user has their own crontab. Use absolute paths in commands to avoid surprises.
Real-world cron job examples: a database backup every night, a temporary file cleanup every week, a maintenance script every month.
Seeing ready-made examples speeds everything up. With a few templates on hand, you can adapt them to any routine your server needs.
Backup: 0 2 * * * calls a dump script. Cleanup: 0 4 * * 0 (Sunday) deletes temporary files. Always point to a script, not one giant command.
Ways to tell whether a cron job ran and what it did: redirect the command’s output to a log file and check the system log.
Cron runs silently. Without logs, you never know whether the backup actually ran until the day you need it and discover it’s been failing for months.
Add >> /var/log/meujob.log 2>&1 at the end of the line to save output and errors. In the journal, filter by journalctl -u cron (or crond).
systemd timers are the modern alternative to cron: a file .timer schedules when a .service should run, integrated with systemd.
Timers have logs in the journal, can recover missed executions, and integrate with services. On modern servers, they’re often the better choice.
A pair: the .service performs the task, the .timer says when. OnCalendar= sets the schedule; systemctl list-timers shows the next scheduled runs.