Step 03: Docker 컨테이너화 및 배포
0 studying now
advanced 60 min
Docker 컨테이너화 및 배포
Docker로 애플리케이션을 패키징하고 배포합니다.
Execute this step
Run from project root:
docker-compose upStep 3: Docker 컨테이너화 및 배포
학습 목표
- Rust 애플리케이션을 Docker 이미지로 만들기
- docker-compose로 전체 스택 실행하기
- 프로덕션 환경 설정하기
Dockerfile 작성
Dockerfile (멀티 스테이지 빌드):
1# 빌드 스테이지 2FROM rust:1.75 as builder 3 4WORKDIR /app 5 6# 의존성만 먼저 빌드 (캐싱) 7COPY Cargo.toml Cargo.lock ./ 8RUN mkdir src && \ 9 echo "fn main() {}" > src/main.rs && \ 10 cargo build --release && \ 11 rm -rf src 12 13# 실제 소스 빌드 14COPY . . 15RUN touch src/main.rs && \ 16 cargo build --release --bin web 17 18# 런타임 스테이지 19FROM debian:bookworm-slim 20 21RUN apt-get update && \ 22 apt-get install -y libpq5 ca-certificates && \ 23 rm -rf /var/lib/apt/lists/* 24 25WORKDIR /app 26 27COPY /app/target/release/web /app/web 28COPY /app/.env /app/.env 29 30EXPOSE 8080 31 32CMD ["./web"]
docker-compose.yml
1version: '3.8' 2 3services: 4 postgres: 5 image: postgres:15 6 container_name: library-postgres 7 environment: 8 POSTGRES_USER: postgres 9 POSTGRES_PASSWORD: password 10 POSTGRES_DB: library_db 11 ports: 12 - "5432:5432" 13 volumes: 14 - postgres_data:/var/lib/postgresql/data 15 healthcheck: 16 test: ["CMD-SHELL", "pg_isready -U postgres"] 17 interval: 10s 18 timeout: 5s 19 retries: 5 20 21 web: 22 build: . 23 container_name: library-web 24 environment: 25 DATABASE_URL: postgresql://postgres:password@postgres:5432/library_db 26 JWT_SECRET: your-secret-key-change-in-production 27 RUST_LOG: info 28 ports: 29 - "8080:8080" 30 depends_on: 31 postgres: 32 condition: service_healthy 33 command: > 34 sh -c "sleep 5 && ./web" 35 36volumes: 37 postgres_data:
.dockerignore
1target/ 2.git/ 3.env 4*.log 5Dockerfile 6docker-compose.yml 7README.md
프로덕션 환경 변수
.env.production:
1DATABASE_URL=postgresql://user:password@db-host:5432/library_db 2JWT_SECRET=your-very-secret-key-min-32-characters 3RUST_LOG=info 4BIND_ADDRESS=0.0.0.0:8080
빌드 및 실행
로컬 빌드
1# 이미지 빌드 2docker build -t library-manager . 3 4# 컨테이너 실행 5docker run -p 8080:8080 --env-file .env library-manager
docker-compose 사용
1# 전체 스택 시작 2docker-compose up -d 3 4# 로그 확인 5docker-compose logs -f web 6 7# 마이그레이션 실행 8docker-compose exec web sqlx migrate run 9 10# 종료 11docker-compose down 12 13# 볼륨까지 삭제 14docker-compose down -v
헬스 체크 추가
src/bin/web.rs에 헬스 체크 개선:
1#[derive(Serialize)] 2struct HealthResponse { 3 status: String, 4 database: String, 5 version: String, 6} 7 8async fn health_check(data: web::Data<AppState>) -> HttpResponse { 9 let db_status = match data.db.check_connection().await { 10 Ok(_) => "healthy", 11 Err(_) => "unhealthy", 12 }; 13 14 HttpResponse::Ok().json(HealthResponse { 15 status: "ok".to_string(), 16 database: db_status.to_string(), 17 version: env!("CARGO_PKG_VERSION").to_string(), 18 }) 19}
src/db.rs에 추가:
1impl Database { 2 pub async fn check_connection(&self) -> Result<()> { 3 sqlx::query("SELECT 1") 4 .execute(&self.pool) 5 .await 6 .map(|_| ()) 7 .map_err(|e| LibraryError::DatabaseError(e.to_string())) 8 } 9}
프로덕션 최적화
1. 로깅 설정
Cargo.toml에 추가:
[dependencies] env_logger = "0.11" log = "0.4"
src/bin/web.rs:
1use log::{info, error}; 2 3#[actix_web::main] 4async fn main() -> std::io::Result<()> { 5 env_logger::init(); 6 7 info!("Starting library management system"); 8 9 // ... 10 11 info!("Server listening on http://{}:{}", host, port); 12 13 HttpServer::new(move || { 14 App::new() 15 .wrap(actix_web::middleware::Logger::default()) 16 // ... 17 }) 18 .bind((host, port))? 19 .run() 20 .await 21}
2. CORS 설정
[dependencies] actix-cors = "0.7"
1use actix_cors::Cors; 2 3HttpServer::new(move || { 4 let cors = Cors::default() 5 .allowed_origin("https://your-frontend.com") 6 .allowed_methods(vec!["GET", "POST", "PUT", "DELETE"]) 7 .allowed_headers(vec![header::AUTHORIZATION, header::CONTENT_TYPE]) 8 .max_age(3600); 9 10 App::new() 11 .wrap(cors) 12 .wrap(actix_web::middleware::Logger::default()) 13 // ... 14})
3. Rate Limiting
[dependencies] actix-limitation = "0.5"
배포
AWS ECS 배포 예시
- ECR에 이미지 푸시:
1# ECR 로그인 2aws ecr get-login-password --region us-east-1 | \ 3 docker login --username AWS --password-stdin <account-id>.dkr.ecr.us-east-1.amazonaws.com 4 5# 이미지 태그 6docker tag library-manager:latest <account-id>.dkr.ecr.us-east-1.amazonaws.com/library-manager:latest 7 8# 푸시 9docker push <account-id>.dkr.ecr.us-east-1.amazonaws.com/library-manager:latest
-
RDS PostgreSQL 설정
-
ECS Task Definition 생성
-
ECS Service 배포
간단한 서버 배포
1# 서버에서 2git clone <repo> 3cd library-manager 4docker-compose -f docker-compose.prod.yml up -d 5 6# Nginx 리버스 프록시 설정 7# /etc/nginx/sites-available/library 8server { 9 listen 80; 10 server_name library.example.com; 11 12 location / { 13 proxy_pass http://localhost:8080; 14 proxy_set_header Host $host; 15 proxy_set_header X-Real-IP $remote_addr; 16 } 17}
모니터링
1# docker-compose.monitoring.yml 2services: 3 prometheus: 4 image: prom/prometheus 5 ports: 6 - "9090:9090" 7 volumes: 8 - ./prometheus.yml:/etc/prometheus/prometheus.yml 9 10 grafana: 11 image: grafana/grafana 12 ports: 13 - "3000:3000" 14 environment: 15 - GF_SECURITY_ADMIN_PASSWORD=admin
체크리스트
- [ ] Dockerfile을 작성했습니다
- [ ] docker-compose로 전체 스택을 실행했습니다
- [ ] 멀티 스테이지 빌드로 이미지 크기를 최적화했습니다
- [ ] 헬스 체크를 구현했습니다
- [ ] 프로덕션 환경 변수를 설정했습니다
- [ ] 로깅을 추가했습니다
축하합니다! 🎉
초급부터 고급까지 Rust 도서 관리 시스템을 완성했습니다!
배운 내용:
- ✅ Rust 기초 문법 (소유권, 차용, 구조체, 열거형)
- ✅ 비동기 프로그래밍 (async/await, tokio)
- ✅ 웹 개발 (Actix-web, REST API)
- ✅ 데이터베이스 (PostgreSQL, SQLx)
- ✅ 인증/인가 (JWT, bcrypt)
- ✅ 배포 (Docker, docker-compose)
이제 실전 Rust 프로젝트를 만들 준비가 되었습니다!