# 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!) ![digitalocean-inception dashboard](https://hackmd.io/_uploads/SkrKr3Yrxl.png) - 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. ---