嗨嗨!大家好!歡迎來到 Rust 三十天挑戰的第三十天,也是我們這趟學習旅程的最終章!
三十天的 Rust 學習之旅即將圓滿落幕!從第一天寫下 "Hello, world!" 到今天完成一個功能完整的部落格後端 API,我們一起走過了從零基礎到實戰應用的完整歷程。
今天,我們將為這個專案加上最後的部署配置,讓它真正可以在生產環境中運行,並回顧這一路上的收穫與成長。
現代軟體開發離不開容器化技術。Docker 讓我們可以將應用程式及其運行環境打包成一個輕量、可移植的容器,確保在任何地方都能穩定運行。
# Multi-stage build for Rust backend
FROM rustlang/rust:nightly-alpine AS builder
# Install build dependencies (cached layer)
RUN apk add --no-cache musl-dev openssl-dev openssl-libs-static pkgconfig curl
# Create app directory
WORKDIR /app
# Copy manifest files first (for dependency caching)
COPY Cargo.toml Cargo.lock ./
COPY migration/Cargo.toml migration/Cargo.lock ./migration/
# Create dummy source files to cache dependencies
RUN mkdir -p src migration/src && \
echo "fn main() {}" > src/main.rs && \
echo "fn main() {}" > migration/src/main.rs
# Build dependencies (this layer will be cached)
RUN cargo build --release
RUN rm -rf src migration/src
# Copy real source code
COPY src ./src
COPY migration/src ./migration/src
# Build the application (only app code, dependencies are cached)
RUN touch src/main.rs migration/src/main.rs && \
cargo build --release
# Runtime stage
FROM alpine:3.19
# Install runtime dependencies
RUN apk add --no-cache ca-certificates openssl wget
# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
# Create app directory
WORKDIR /app
# Copy the binary from builder stage
COPY --from=builder /app/target/release/blog .
# Change ownership to non-root user
RUN chown -R appuser:appgroup /app
USER appuser
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
# Start the application
CMD ["./blog"]
# Rust build artifacts
target/
**/*.rs.bk
# IDE files
.vscode/
.idea/
*.swp
*.swo
# Environment files
.env*
# Git
.git/
.gitignore
# Documentation
README.md
*.md
# Docker files
Dockerfile*
docker-compose*
.dockerignore
# OS files
.DS_Store
Thumbs.db
# Logs
*.log
為了簡化開發與部署,我們建立一個完整的 Docker Compose 配置:
services:
# PostgreSQL Database
postgres:
image: postgres:16-alpine
container_name: blog-postgres
environment:
POSTGRES_DB: personal_blog
POSTGRES_USER: blog_user
POSTGRES_PASSWORD: blog_password
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- blog-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U blog_user -d personal_blog"]
interval: 10s
timeout: 5s
retries: 5
command: >
postgres
-c log_statement=all
-c log_min_duration_statement=0
-c shared_preload_libraries=pg_stat_statements
# Rust Backend
backend:
build:
context: ./blog-backend
dockerfile: Dockerfile
container_name: blog-backend
env_file:
- ./blog-backend/.env
environment:
- HOST=0.0.0.0
- PORT=3000
- PROTOCOL=http
- BLOG_NAME=我的個人技術部落格
- BLOG_DESCRIPTION=分享程式設計學習心得與生活感悟
- BLOG_AUTHOR=哈囉你好嗎
- DATABASE_URL=postgres://blog_user:blog_password@postgres:5432/personal_blog
- DATABASE_MAX_CONNECTIONS=10
- RUST_LOG=info
- CORS_ORIGIN=http://localhost:3000,http://127.0.0.1:3000,http://localhost:5173,http://localhost
- JWT_SECRET=blog_secret_key
- JWT_EXPIRY_HOURS=24
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=admin123
- CORS_ORIGINS=http://localhost,http://localhost:80,http://localhost:3000,http://localhost:5173,http://localhost:5174,http://127.0.0.1:3000
- ENVIRONMENT=production
ports:
- "3000:3000"
depends_on:
postgres:
condition: service_healthy
networks:
- blog-network
restart: unless-stopped
healthcheck:
test: ["CMD", "sh", "-c", "wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
# React Frontend
frontend:
build:
context: ./blog-frontend
dockerfile: Dockerfile
container_name: blog-frontend
ports:
- "80:80"
depends_on:
backend:
condition: service_healthy
networks:
- blog-network
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/"]
interval: 30s
timeout: 10s
retries: 3
volumes:
postgres_data:
external: true
name: blog-backend_postgres_data
networks:
blog-network:
driver: bridge
💡 前端小提示!!!
這個前端是我用 Lovable來簡單生成的,大家也可以來生成自己喜歡的樣式歐!!
他每天都有一定的免費額度,大家一起來做自己喜歡的Blog吧!!!
建立 .env.example
作為範本:
HOST=0.0.0.0
PORT=3000
PROTOCOL=http
# 部落格資訊
BLOG_NAME=我的個人技術部落格
BLOG_DESCRIPTION=分享程式設計學習心得與生活感悟
BLOG_AUTHOR=哈囉你好嗎
# 🆕 資料庫設定
DATABASE_URL=postgres://blog_user:blog_password@localhost:5432/personal_blog
DATABASE_MAX_CONNECTIONS=10
# 日誌設定
RUST_LOG=info
CORS_ORIGIN=http://localhost:3000,http://127.0.0.1:3000
# JWT 配置
JWT_SECRET=blog_secret_key
JWT_EXPIRY_HOURS=24
# 管理員帳號
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123
# CORS 配置
CORS_ORIGINS=http://localhost:3000,https://yourdomain.com
ENVIRONMENT=development
第一週:Rust 基礎奠基
第二週:核心概念深化
第三週:現代化開發技術
第四週:實戰項目開發
我們成功建構的部落格後端具備:
核心功能:
技術特色:
我們成功完成了:
技術成就:
學習里程碑:
程式設計是一個永無止境的學習過程。Rust 雖然有一定的學習門檻,但它提供了獨特的價值:
記憶體安全 + 高效能 + 現代語言特性
今天就先到此結束拉!主要的內容大致上都講得差不多了,我們明天來不務正業一下,講個我覺得很有趣,看起來很瞎趴的東西 TUI (terminal UI)!!
有興趣的我們明天見!!