Deploy ও CI/CD
Server এ তোলা, GitHub Actions দিয়ে auto deploy
তোমার API এখন Docker এ চলে। এবার সেটা internet এ তুলবো, যাতে তোমার Flutter app যেকোনো জায়গা থেকে, যেকোনো phone থেকে ব্যবহার করা যায়। তারপর এমন ব্যবস্থা করবো যাতে GitHub এ code push করলেই নিজে থেকে test চলে, আর সব ঠিক থাকলে নতুন version deploy হয়ে যায় (CI/CD)। অফিসে যে "deploy এর দিন" এর আতঙ্ক থাকে, সেটা দূর করার উপায় এটাই।
#কোথায় deploy করবে
| ধরন | উদাহরণ | সুবিধা | অসুবিধা | কখন |
|---|---|---|---|---|
| PaaS (platform) | Railway, Render, Fly.io, Koyeb | Git push বা Docker image দিলেই চলে, HTTPS, database সহজে | খরচ বড় হলে বেশি, নিয়ন্ত্রণ কম | শেখা, ছোট-মাঝারি project, startup |
| VPS (নিজের server) | DigitalOcean, Hetzner, Linode, AWS Lightsail | সস্তা, পুরো নিয়ন্ত্রণ | সব নিজে: security update, backup, HTTPS, monitoring | Linux শিখতে চাইলে, খরচ কমাতে |
| বড় cloud | AWS, GCP, Azure | সব কিছু আছে, বিশাল scale | জটিল, খরচ বোঝা কঠিন | অফিসের বড় system |
| Serverless | AWS Lambda, Cloud Run | ব্যবহার না হলে খরচ প্রায় শূন্য | Cold start, সীমাবদ্ধতা | হঠাৎ হঠাৎ ব্যবহার হওয়া API |
শেখার জন্য পরামর্শ: প্রথমে একটা PaaS এ deploy করো (দ্রুত সফলতা)। পরে একবার একটা ছোট VPS এ নিজে সব করে দেখো (Linux, Nginx, HTTPS শেখার জন্য)।
#Production এর আগে checklist
#PaaS এ deploy (Railway উদাহরণ, Render/Fly প্রায় একই)
- GitHub এ repo push করো (Dockerfile সহ)
- Platform এ নতুন project → "Deploy from GitHub repo"
- একটা PostgreSQL আর একটা Redis যোগ করো (platform এর ভেতরেই)
- Environment variable দাও:
DATABASE_URL(platform এর দেওয়া, শুধু driver অংশpostgresql+asyncpg://করে নাও),REDIS_URL,JWT_SECRET,ENVIRONMENT=production - Migration: start command এর আগে চালাও, বা আলাদা "release command":
alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port $PORT --proxy-headers- Platform একটা
https://notes-api-production.up.railway.appএর মতো URL দেবে। নিজের domain লাগাতে CNAME record (DNS অধ্যায়)।
#VPS এ deploy: নিজের হাতে একবার
একটা Ubuntu server (মাসে ৪-৬ ডলার) নিয়ে:
# ১. Server এ ঢোকো (SSH key দিয়ে, password দিয়ে না)
ssh root@203.0.113.50
# ২. নিরাপত্তার মৌলিক কাজ
adduser deploy && usermod -aG sudo deploy
# SSH এ password login আর root login বন্ধ করো (/etc/ssh/sshd_config)
ufw allow OpenSSH && ufw allow 80 && ufw allow 443 && ufw enable
apt update && apt upgrade -y && apt install -y unattended-upgrades
# ৩. Docker install (official script বা apt repo)
curl -fsSL https://get.docker.com | sh
usermod -aG docker deploy# ৪. Code আর env আনো, চালাও
git clone https://github.com/you/notes-api.git && cd notes-api
nano .env # production এর secret
docker compose -f compose.prod.yaml up -d --buildHTTPS এর জন্য সবচেয়ে সহজ Caddy (নিজে থেকে Let's Encrypt certificate নেয় আর নবায়ন করে):
# Caddyfile
api.example.com {
reverse_proxy api:8000
encode gzip
}Compose এ caddy service যোগ করে port 80/443 খুলে দাও। এখন https://api.example.com চালু, certificate নিয়ে আর চিন্তা নেই।
#CI/CD: GitHub Actions
CI (Continuous Integration): প্রতিটা push এ নিজে থেকে test আর check। CD (Continuous Deployment): main branch এ সব সবুজ হলে নিজে থেকে deploy।
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17
env:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: notes_test
ports: ["5432:5432"]
options: >-
--health-cmd "pg_isready -U app" --health-interval 5s --health-retries 10
env:
DATABASE_URL: postgresql+asyncpg://app:secret@localhost:5432/notes_test
JWT_SECRET: ci-only-secret
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
- run: uv sync --frozen
- run: uv run ruff check .
- run: uv run ruff format --check .
- run: uv run pyright
- run: uv run pytest --cov=src --cov-report=term-missing
deploy:
needs: test # test সফল হলে তবেই
if: github.ref == 'refs/heads/main' # শুধু main branch এ
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Platform অনুযায়ী: Railway/Render/Fly এর deploy hook বা CLI
- run: curl -fsS -X POST "${{ secrets.DEPLOY_HOOK_URL }}"secrets.DEPLOY_HOOK_URL থাকে GitHub repo এর Settings → Secrets এ, code এ না।
#Branch এর নিয়ম
mainএ সরাসরি push বন্ধ (branch protection)- প্রতিটা কাজ আলাদা branch এ, Pull Request দিয়ে
- PR merge হবে শুধু CI সবুজ হলে
- একা কাজ করলেও এই অভ্যাস রাখো। অফিসে আর interview এ এটা দেখায় তুমি পেশাদারভাবে কাজ করো।
#Deploy এর পরে
- Smoke test: deploy এর পর
/health/readyআর একটা মূল endpoint call করে দেখো - Rollback এর উপায় জানো: আগের image/version এ ফেরার command বা button, আগে থেকেই একবার চেষ্টা করে দেখো
- Log আর error দেখো: deploy এর পরের ১৫ মিনিট বিশেষ নজর (Monitoring)
- Database backup পরীক্ষা: backup নেওয়া হচ্ছে, কিন্তু সেখান থেকে restore করা যায় কিনা একবার নিজে চেষ্টা করেছো? যে backup কখনো restore করে দেখা হয়নি, সেটা backup না।
#অনুশীলন
#নিজেকে যাচাই করো
CI আর CD এর পার্থক্য কী?
CI: প্রতিটা push এ নিজে থেকে lint, type check আর test চালিয়ে code এর মান যাচাই। CD: সব যাচাই সফল হলে নিজে থেকে production (বা staging) এ deploy করা।
Production এর secret (JWT_SECRET, database password) কোথায় রাখবে?
Platform এর environment variable বা secret manager এ, আর CI এর জন্য GitHub Secrets এ। কখনো code, Git, বা Docker image এর ভেতরে না।
একাধিক container এর প্রতিটা চালু হওয়ার সময় migration চালালে কী ঝুঁকি?
একসাথে কয়েকটা migration চলে একে অপরের সাথে সংঘর্ষ করতে পারে বা আংশিক অবস্থায় আটকে যেতে পারে। ভালো উপায় হলো deploy এর একটা আলাদা ধাপে একবার migration চালানো।
"যে backup কখনো restore করে দেখা হয়নি সেটা backup না" কথাটার মানে কী?
Backup হয়তো ভাঙা, অসম্পূর্ণ, বা restore এর পদ্ধতি কেউ জানে না। আসল বিপদের সময় সেটা কাজ না করলে কোনো লাভ নেই। তাই মাঝে মাঝে backup থেকে আলাদা জায়গায় restore করে যাচাই করতে হয়।
চিহ্ন দিলে sidebar আর রোডম্যাপে এই অধ্যায়ের station ভরে যাবে।