# General Project setup
Virtual Server Setup:
- Register on [digitalocean](https://www.digitalocean.com/?utm_campaign=search_emea_en_brand&utm_adgroup=digitalocean_exact_exact&utm_keyword=digitalocean&utm_matchtype=e&utm_adposition=&utm_creative=679114066310&utm_placement=&utm_device=c&utm_location=&utm_location=9056141&utm_term=digitalocean&utm_source=google&utm_medium=cpc&gad_source=1&gad_campaignid=10266589429&gclid=CjwKCAjw4K3DBhBqEiwAYtG_9LaV0Hh-mBasE-FO3Lhs3cTd0poAbQ1JBOO1qtZtjPSxKE6mkVrGkhoC_tIQAvD_BwE) to create a online virtual machine with Github student account (Free!)

- Intall extension [remote ssh](https://code.visualstudio.com/docs/remote/ssh) on vscode, after can access to the virtual server and make edits and test. (Super convenient!)
- Setup Structure:
```
Host inception
HostName 161.35.197.125 # My remote server
User yilin42
Port 4242
```
=> It's running Docker containers ON A REMOTE SERVER, not locally!
- Workflow:
```
Local Machine → SSH → Remote Server (161.35.197.125)
↓
Docker containers running here
↓
Adminer/WordPress/nginx
```
- Remote Docker setup structure:
```
Local Machine
↓ (SSH)
Remote Server (161.35.197.125:4242)
↓ (Docker)
nginx:443 → adminer:80
→ wordpress:9000
→ mariadb:3306
```
- Set up SSH Key linkage (SSH Key Authentication):
```bash!
# View Your Public Key # Copy this key
cat ~/.ssh/id_rsa.pub
# Add Key to Server
# Method 1: If you have password access
ssh-copy-id -p 4242 yilin42@161.35.197.125
# Method 2: Manual copy (if password access available)
ssh -p 4242 yilin42@161.35.197.125
# Then on server:
mkdir -p ~/.ssh
echo "YOUR_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# Once SSH Works:
# After SSH connection established -> link to the designated port
ssh yilin42@161.35.197.125 -p 4242
```
---
---
# Structure Overview
### 🔹 **Visual Overview: Docker vs Docker Compose**
```
Docker (Single Container Example)
┌──────────────────────────┐
│ Your Machine │
│ ┌────────────────────┐ │
│ │ Docker Engine │ │
│ │ ┌──────────────┐ │ │
│ │ │ Container │ │ │ ← Runs 1 app (e.g., a Python app)
│ │ └──────────────┘ │ │
│ └────────────────────┘ │
└──────────────────────────┘
You manually build/run:
docker build -t myapp .
docker run -p 5000:5000 myapp
```
```
Docker Compose (Multi-Container Example)
┌──────────────────────────────┐
│ Your Machine │
│ ┌─────────────────────────┐ │
│ │ Docker Engine │ │
│ │ ┌────────┐ ┌──────────┐ │ │
│ │ │Frontend│ │ Backend │ │ │
│ │ └────────┘ └──────────┘ │ │
│ │ ┌────────────┐ │ │
│ │ │ Database │ │ │
│ │ └────────────┘ │ │
│ └─────────────────────────┘ │
└──────────────────────────────┘
All started via:
docker compose up
```
### 🔹 **Visual: Project Directory Structure**
```
your-project/
├── docker-compose.yml ← Defines all services (frontend, backend, db)
├── .env ← (Optional) Environment variables
│
├── frontend/ ← Frontend service
│ ├── Dockerfile ← Image for frontend
│ └── index.html
│
├── backend/ ← Backend service
│ ├── Dockerfile ← Image for backend
│ └── app.py
│
├── db/ ← Database initialization
│ └── init.sql
```
---
---
# Before Using Makefile to run containers(/docker-compose.yml)
## one-line command to reset dockers
```bash!
docker stop $(docker ps -qa); docker rm $(docker ps -qa); docker rmi -f $(docker images -qa); docker volume rm $(docker volume ls -q); docker network rm $(docker network ls -q) 2>/dev/null
```
* `docker ps -qa`: Lists all container IDs (`-q` for quiet, `-a` for all).
* `docker stop $(...)`: Stops all running containers.
* `docker rm $(...)`: Removes all containers.
* `docker rmi -f $(...)`: Force removes all images.
* `docker volume rm $(...)`: Removes all volumes.
* `docker network rm $(...)`: Removes all networks.
* `2>/dev/null`: Silently discards error messages (e.g., trying to remove the default `bridge` network, which isn’t allowed).
> ✅ **Purpose**: This completely resets the Docker environment (except default networks).
---
## Important Concepts
### 🐳 vs 🖥 **Docker vs Virtual Machine**
| Feature | Docker (Container) | Virtual Machine (VM) |
| -------------- | --------------------------------- | --------------------------------- |
| Boot time | Seconds | Minutes |
| Resource usage | Lightweight | Heavy (full OS) |
| Isolation | Shares OS kernel | Full OS isolation |
| Use case | Run apps in isolated environments | Full OS testing or legacy systems |
**Analogy**:
Docker is like using multiple apps in the same phone.
VM is like giving every app its own phone.
---
### 🔄 **Analogy for Dockerfile, Image, Container, Docker Compose, App, Environment**
#### **🏗 Analogy: Building and Running a Restaurant**
* **Dockerfile** = *Recipe Book*
→ Tells you how to cook a dish (build your app image).
* **Image** = *Prepared Meal in a Box*
→ The result of following the recipe. It’s ready to be served but not “eaten” yet.
* **Container** = *Table where the meal is served*
→ It runs the image (meal), isolated from other tables. Each container is like its own customer with its own plate.
* **Docker Compose File** = *Restaurant Manager*
→ Organizes many meals (services) and tells the kitchen when and how to cook and serve each dish. Manages multi-container apps.
* **App** = *The dish itself*
→ Your website, database, etc., running inside containers.
* **Environment** = *Restaurant theme/config*
→ Custom settings: e.g., lighting, music, menu (ENV variables like DB name, passwords, etc.)
---
### **Alpine vs Debian to Docker**
| Feature | Alpine | Debian |
| ------------- | ------------------------------- | ------------------------------------ |
| Size | \~5 MB (very minimal) | \~20–100 MB (depending on version) |
| Performance | Fast, small footprint | More robust, compatible |
| Package Mgr | `apk` | `apt` |
| Use Case | Minimalist containers, security | Full-featured containers, easier dev |
| Compatibility | May break with some packages | More stable with most packages |
> **Connection to Docker**: Docker images are often **based on Alpine** or **Debian** to reduce size or improve compatibility.
=> Example:
```Dockerfile
FROM alpine
# or
FROM debian:bullseye
```
---
### **Importance of `networks` in `docker-compose.yml`**
* **Defines how containers communicate.**
* **Isolates services from external traffic unless published.**
* **Allows naming and managing logical groups.**
* **Provides internal DNS (you can use service names as hostnames).**
> ✅ Custom networks give more **control**, **security**, and **scalability** in Docker setups.
---
### **`network: host` / `links:` / ```bridge```**
```yaml
# bridge version:
networks:
inception_network:
driver: bridge
```
> ✅ This defines a **user-defined bridge network**, more isolated and preferred over defaults.
### Differences between the 3:
| Feature | `network: host` | `links:` | Custom `bridge` Network |
| ------------------------------- | ------------------------------ | --------------------------------- | ------------------------------------ |
| **`network: host`** | Shares host's networking stack | Deprecated way to link containers | Custom, user-defined virtual network |
| **Security** | Less secure | Less flexible | Better isolation and flexibility |
| **DNS-Based Service Discovery** | ❌ | ❌ | ✅ Yes, with container names |
| **Use Case** | High performance, like games | Legacy projects | Recommended for most Compose setups |
> ❗ Avoid `host` unless necessary. Avoid `links:` — it's deprecated.
---
### **How Docker & Docker Compose Work?**
* **Docker** is a tool that lets you package an application with everything it needs (code, libraries, settings) into a **container**. A container runs the same way on any system with Docker installed, ensuring consistency and avoiding "it works on my machine" problems.
* **Docker Compose** is a tool for running **multiple containers together**. It uses a file (usually `docker-compose.yml`) to define and manage multi-container applications (e.g., a web app, a database, and a cache working together). You define how the services interact, then run everything with a single command.
---
### **Difference Between a Docker Image Used With and Without Docker Compose?**
* **Without Docker Compose**:
You manually run each container using the `docker run` command, specifying all options (ports, volumes, networks, etc.) every time.
* **With Docker Compose**:
You define all containers and settings **once** in a `docker-compose.yml` file. Then, you launch everything together with `docker compose up`. It simplifies orchestration and is easier to maintain, especially for projects involving multiple services.
> **Note:** The Docker image itself does **not change**. Whether you use it with or without Compose, it’s the same image. The difference is in **how** the image is deployed and managed.
---