← All chapters

Chapter 3

Chapter 3: I'm Tired of Typing This

Max discovers the power of shell scripts and Docker Compose

Two weeks passed. The server was running. Friends were playing. Jake rebuilt his castle (with a bigger moat this time). Life was good.

Then Max's computer needed updates. A reboot. The server stopped.

No problem—Max knew the drill. He opened his terminal, navigated to his folder, and started typing:

docker run -d --name minecraft -p 19132:19132/udp -e EULA=TRUE -v minecraft-data:/data --restart unless-stopped itzg/minecraft-bedrock-server

He got it wrong the first time. Typo in the port number. Had to stop the container, remove it, try again.

Max

I've typed this command like fifty times now. And I mess it up half the time because it's SO LONG.

There has to be a better way.

"There is," I said. "Several, actually. Let me show you the first one."

Your First Shell Script

"What if," I said, "instead of typing that command every time, you wrote it down once, and then just told the computer 'run that thing I wrote down'?"

Max stared at me. "That's... possible?"

"That's literally what scripts are. A text file with commands in it. The computer runs them in order. It's not magic—it's just automation."

I opened a new file.

start-minecraft.sh(bash)
🧐
Max

What's that first line? The hashtag-exclamation thing?

"That's called a 'shebang'—hash-bang, shebang. It tells the system which program should run this script. #!/bin/bash means 'use bash to run these commands.'"

"And the backslashes?"

"Those just let us break a long command across multiple lines. Makes it readable. The computer sees it as one long line."

I saved the file and showed Max the next step.

$Make it executable

"By default, text files can't be 'run' as programs. The chmod +x command adds execute permission—it tells the system 'this file is meant to be run, not just read.'"

$Run your script

Max ran it. The familiar output appeared—container ID, no errors.

"That's it? I just... saved myself typing all that every time?"

😮
Max

Wait. So every time I restart my computer, I just type ./start-minecraft.sh and it does the whole thing?

I basically automated my life!

💡 CONCEPT

Scripts Are Time Machines

Every shell script is a message to your future self: "Hey, I already figured this out. Just run me."

Key concepts:

  • #!/bin/bash — The "shebang" tells the system what program runs this script
  • chmod +x — Makes a file executable
  • ./ — Means "run this file from the current directory"

If you type it more than twice, make it a script.

Adding Some Smarts

"There's a problem, though," I said. "What happens if the container already exists? Like if you stopped it but didn't remove it?"

Max tried it. The script failed: "container name 'minecraft' is already in use."

"We need to make the script smarter. It should check if the container exists first."

start-minecraft.sh(bash)
😕
Max

Okay, I recognize if from math class, but what's all that other stuff?

"Let's break it down," I said.

"docker ps -a --format '{{.Names}}' lists all container names. The -a includes stopped containers. The --format part tells Docker to only show names, not the full table."

"The | is a pipe—it sends the output of one command into another. So we're sending the list of names to grep."

"grep -q searches for a pattern. The -q means 'quiet'—don't print anything, just tell me if you found it or not. The ^minecraft$ means 'exactly minecraft'—the ^ means start, the $ means end."

"If grep finds it, the if block runs docker start. If not, the else block creates a new container."

Max nodded slowly. "So the script thinks for itself now?"

"A little bit. It makes decisions based on what it finds. That's the power of conditionals."

💡Script Building Blocks

Scripts get smarter with these tools:

  • if/else — Make decisions
  • pipes (|) — Chain commands together
  • grep — Search for patterns
  • variables — Store values for later

You don't need to memorize these. You look them up when you need them. Everyone does.

The Better Way: Docker Compose

"Scripts are great," I said. "But Docker has something even better for this specific problem."

"Better than scripts?"

"Different. Scripts are general-purpose—you can do anything with them. But for defining how containers should run, there's a tool built specifically for that. It's called Docker Compose."

I created a new file.

docker-compose.yml(yaml)
🧐
Max

That looks... different. What language is that?

"YAML. It's a way to write configuration that humans can actually read. See how it lines up? The indentation matters—it shows what belongs to what."

"Look at how it maps to the command you've been typing. image: is the image name. ports: is the -p flag. environment: is -e. It's all the same information, just organized differently."

💡 CONCEPT

Docker Compose = Recipe Cards

Docker Compose is like a recipe card for your containers:

  • Written in YAML (human-readable configuration)
  • Defines everything about how to run your containers
  • One file replaces long commands

Instead of memorizing flags, you write them down once and forget them.

$Start with Docker Compose

Max ran it. Docker read the YAML file, created the container exactly as specified, and started it.

"Four words," Max said. "Instead of that whole long command."

$Stop with Docker Compose
Max

That's so much cleaner. And I can actually read what it's doing without decoding a bunch of flags.

"That's the point. The compose file is documentation. Six months from now, when you've forgotten all the details, you can open this file and see exactly how your server is configured."

"It's also version-controllable—but we'll get to that next chapter."

Adding More Services

"Here's where Compose really shines," I said. "What if you wanted to run multiple things? A Minecraft server plus some kind of monitor, or a backup service, or a web dashboard?"

"Can you do that?"

"With Compose, you just add another service to the file."

docker-compose.yml(yaml)
🧐
Max

What does depends_on do?

"It tells Docker: 'Don't start the watchdog until minecraft is running.' Order matters sometimes. If the watchdog tried to check the server before it existed, it might fail."

"When you run docker compose up, both services start. When you run docker compose down, both stop. One command, multiple containers, all orchestrated together."

ℹ️Orchestration

Running multiple containers that work together is called "orchestration." Docker Compose is a simple orchestrator—it handles starting, stopping, and connecting containers.

For bigger deployments, there's Kubernetes. But that's way down the road. Compose is plenty for what we're doing.

Useful Compose Commands

"Here's your new toolkit," I said.

$See running services
$View logs from all services
$Restart just one service
$Pull new versions of images
$Rebuild and restart everything

Max practiced the commands, watching containers start and stop, logs scroll by.

"This is way better than typing that giant command every time."

"It gets even better," I said. "Right now, your docker-compose.yml exists only on your computer. What if you accidentally delete it? What if you make a change that breaks everything and want to undo it?"

🤔
Max

I'd have to remember what it was before? Or... start over?

"Neither. There's a system that tracks every change you make to a file. You can go back in time, see what you changed, undo mistakes. It's called version control."

Max's eyes lit up. "Like save points in a video game?"

"Exactly like save points. That's next chapter."

🧠 MEMORY

Docker Compose Essentials

docker-compose.yml Structure

services:
  servicename:
    image: image:tag
    container_name: friendly-name
    ports:
      - "host:container"
    environment:
      VAR: "value"
    volumes:
      - volume-name:/path
    restart: unless-stopped
    depends_on:
      - other-service

volumes:
  volume-name:

Key Commands

docker compose up -d        # Start everything (detached)
docker compose down         # Stop and remove containers
docker compose logs -f      # Follow logs from all services
docker compose ps           # List running services
docker compose restart      # Restart services
docker compose pull         # Update images
docker compose up -d --force-recreate  # Rebuild everything

When to Use What

  • Shell scripts: General automation, complex logic, non-Docker tasks
  • Docker Compose: Container configuration, multi-service setups
Type a command below or scroll through content...
$
Vol
0/4
Ch
0/1
Cmd
0
Egg
0/7
LVL 1
Newbie
0 XP