# How Docker Containers Really Talk to Each Other with Networks : My First Real DevOps Lesson

When I started learning Docker with a simple **Spring Boot + MongoDB** project, the tutor gave us two commands:

```bash
# Run the Spring Boot app
docker run -d -p 8080:8080 --name springapp \
  --network jionetwork \
  -e MONGO_DB_HOSTNAME=mongo \
  -e MONGO_DB_USERNAME=devdb \
  -e MONGO_DB_PASSWORD=dev@123 \
  kkdevopsb5/springwebapp:1.0.0

# Run the MongoDB database
docker run -d --name mongo \
  --network jionetwork \
  -e MONGO_INITDB_ROOT_USERNAME=devdb \
  -e MONGO_INITDB_ROOT_PASSWORD=dev@123 \
  mongo
```

The app worked fine after running these. But inside my head, one big question popped up:

👉 **Why exactly are we running these commands in this way?**  
How did the Spring Boot container *know* that the `mongo` container is the database?

At first, I thought it was magic. Later, after some digging, it made complete sense. Let me share what I discovered.

---

## Step 1: Spring Boot Doesn’t Hardcode DB Configs

In the source code, I found this `application.yaml`:

```yaml
spring:
  data:
    mongodb:
      host: ${MONGO_DB_HOSTNAME}
      port: 27017
      username: ${MONGO_DB_USERNAME}
      password: ${MONGO_DB_PASSWORD}
      database: users
      authentication-database: admin
```

Notice the `${...}` placeholders.  
Spring Boot expects **environment variables** to fill these values at runtime.

That’s why the tutor passed:

* `-e MONGO_DB_HOSTNAME=mongo`
    
* `-e MONGO_DB_USERNAME=devdb`
    
* `-e MONGO_DB_PASSWORD=dev@123`
    

Without these, the app wouldn’t know where the database lives or how to log in.

👉 **Learning point**: As DevOps, our job is not to code the app, but to *read the config files* (like `application.yaml`) and know what environment variables the app expects.

---

## Step 2: Why `mongo` Instead of an IP Address?

This is where **Docker networks** come in.  
Both containers were attached to the same custom network `jionetwork`.

In Docker, when you create a custom network:

* Every container in that network can talk to others **by name**, not IP.
    
* Docker runs an internal DNS resolver that maps names → container IPs.
    

So when Spring Boot tries to connect to `mongo:27017`, Docker resolves `mongo` to the real container IP behind the scenes.

### Analogy: Calling a Friend

Think of it like calling a friend:

* Without Docker network → you must remember your friend’s phone number (IP address).
    
* With Docker network → you just say their **name** (e.g., “Call *mongo*”), and your phone (Docker DNS) automatically finds the correct number.
    

This makes things stable: even if MongoDB container restarts and gets a new IP, the name `mongo` still works.

**Learning point**: The whole purpose of Docker networks is to allow containers to communicate using **names instead of IPs**.

---

## Step 3: Separation of Build vs Runtime

Another thing that confused me:  
“Why doesn’t the Dockerfile mention Mongo anywhere?”

Then I realized:

* **Dockerfile** = build instructions (package the JAR, set workdir, expose port)
    
* **docker run with -e** = runtime instructions (which DB host, which credentials)
    

This separation is good practice. It means the same app image can be reused for:

* Local environment → maybe DB host = [`localhost`](http://localhost)
    
* Staging → DB host = `mongo-staging`
    
* Production → DB host = `mongo-prod`
    

All without rebuilding the image.

---

## What I Wish I Knew Earlier

* Every framework has its own config system:
    
    * Spring Boot → `application.yaml`
        
    * Node.js → `.env`
        
    * Python Django/Flask → [`settings.py`](http://settings.py) or `.env`
        
* As DevOps, you don’t need to write app logic, but you must know **where to look for DB configs, ports, and credentials**.
    
* Docker custom networks give you **name-based communication**, powered by Docker’s built-in DNS.
    

---

## Final Takeaway

At first, I thought my tutor skipped details. But later I realized this is **real-world learning**:  
In companies, no one explains every line. You get a repo and some commands, and it’s your job to **retrospect** and figure out:

* Why these environment variables?
    
* How do containers find each other?
    
* What’s handled at build time vs runtime?
    

And that reflection — the “why” behind the command — is what transforms you from just running Docker to actually understanding DevOps.

---

**Tip for beginners like me**:  
Whenever you see `docker run` with `-e` flags, pause and check the app’s config files.  
That’s where the missing link hides — and once you see it, the whole flow makes sense.

---

✨ That’s the story of how I learned that `docker run` isn’t just about starting a container — it’s about passing the right environment and letting Docker networking + DNS do the magic.

---
