404 Not Found

404 Not Found


nginx

Project Deployment and Launch — From Development to Production

Launching a product is like launching a rocket—the first 24 lessons cover design and manufacturing, and this lesson is about the countdown and launch. There's a long checklist before launch, and you can't ignite the engines until every item is checked off. Launching without a checklist is a gamble.

1. What You'll Learn


2. Alice's True Story

(1) Pain Point: Frequent Incidents During Deployment

PriceTracker experienced issues during its first two deployments: the first time, they forgot to configure HTTPS; the second time, a table lock during a database migration caused a 10-minute service outage; and the third time, logs weren't aggregated, so after a problem arose, Charlie spent two hours sifting through logs on five servers. Alice needs a systematic deployment process to ensure that every deployment is safe and controllable.

(2) Solution for the Deployment Checklist

Deployment isn't just a matter of "pushing the code up and calling it a day"; it's a series of checklists: security hardening, performance validation, migration strategy, staged rollout, and monitoring verification—you can only move on to the next step after checking off each one.

(3) Revenue

Third deployment: All items on the checklist were checked off; HTTPS was configured; the migration was completed with zero downtime; a rolling release was initiated by first routing 10% of traffic for validation; and logs were automatically aggregated to Loki—the entire deployment process went off without a hitch, and Charlie's monitoring dashboard remained in the green the whole time.


3. Production Environment Checklist

(1) Launch Process

100%
flowchart TD
    A[Code Freeze] --> B[Security Audit]
    B --> C[Load Test]
    C --> D[Staging Deploy]
    D --> E[Smoke Test]
    E --> F[Canary Release 10%]
    F --> G{Metrics OK?}
    G -->|Yes| H[Full Rollout 100%]
    G -->|No| I[Rollback]
    I --> J[Investigate]
    J --> A
    H --> K[Monitor 1h]
    K --> L[✓ Live]

(2) Three-Dimensional Checklist

Dimension Check Item Status
Security HTTPS Certificate Configuration
CORS allows only production domains
Rate Limiting Enabled
JWT SECRET_KEY has been changed
No hard-coded keys
Security scan passed
Performance Uvicorn Workers ≥ 4
Appropriate DB connection pool size
Redis Caching Enabled
GZip compression enabled
Load test passed (target QPS)
Monitoring /health endpoint is normal
Prometheus Metrics Collection
Grafana Dashboard Ready
Alert Rule Configuration
Log Aggregation Running

4. Staged Rollout Strategy

(1) Blue-Green Deployment

100%
flowchart LR
    LB[Load Balancer] -->|100% traffic| Blue[Blue v1]
    
    subgraph Deploy
        Green[Green v2]
    end
    
    LB -.->|Switch| Green
    
    style Blue fill:#4caf50
    style Green fill:#2196f3
Step Action Rollback
1 Deploy the Green (v2) environment -
2 Run smoke tests in Green -
3 LB Switch to Green Switch back to Blue
4 Monitor Green for 30 minutes Switch back to Blue
5 Stability confirmed, Blue taken offline -

(1) ▶ Example: Nginx Blue-Green Configuration

NGINX
# nginx/conf.d/pricetracker.conf
upstream pricetracker_blue {
    server api-blue:8000;
}

upstream pricetracker_green {
    server api-green:8000;
}

