docs: Update README to reflect Podman integration and rootless setup
- Replace Docker commands with Podman equivalents for building, running, and pushing images. - Enhance local-first development section to highlight Podman's rootless container capabilities. - Update cost comparison and installation instructions to focus on Podman. - Add detailed steps for configuring Podman as a user service and firewall setup. - Revise deployment instructions to align with Podman usage.
- commit
- 5dcaefe013d4a5f1bf4238dab005a46110fbc28b
- author
- bamen · · 2025-06-07 07:37 UTC
- parent
- a7b3a9b
- signature
- unsigned
1 file · +100 -43
M README.md +100 -43
| @@ -25,12 +25,12 @@ Gordon is the missing piece that makes container deployment on budget VPS server | |||
| 25 | 25 | ||
| 26 | 26 | ```bash | |
| 27 | 27 | # 1. Build & test on YOUR machine | |
| 28 | - | docker build -t myapp . | |
| 29 | - | docker run -p 8080:8080 myapp # Works? Great! | |
| 28 | + | podman build -t myapp . | |
| 29 | + | podman run -p 8080:8080 myapp # Works? Great! | |
| 30 | 30 | ||
| 31 | 31 | # 2. Push to deploy | |
| 32 | - | docker tag myapp registry.yourdomain.com/myapp:latest | |
| 33 | - | docker push registry.yourdomain.com/myapp:latest | |
| 32 | + | podman tag myapp registry.yourdomain.com/myapp:latest | |
| 33 | + | podman push registry.yourdomain.com/myapp:latest | |
| 34 | 34 | ||
| 35 | 35 | # 3. That's it. Gordon deploys it automatically. | |
| 36 | 36 | ``` | |
| @@ -54,10 +54,10 @@ Save the file. Gordon redeploys the previous version. Problem solved in seconds. | |||
| 54 | 54 | ## ✨ Key Features | |
| 55 | 55 | ||
| 56 | 56 | ### 🏠 Local-First Development | |
| 57 | - | **Your machine is the build server.** Test locally, push when ready. No waiting for remote builds. | |
| 57 | + | **Your machine is the build server.** Test locally with Podman's rootless containers, push when ready. No waiting for remote builds. | |
| 58 | 58 | ||
| 59 | - | ### 🏦 Built-in Docker Registry | |
| 60 | - | Your VPS becomes a private Docker registry. No Docker Hub subscription needed. | |
| 59 | + | ### 🏦 Built-in Container Registry | |
| 60 | + | Your VPS becomes a private container registry (Docker/Podman compatible). No Docker Hub subscription needed. | |
| 61 | 61 | ||
| 62 | 62 | ### 🔄 Push-to-Deploy Magic | |
| 63 | 63 | Gordon watches for new images and deploys them instantly to configured domains. | |
| @@ -74,22 +74,39 @@ Push new versions anytime. Gordon handles graceful container swaps. | |||
| 74 | 74 | ### 🚀 Automatic Deployment | |
| 75 | 75 | Containers deploy instantly when you push new images. No manual deployment steps needed. | |
| 76 | 76 | ||
| 77 | - | ## 💰 Cost Comparison | |
| 78 | - | ||
| 79 | - | | Solution | Monthly Cost | Setup Complexity | # Apps | | |
| 80 | - | |----------|-------------|------------------|--------| | |
| 81 | - | | Heroku | $7-25/app | ⭐ | Limited | | |
| 82 | - | | AWS ECS | $50-200+ | ⭐⭐⭐⭐⭐ | Unlimited | | |
| 83 | - | | Kubernetes | $100+ | ⭐⭐⭐⭐⭐ | Unlimited | | |
| 84 | - | | **Gordon + VPS** | **$5-20 total** | **⭐⭐** | **Unlimited** | | |
| 85 | - | ||
| 86 | 77 | ## 🚀 Quick Start (5 minutes) | |
| 87 | 78 | ||
| 88 | - | ### 1. Get a VPS & Install Docker | |
| 79 | + | ### 1. Get a VPS & Install Podman (Rootless & Secure) | |
| 89 | 80 | ```bash | |
| 90 | 81 | # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner | |
| 91 | 82 | # Ubuntu/Debian recommended | |
| 92 | - | curl -fsSL https://get.docker.com | sh | |
| 83 | + | ||
| 84 | + | # Install Podman (more secure than Docker) | |
| 85 | + | sudo apt update | |
| 86 | + | sudo apt install -y podman | |
| 87 | + | ||
| 88 | + | # Enable rootless mode for enhanced security | |
| 89 | + | echo 'user.max_user_namespaces=28633' | sudo tee -a /etc/sysctl.conf | |
| 90 | + | sudo sysctl -p | |
| 91 | + | ||
| 92 | + | # Configure user for rootless containers | |
| 93 | + | sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER | |
| 94 | + | ||
| 95 | + | # Start user services (no root required!) | |
| 96 | + | systemctl --user enable --now podman.socket | |
| 97 | + | ||
| 98 | + | # Configure registries for your Gordon registry | |
| 99 | + | mkdir -p ~/.config/containers | |
| 100 | + | tee ~/.config/containers/registries.conf > /dev/null <<EOF | |
| 101 | + | [registries.search] | |
| 102 | + | registries = ['docker.io', 'registry.yourdomain.com'] | |
| 103 | + | ||
| 104 | + | [registries.insecure] | |
| 105 | + | registries = ['registry.yourdomain.com'] | |
| 106 | + | ||
| 107 | + | [registries.block] | |
| 108 | + | registries = [] | |
| 109 | + | EOF | |
| 93 | 110 | ``` | |
| 94 | 111 | ||
| 95 | 112 | ### 2. Install Gordon | |
| @@ -105,7 +122,7 @@ sudo mv gordon-linux-amd64 /usr/local/bin/gordon | |||
| 105 | 122 | [server] | |
| 106 | 123 | port = 8080 | |
| 107 | 124 | registry_domain = "registry.yourdomain.com" | |
| 108 | - | runtime = "auto" # auto-detects Docker/Podman | |
| 125 | + | runtime = "podman-rootless" # Secure rootless mode | |
| 109 | 126 | ssl_email = "you@yourdomain.com" | |
| 110 | 127 | ||
| 111 | 128 | [registry_auth] | |
| @@ -125,25 +142,64 @@ A *.yourdomain.com → YOUR_VPS_IP | |||
| 125 | 142 | A yourdomain.com → YOUR_VPS_IP | |
| 126 | 143 | ``` | |
| 127 | 144 | ||
| 128 | - | ### 5. Start Gordon & Configure Firewall | |
| 145 | + | ### 5. Create Systemd Service (Rootless) | |
| 129 | 146 | ```bash | |
| 130 | - | # Start Gordon | |
| 131 | - | sudo gordon start | |
| 147 | + | # Create user systemd service (no root privileges needed!) | |
| 148 | + | mkdir -p ~/.config/systemd/user | |
| 132 | 149 | ||
| 150 | + | tee ~/.config/systemd/user/gordon.service > /dev/null <<EOF | |
| 151 | + | [Unit] | |
| 152 | + | Description=Gordon Container Platform (Rootless) | |
| 153 | + | After=podman.socket | |
| 154 | + | Requires=podman.socket | |
| 155 | + | ||
| 156 | + | [Service] | |
| 157 | + | Type=simple | |
| 158 | + | Restart=always | |
| 159 | + | RestartSec=5 | |
| 160 | + | Environment=CONTAINER_HOST=unix://%t/podman/podman.sock | |
| 161 | + | ExecStart=/usr/local/bin/gordon start | |
| 162 | + | WorkingDirectory=%h | |
| 163 | + | ||
| 164 | + | [Install] | |
| 165 | + | WantedBy=default.target | |
| 166 | + | EOF | |
| 167 | + | ||
| 168 | + | # Enable and start the user service | |
| 169 | + | systemctl --user daemon-reload | |
| 170 | + | systemctl --user enable --now gordon | |
| 171 | + | ||
| 172 | + | # Enable lingering to start service on boot | |
| 173 | + | sudo loginctl enable-linger $USER | |
| 174 | + | ||
| 175 | + | # Check service status | |
| 176 | + | systemctl --user status gordon | |
| 177 | + | ``` | |
| 178 | + | ||
| 179 | + | ### 6. Configure Firewall | |
| 180 | + | ```bash | |
| 133 | 181 | # Set up port forwarding (choose one option) | |
| 134 | 182 | ||
| 135 | 183 | # Option A: iptables (most common) | |
| 136 | 184 | sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080 | |
| 137 | 185 | sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080 | |
| 138 | 186 | ||
| 187 | + | # Make iptables rules persistent | |
| 188 | + | sudo apt-get install iptables-persistent | |
| 189 | + | sudo netfilter-persistent save | |
| 190 | + | ||
| 139 | 191 | # Option B: UFW with NAT (Ubuntu) | |
| 140 | 192 | sudo ufw allow 22,80,443,8080/tcp | |
| 141 | 193 | echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf | |
| 142 | 194 | sudo sysctl -p | |
| 143 | 195 | ||
| 144 | - | # Deploy your first app | |
| 145 | - | docker tag myapp:latest registry.yourdomain.com/myapp:latest | |
| 146 | - | docker push registry.yourdomain.com/myapp:latest | |
| 196 | + | # Authenticate with your Gordon registry | |
| 197 | + | podman login registry.yourdomain.com | |
| 198 | + | # Use the username/password from your gordon.toml config | |
| 199 | + | ||
| 200 | + | # Deploy your first app (using podman) | |
| 201 | + | podman tag myapp:latest registry.yourdomain.com/myapp:latest | |
| 202 | + | podman push registry.yourdomain.com/myapp:latest | |
| 147 | 203 | # Visit https://app.yourdomain.com 🎉 | |
| 148 | 204 | ``` | |
| 149 | 205 | ||
| @@ -152,32 +208,33 @@ docker push registry.yourdomain.com/myapp:latest | |||
| 152 | 208 | ### Deploy a Node.js App | |
| 153 | 209 | ```bash | |
| 154 | 210 | # Build and test locally first | |
| 155 | - | docker build -t myapp . | |
| 156 | - | docker run -p 3000:3000 myapp # Test it! | |
| 211 | + | podman build -t myapp . | |
| 212 | + | podman run -p 3000:3000 myapp # Test it! | |
| 157 | 213 | ||
| 158 | - | # Tag with version AND latest | |
| 159 | - | docker tag myapp registry.yourdomain.com/myapp:v1.0.0 | |
| 160 | - | docker tag myapp registry.yourdomain.com/myapp:latest | |
| 214 | + | # Tag with registry prefix for both version and latest | |
| 215 | + | podman tag myapp registry.yourdomain.com/myapp:v1.0.0 | |
| 216 | + | podman tag myapp registry.yourdomain.com/myapp:latest | |
| 161 | 217 | ||
| 162 | - | # Push both tags | |
| 163 | - | docker push registry.yourdomain.com/myapp:v1.0.0 | |
| 164 | - | docker push registry.yourdomain.com/myapp:latest | |
| 218 | + | # Push both tags to your Gordon registry | |
| 219 | + | podman push registry.yourdomain.com/myapp:v1.0.0 | |
| 220 | + | podman push registry.yourdomain.com/myapp:latest | |
| 165 | 221 | ||
| 166 | - | # Auto-deployed to app.yourdomain.com | |
| 222 | + | # Gordon automatically detects the push and deploys to app.yourdomain.com | |
| 167 | 223 | ``` | |
| 168 | 224 | ||
| 169 | 225 | ### Smart Versioning Strategy | |
| 170 | 226 | ```bash | |
| 171 | - | # Always push versioned tags | |
| 172 | - | docker tag myapp registry.yourdomain.com/myapp:v1.0.1 | |
| 173 | - | docker push registry.yourdomain.com/myapp:v1.0.1 | |
| 227 | + | # Always push versioned tags first | |
| 228 | + | podman tag myapp registry.yourdomain.com/myapp:v1.0.1 | |
| 229 | + | podman push registry.yourdomain.com/myapp:v1.0.1 | |
| 174 | 230 | ||
| 175 | - | # Update config to test | |
| 231 | + | # Update config to test the new version | |
| 232 | + | # Edit gordon.toml: | |
| 176 | 233 | "app.yourdomain.com" = "myapp:v1.0.1" | |
| 177 | 234 | ||
| 178 | - | # Happy? Update latest | |
| 179 | - | docker tag myapp registry.yourdomain.com/myapp:latest | |
| 180 | - | docker push registry.yourdomain.com/myapp:latest | |
| 235 | + | # Happy with the new version? Tag and push as latest | |
| 236 | + | podman tag registry.yourdomain.com/myapp:v1.0.1 registry.yourdomain.com/myapp:latest | |
| 237 | + | podman push registry.yourdomain.com/myapp:latest | |
| 181 | 238 | ``` | |
| 182 | 239 | ||
| 183 | 240 | ### Instant Rollback When Things Break | |
| @@ -281,8 +338,8 @@ A: Use environment variables in your container or Docker secrets. Gordon doesn't | |||
| 281 | 338 | # Traditional CI/CD | |
| 282 | 339 | push code → wait for build → hope it works → debug remotely → repeat | |
| 283 | 340 | ||
| 284 | - | # The Gordon Way | |
| 285 | - | build locally → test locally → push image → instant deploy | |
| 341 | + | # The Gordon Way (with Podman) | |
| 342 | + | podman build locally → test locally → push image → instant deploy | |
| 286 | 343 | ``` | |
| 287 | 344 | ||
| 288 | 345 | ## 🏗️ Architecture | |
| @@ -25,12 +25,12 @@ Gordon is the missing piece that makes container deployment on budget VPS server | |||||
| 25 | 25 | ||||
| 26 | ```bash | 26 | ```bash | ||
| 27 | # 1. Build & test on YOUR machine | 27 | # 1. Build & test on YOUR machine | ||
| 28 | - | docker build -t myapp . | 28 | + | podman build -t myapp . |
| 29 | - | docker run -p 8080:8080 myapp # Works? Great! | 29 | + | podman run -p 8080:8080 myapp # Works? Great! |
| 30 | 30 | ||||
| 31 | # 2. Push to deploy | 31 | # 2. Push to deploy | ||
| 32 | - | docker tag myapp registry.yourdomain.com/myapp:latest | 32 | + | podman tag myapp registry.yourdomain.com/myapp:latest |
| 33 | - | docker push registry.yourdomain.com/myapp:latest | 33 | + | podman push registry.yourdomain.com/myapp:latest |
| 34 | 34 | ||||
| 35 | # 3. That's it. Gordon deploys it automatically. | 35 | # 3. That's it. Gordon deploys it automatically. | ||
| 36 | ``` | 36 | ``` | ||
| @@ -54,10 +54,10 @@ Save the file. Gordon redeploys the previous version. Problem solved in seconds. | |||||
| 54 | ## ✨ Key Features | 54 | ## ✨ Key Features | ||
| 55 | 55 | ||||
| 56 | ### 🏠 Local-First Development | 56 | ### 🏠 Local-First Development | ||
| 57 | - | **Your machine is the build server.** Test locally, push when ready. No waiting for remote builds. | 57 | + | **Your machine is the build server.** Test locally with Podman's rootless containers, push when ready. No waiting for remote builds. |
| 58 | 58 | ||||
| 59 | - | ### 🏦 Built-in Docker Registry | 59 | + | ### 🏦 Built-in Container Registry |
| 60 | - | Your VPS becomes a private Docker registry. No Docker Hub subscription needed. | 60 | + | Your VPS becomes a private container registry (Docker/Podman compatible). No Docker Hub subscription needed. |
| 61 | 61 | ||||
| 62 | ### 🔄 Push-to-Deploy Magic | 62 | ### 🔄 Push-to-Deploy Magic | ||
| 63 | Gordon watches for new images and deploys them instantly to configured domains. | 63 | Gordon watches for new images and deploys them instantly to configured domains. | ||
| @@ -74,22 +74,39 @@ Push new versions anytime. Gordon handles graceful container swaps. | |||||
| 74 | ### 🚀 Automatic Deployment | 74 | ### 🚀 Automatic Deployment | ||
| 75 | Containers deploy instantly when you push new images. No manual deployment steps needed. | 75 | Containers deploy instantly when you push new images. No manual deployment steps needed. | ||
| 76 | 76 | ||||
| 77 | - | ## 💰 Cost Comparison | |||
| 78 | - | ||||
| 79 | - | | Solution | Monthly Cost | Setup Complexity | # Apps | | |||
| 80 | - | |----------|-------------|------------------|--------| | |||
| 81 | - | | Heroku | $7-25/app | ⭐ | Limited | | |||
| 82 | - | | AWS ECS | $50-200+ | ⭐⭐⭐⭐⭐ | Unlimited | | |||
| 83 | - | | Kubernetes | $100+ | ⭐⭐⭐⭐⭐ | Unlimited | | |||
| 84 | - | | **Gordon + VPS** | **$5-20 total** | **⭐⭐** | **Unlimited** | | |||
| 85 | - | ||||
| 86 | ## 🚀 Quick Start (5 minutes) | 77 | ## 🚀 Quick Start (5 minutes) | ||
| 87 | 78 | ||||
| 88 | - | ### 1. Get a VPS & Install Docker | 79 | + | ### 1. Get a VPS & Install Podman (Rootless & Secure) |
| 89 | ```bash | 80 | ```bash | ||
| 90 | # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner | 81 | # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner | ||
| 91 | # Ubuntu/Debian recommended | 82 | # Ubuntu/Debian recommended | ||
| 92 | - | curl -fsSL https://get.docker.com | sh | 83 | + | |
| 84 | + | # Install Podman (more secure than Docker) | |||
| 85 | + | sudo apt update | |||
| 86 | + | sudo apt install -y podman | |||
| 87 | + | ||||
| 88 | + | # Enable rootless mode for enhanced security | |||
| 89 | + | echo 'user.max_user_namespaces=28633' | sudo tee -a /etc/sysctl.conf | |||
| 90 | + | sudo sysctl -p | |||
| 91 | + | ||||
| 92 | + | # Configure user for rootless containers | |||
| 93 | + | sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER | |||
| 94 | + | ||||
| 95 | + | # Start user services (no root required!) | |||
| 96 | + | systemctl --user enable --now podman.socket | |||
| 97 | + | ||||
| 98 | + | # Configure registries for your Gordon registry | |||
| 99 | + | mkdir -p ~/.config/containers | |||
| 100 | + | tee ~/.config/containers/registries.conf > /dev/null <<EOF | |||
| 101 | + | [registries.search] | |||
| 102 | + | registries = ['docker.io', 'registry.yourdomain.com'] | |||
| 103 | + | ||||
| 104 | + | [registries.insecure] | |||
| 105 | + | registries = ['registry.yourdomain.com'] | |||
| 106 | + | ||||
| 107 | + | [registries.block] | |||
| 108 | + | registries = [] | |||
| 109 | + | EOF | |||
| 93 | ``` | 110 | ``` | ||
| 94 | 111 | ||||
| 95 | ### 2. Install Gordon | 112 | ### 2. Install Gordon | ||
| @@ -105,7 +122,7 @@ sudo mv gordon-linux-amd64 /usr/local/bin/gordon | |||||
| 105 | [server] | 122 | [server] | ||
| 106 | port = 8080 | 123 | port = 8080 | ||
| 107 | registry_domain = "registry.yourdomain.com" | 124 | registry_domain = "registry.yourdomain.com" | ||
| 108 | - | runtime = "auto" # auto-detects Docker/Podman | 125 | + | runtime = "podman-rootless" # Secure rootless mode |
| 109 | ssl_email = "you@yourdomain.com" | 126 | ssl_email = "you@yourdomain.com" | ||
| 110 | 127 | ||||
| 111 | [registry_auth] | 128 | [registry_auth] | ||
| @@ -125,25 +142,64 @@ A *.yourdomain.com → YOUR_VPS_IP | |||||
| 125 | A yourdomain.com → YOUR_VPS_IP | 142 | A yourdomain.com → YOUR_VPS_IP | ||
| 126 | ``` | 143 | ``` | ||
| 127 | 144 | ||||
| 128 | - | ### 5. Start Gordon & Configure Firewall | 145 | + | ### 5. Create Systemd Service (Rootless) |
| 129 | ```bash | 146 | ```bash | ||
| 130 | - | # Start Gordon | 147 | + | # Create user systemd service (no root privileges needed!) |
| 131 | - | sudo gordon start | 148 | + | mkdir -p ~/.config/systemd/user |
| 132 | 149 | ||||
| 150 | + | tee ~/.config/systemd/user/gordon.service > /dev/null <<EOF | |||
| 151 | + | [Unit] | |||
| 152 | + | Description=Gordon Container Platform (Rootless) | |||
| 153 | + | After=podman.socket | |||
| 154 | + | Requires=podman.socket | |||
| 155 | + | ||||
| 156 | + | [Service] | |||
| 157 | + | Type=simple | |||
| 158 | + | Restart=always | |||
| 159 | + | RestartSec=5 | |||
| 160 | + | Environment=CONTAINER_HOST=unix://%t/podman/podman.sock | |||
| 161 | + | ExecStart=/usr/local/bin/gordon start | |||
| 162 | + | WorkingDirectory=%h | |||
| 163 | + | ||||
| 164 | + | [Install] | |||
| 165 | + | WantedBy=default.target | |||
| 166 | + | EOF | |||
| 167 | + | ||||
| 168 | + | # Enable and start the user service | |||
| 169 | + | systemctl --user daemon-reload | |||
| 170 | + | systemctl --user enable --now gordon | |||
| 171 | + | ||||
| 172 | + | # Enable lingering to start service on boot | |||
| 173 | + | sudo loginctl enable-linger $USER | |||
| 174 | + | ||||
| 175 | + | # Check service status | |||
| 176 | + | systemctl --user status gordon | |||
| 177 | + | ``` | |||
| 178 | + | ||||
| 179 | + | ### 6. Configure Firewall | |||
| 180 | + | ```bash | |||
| 133 | # Set up port forwarding (choose one option) | 181 | # Set up port forwarding (choose one option) | ||
| 134 | 182 | ||||
| 135 | # Option A: iptables (most common) | 183 | # Option A: iptables (most common) | ||
| 136 | sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080 | 184 | sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080 | ||
| 137 | sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080 | 185 | sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080 | ||
| 138 | 186 | ||||
| 187 | + | # Make iptables rules persistent | |||
| 188 | + | sudo apt-get install iptables-persistent | |||
| 189 | + | sudo netfilter-persistent save | |||
| 190 | + | ||||
| 139 | # Option B: UFW with NAT (Ubuntu) | 191 | # Option B: UFW with NAT (Ubuntu) | ||
| 140 | sudo ufw allow 22,80,443,8080/tcp | 192 | sudo ufw allow 22,80,443,8080/tcp | ||
| 141 | echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf | 193 | echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf | ||
| 142 | sudo sysctl -p | 194 | sudo sysctl -p | ||
| 143 | 195 | ||||
| 144 | - | # Deploy your first app | 196 | + | # Authenticate with your Gordon registry |
| 145 | - | docker tag myapp:latest registry.yourdomain.com/myapp:latest | 197 | + | podman login registry.yourdomain.com |
| 146 | - | docker push registry.yourdomain.com/myapp:latest | 198 | + | # Use the username/password from your gordon.toml config |
| 199 | + | ||||
| 200 | + | # Deploy your first app (using podman) | |||
| 201 | + | podman tag myapp:latest registry.yourdomain.com/myapp:latest | |||
| 202 | + | podman push registry.yourdomain.com/myapp:latest | |||
| 147 | # Visit https://app.yourdomain.com 🎉 | 203 | # Visit https://app.yourdomain.com 🎉 | ||
| 148 | ``` | 204 | ``` | ||
| 149 | 205 | ||||
| @@ -152,32 +208,33 @@ docker push registry.yourdomain.com/myapp:latest | |||||
| 152 | ### Deploy a Node.js App | 208 | ### Deploy a Node.js App | ||
| 153 | ```bash | 209 | ```bash | ||
| 154 | # Build and test locally first | 210 | # Build and test locally first | ||
| 155 | - | docker build -t myapp . | 211 | + | podman build -t myapp . |
| 156 | - | docker run -p 3000:3000 myapp # Test it! | 212 | + | podman run -p 3000:3000 myapp # Test it! |
| 157 | 213 | ||||
| 158 | - | # Tag with version AND latest | 214 | + | # Tag with registry prefix for both version and latest |
| 159 | - | docker tag myapp registry.yourdomain.com/myapp:v1.0.0 | 215 | + | podman tag myapp registry.yourdomain.com/myapp:v1.0.0 |
| 160 | - | docker tag myapp registry.yourdomain.com/myapp:latest | 216 | + | podman tag myapp registry.yourdomain.com/myapp:latest |
| 161 | 217 | ||||
| 162 | - | # Push both tags | 218 | + | # Push both tags to your Gordon registry |
| 163 | - | docker push registry.yourdomain.com/myapp:v1.0.0 | 219 | + | podman push registry.yourdomain.com/myapp:v1.0.0 |
| 164 | - | docker push registry.yourdomain.com/myapp:latest | 220 | + | podman push registry.yourdomain.com/myapp:latest |
| 165 | 221 | ||||
| 166 | - | # Auto-deployed to app.yourdomain.com | 222 | + | # Gordon automatically detects the push and deploys to app.yourdomain.com |
| 167 | ``` | 223 | ``` | ||
| 168 | 224 | ||||
| 169 | ### Smart Versioning Strategy | 225 | ### Smart Versioning Strategy | ||
| 170 | ```bash | 226 | ```bash | ||
| 171 | - | # Always push versioned tags | 227 | + | # Always push versioned tags first |
| 172 | - | docker tag myapp registry.yourdomain.com/myapp:v1.0.1 | 228 | + | podman tag myapp registry.yourdomain.com/myapp:v1.0.1 |
| 173 | - | docker push registry.yourdomain.com/myapp:v1.0.1 | 229 | + | podman push registry.yourdomain.com/myapp:v1.0.1 |
| 174 | 230 | ||||
| 175 | - | # Update config to test | 231 | + | # Update config to test the new version |
| 232 | + | # Edit gordon.toml: | |||
| 176 | "app.yourdomain.com" = "myapp:v1.0.1" | 233 | "app.yourdomain.com" = "myapp:v1.0.1" | ||
| 177 | 234 | ||||
| 178 | - | # Happy? Update latest | 235 | + | # Happy with the new version? Tag and push as latest |
| 179 | - | docker tag myapp registry.yourdomain.com/myapp:latest | 236 | + | podman tag registry.yourdomain.com/myapp:v1.0.1 registry.yourdomain.com/myapp:latest |
| 180 | - | docker push registry.yourdomain.com/myapp:latest | 237 | + | podman push registry.yourdomain.com/myapp:latest |
| 181 | ``` | 238 | ``` | ||
| 182 | 239 | ||||
| 183 | ### Instant Rollback When Things Break | 240 | ### Instant Rollback When Things Break | ||
| @@ -281,8 +338,8 @@ A: Use environment variables in your container or Docker secrets. Gordon doesn't | |||||
| 281 | # Traditional CI/CD | 338 | # Traditional CI/CD | ||
| 282 | push code → wait for build → hope it works → debug remotely → repeat | 339 | push code → wait for build → hope it works → debug remotely → repeat | ||
| 283 | 340 | ||||
| 284 | - | # The Gordon Way | 341 | + | # The Gordon Way (with Podman) |
| 285 | - | build locally → test locally → push image → instant deploy | 342 | + | podman build locally → test locally → push image → instant deploy |
| 286 | ``` | 343 | ``` | ||
| 287 | 344 | ||||
| 288 | ## 🏗️ Architecture | 345 | ## 🏗️ Architecture | ||