# Currently serving Blue
server {
    listen 80;
    server_name api.pricetracker.example.com;

    location / {
        proxy_pass http://pricetracker_blue;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# Switch to Green by changing proxy_pass target
# Then: docker compose -f docker-compose.green.yml up -d

Output:

TEXT
// Execution Successful

(2) Canary Release

Strategy Traffic Distribution Observation Period Rollback
10% 1 v2 + 9 v1 15 min Switch back to v1
30% 3 v2 + 7 v1 15 min Switch back to v1
50% 5 v2 + 5 v1 15 min Switch back to v1
100% All v2 30 min Rollback image version

5. Zero-Downtime Database Migration

(1) Principles of Secure Migration

Principle Description Example
Add Only, Do Not Delete Add a new column first; do not delete the old column ALTER TABLE ADD COLUMN new_col
Dual-write compatibility Both new and old code work New code writes to two columns; old code reads only the old column
Delayed Cleanup Delete old columns only after stability is confirmed Delete old columns 7 days after deploying v2
Incremental Migration Change only one thing at a time Don't add columns or change data types in a single migration

(1) ▶ Example: Safe Column Addition Migration

PYTHON
# alembic/versions/xxx_add_wholesale_price.py
"""Add wholesale_price column to products

Safe migration: ADD COLUMN is non-blocking in PostgreSQL
"""

def upgrade():
    op.add_column(
        "products",
        sa.Column("wholesale_price", sa.Float(), nullable=True),
    )
    # Set default for existing rows (separate statement for performance)
    op.execute("UPDATE products SET wholesale_price = base_price * 0.6 WHERE wholesale_price IS NULL")
    # Make non-nullable in next migration after code deployed

def downgrade():
    op.drop_column("products", "wholesale_price")

Output:

TEXT
# Function defined successfully

(2) Risky Migration vs. Safe Migration

Migration Type Security Risk of Table Locking Recommendations
ADD COLUMN Security None Can be executed online
CREATE INDEX Relatively safe Possible Use CREATE INDEX CONCURRENTLY
DROP COLUMN Risk Yes Make sure the code no longer uses it first
ALTER COLUMN TYPE Risk High Phased migration (add new column → migrate data → delete old column)
RENAME COLUMN Danger Medium Rename after enabling dual-write compatibility

6. Log Aggregation

(1) Structured Logs

(1) ▶ Example: Structured Log Configuration

PYTHON
# app/core/logging.py
import logging
import json
from datetime import datetime

class JSONFormatter(logging.Formatter):
    def format(self, record):
        log_entry = {
            "timestamp": datetime.utcnow().isoformat(),
            "level": record.levelname,
            "message": record.getMessage(),
            "module": record.module,
            "function": record.funcName,
            "line": record.lineno,
        }
        # Add request context if available
        if hasattr(record, "request_id"):
            log_entry["request_id"] = record.request_id
        if hasattr(record, "user_id"):
            log_entry["user_id"] = record.user_id
        return json.dumps(log_entry)

# Configure logging
logger = logging.getLogger("pricetracker")
handler = logging.StreamHandler()
handler.setFormatter(JSONFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)

Output:

TEXT
# Function defined successfully

(2) Comparison of Log Aggregation Solutions

Solution Advantages Disadvantages Recommended Scenarios
ELK (Elasticsearch + Logstash + Kibana) Comprehensive features, powerful search capabilities High resource consumption Large-scale projects
Loki+Grafana+Promtail Lightweight, integrated with Grafana Limited search capabilities Small to medium-sized projects
CloudWatch Logs Zero-Maintenance AWS Lockdown AWS Deployment

(2) ▶ Example: Adding Loki to Docker Compose

YAML
# Add to docker-compose.yml
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    volumes:
      - loki_data:/loki

  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/log:/var/log:ro
      - ./docker/promtail.yml:/etc/promtail/config.yml
    depends_on:
      - loki

Output:

TEXT
CONTAINER ID   IMAGE          STATUS         PORTS
abc123         nginx:latest   Up 2 hours     0.0.0.0:80->80/tcp

7. PriceTracker Officially Launches

(1) Project Completion Milestones

100%
gantt
    title PriceTracker Development Timeline
    dateFormat  YYYY-MM-DD
    section Phase 1
    FastAPI Intro           :p1a, 2026-01-01, 1d
    Installation & UV       :p1b, after p1a, 1d
    Path & Query Params     :p1c, after p1b, 1d
    Request Body & Pydantic :p1d, after p1c, 1d
    Response Models         :p1e, after p1d, 1d
    Phase 1 Capstone        :p1f, after p1e, 2d
    
    section Phase 2
    Middleware               :p2a, after p1f, 1d
    Dependency Injection     :p2b, after p2a, 1d
    Database SQLAlchemy      :p2c, after p2b, 2d
    CRUD Operations          :p2d, after p2c, 1d
    Authentication JWT       :p2e, after p2d, 2d
    Phase 2 Capstone         :p2f, after p2e, 2d
    
    section Phase 3
    WebSocket                :p3a, after p2f, 1d
    Celery                   :p3b, after p3a, 2d
    File Upload              :p3c, after p3b, 1d
    Testing                  :p3d, after p3c, 1d
    Caching                  :p3e, after p3d, 1d
    OpenAPI                  :p3f, after p3e, 1d
    
    section Phase 4
    Docker                   :p4a, after p3f, 1d
    Performance              :p4b, after p4a, 1d
    Monitoring               :p4c, after p4b, 1d
    CI/CD                    :p4d, after p4c, 1d
    
    section Phase 5
    Project Design           :p5a, after p4d, 1d
    Project Development      :p5b, after p5a, 2d
    Project Deployment       :p5c, after p5b, 1d

(2) Deployment Verification Checklist

Verification Item Verification Method Passing Criteria
API Availability curl /health {"status": "healthy"}
Front-end Integration Bob Calls the API from the Front End All Endpoints Are Working Properly
Authentication JWT Login + Protected Endpoints Login successful; returns 401 if not authenticated
Permission Free/Pro/Enterprise Rate Limiting Correctly limited according to the plan
WebSocket Connection + Price Feeds Receive Real-Time Updates
Cache Cache Hit Rate for Popular Products > 80%
Monitoring Grafana Dashboard Metrics Displayed Normally
Alert P99 Simulation Spike Alert Trigger Notification
Logs Query Loki Searchable Structured Logs
CI/CD Deployment triggered by tag push Automatic deployment successful

❓ FAQ

Q Does blue-green deployment require twice as many servers?
A Yes, two sets of environments are needed during the switchover. For K8s environments, rolling updates can be used instead, so no additional resources are required.
Q How does Canary release distribute traffic?
A Nginx uses the weight parameter (server v2:8000 weight=1; server v1:8000 weight=9;), while K8s uses the canary Deployment to adjust the number of replicas.
Q What should I do if table locking occurs during a database migration?
A Use CREATE INDEX CONCURRENTLY (to create indexes without locking tables) and avoid executing DDL statements during peak hours. Migrate large tables in batches.
Q What is the difference between structured logs and regular logs?
A Structured logs are in JSON format, with each log entry containing fixed fields (timestamp, level, message, request_id); they can be parsed and searched by machines. Regular logs are human-readable text that is difficult for machines to parse.
Q What should I monitor during the first hour after deployment?
A Monitor the three core metrics on the Grafana dashboard: QPS (is it normal?), P99 latency (has it spiked?), and error rate (is it > 1%). Also check the log aggregator for any ERROR messages.
Q How long does a rollback take?
A A Docker rollback takes about 30 seconds (switching back to the old image version and restarting). Database rollbacks depend on the complexity of the migration; simple column deletions take just a few seconds, while complex migrations may require data repair.

📖 Summary


📝 Exercises

  1. Basic Exercise (Difficulty: ⭐): Create a PriceTracker deployment checklist (5 items each for security, performance, and monitoring) and use it to verify your deployment environment item by item. Hint: Refer to the checklist table in this article.
  2. Advanced Problem (Difficulty ⭐⭐): Implement structured JSON logging (including timestamp, level, message, and request_id); add a logging middleware to inject the request_id into each request; and configure Docker Compose and Loki to aggregate the logs. Hint: JSONFormatter + logging.getLogger("pricetracker")
  3. Challenge (Difficulty: ⭐⭐⭐): Complete deployment process—write a safe migration script (follow the "add-only, no-delete" principle), configure Nginx blue-green deployment, set up Grafana alert rules (P99 > 500 ms + error rate > 5%), and perform canary release verification (first route 10% of traffic to v2, then fully switch over). Hint: CREATE INDEX CONCURRENTLY + Nginx upstream switching

---| Back to Table of Contents

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