# Docker 환경 설정

> **최종 갱신**: 2026-02-27
> **Docker Compose**: 7 서비스, `samnet` 브리지 네트워크

---

## 1. 서비스 구성

| 서비스 | 이미지 | 포트 | 역할 |
|--------|--------|------|------|
| nginx | nginx:latest | 80, 443 | 리버스 프록시, SSL 종료 |
| api | php:8.4-fpm (custom) | 9000 | Laravel REST API |
| mng | php:8.4-fpm (custom) | 9000 | Laravel 관리자 패널 |
| react | node:20-alpine | 3000 | Next.js 프론트엔드 |
| design | node:20-alpine | 3002 | Vite 디자인 시스템 |
| php73 | php:7.3-fpm (custom) | 9000 | 레거시 5130 |
| mysql | mysql:8.0 | 3306 | 데이터베이스 |

---

## 2. 도메인 매핑

| 도메인 | 대상 | SSL | 비고 |
|--------|------|-----|------|
| api.sam.kr | api:9000 (FastCGI) | O | 대형 JSON 버퍼링 |
| mng.sam.kr | mng:9000 (FastCGI) | O | 관리자 패널 |
| admin.sam.kr | mng:9000 (FastCGI) | O | mng 별칭 |
| dev.sam.kr | react:3000 (Proxy) | O | HMR WebSocket 지원 |
| design.sam.kr | design:3002 (Proxy) | O | HMR WebSocket 지원 |
| 5130.sam.kr | php73:9000 (FastCGI) | O | 레거시 |
| dev.haisa.kr | host.docker.internal:8888 | X | 외부 프록시 |

---

## 3. 네트워크 구조

```
[호스트]
  127.0.0.1:80  ─→ nginx:80
  127.0.0.1:443 ─→ nginx:443
  127.0.0.1:3306 ─→ mysql:3306

[samnet 내부]
  nginx ──FastCGI──→ api:9000
  nginx ──FastCGI──→ mng:9000
  nginx ──FastCGI──→ php73:9000
  nginx ──Proxy────→ react:3000
  nginx ──Proxy────→ design:3002
  api/mng ─────────→ mysql:3306
```

- 모든 포트는 `127.0.0.1` 바인딩 (외부 접근 차단)
- `samnet` 브리지 네트워크로 컨테이너간 통신

---

## 4. Dockerfile 요약

### api / mng (PHP 8.4-FPM)
```
Base: php:8.4-fpm
Extensions: zip, mysqli, pdo, pdo_mysql, intl
Packages: git, unzip, nginx, supervisor
Composer: 2 (멀티스테이지 빌드)
실행: Supervisor (nginx + php-fpm 동시)
Entrypoint: storage:link, 권한 설정
```

### react (Node 20)
```
Base: node:20-alpine
추가: chromium, font-noto-cjk (Puppeteer 지원)
환경: PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
실행: npm run dev (포트 3000)
```

### design (Node 20)
```
Base: node:20-alpine
실행: npm run dev (포트 3002)
```

### php73 (PHP 7.3-FPM)
```
Base: php:7.3-fpm
Extensions: gd, mbstring
설정: short_open_tag=On, display_errors=On
```

---

## 5. 볼륨 마운팅

### 주요 볼륨
- **db_data** (Named Volume): MySQL 데이터 영속성
- **앱 소스코드**: 호스트 → 컨테이너 직접 마운트
- **API 스토리지**: mng가 api의 storage/app/tenants 공유 마운트

### Nginx 설정
- `docker/nginx/nginx.conf` → `/etc/nginx/nginx.conf` (RO)
- `docker/nginx/ssl/` → `/etc/nginx/ssl/` (RO)

### PHP 설정
- `uploads.ini`: file_uploads=On, memory_limit=256M, upload_max=20M, post_max=100M
- `supervisord.conf`: php-fpm + nginx 동시 실행 (nodaemon)

---

## 6. MySQL 설정

### my.cnf
```ini
innodb_buffer_pool_size = 256M
innodb_log_buffer_size = 16M
sort_buffer_size = 4M
tmp_table_size = 64M
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
log_bin_trust_function_creators = 1
```

### 초기화 (init.sql)
```sql
CREATE DATABASE samdb;      -- API/MNG용
CREATE DATABASE chandj;     -- 레거시 5130용
CREATE USER samuser@'%';
GRANT ALL ON samdb.*, chandj.*;
```

---

## 7. Nginx 보안 필터 (API)

```
차단 패턴:
- 경로 트래버설: \.\.\/|\.\.\\|etc\/passwd
- 민감 파일: \.env|\.git|\.htaccess|\.sql|@fs\/
- 악성 User-Agent: sqlmap, nikto, nmap, masscan, metasploit, nessus
응답: 403 Forbidden
```

### 업로드 제한
| 대상 | 최대 크기 |
|------|----------|
| Nginx (기본) | 100M |
| API | 100M |
| MNG | 210M |

### 정적 자산 캐싱
- 대상: js, css, png, jpg, gif, svg, ico, woff2, ttf
- 만료: 30일, Cache-Control: public

---

## 8. CI/CD (Jenkins)

### 파이프라인 요약

| 저장소 | 트리거 브랜치 | 배포 서버 | 특징 |
|--------|-------------|----------|------|
| api | main, develop | 211.117.60.189 | Release 디렉토리, 자동 마이그레이션, 자동 롤백 |
| react | main, develop | 114.203.209.83 (dev), 211.117.60.189 (stage/prod) | PM2 프로세스 관리 |
| mng | main | 211.117.60.189 | npm build + PHP-FPM 재로드 |
| sales | main | 211.117.60.189 | 정적 사이트 rsync만 |

### 배포 전략 (api/mng)
```
1. releases/{RELEASE_ID} 디렉토리 생성 (타임스탬프)
2. rsync 코드 복사 (.git, .env, storage 제외)
3. composer install + npm install
4. php artisan migrate --force
5. config/route/view 캐시 생성
6. /current symlink → 최신 릴리스
7. PHP-FPM 재로드
8. 이전 릴리스 정리 (최근 6개만 유지)
```

### 롤백: 실패 시 이전 릴리스로 symlink 자동 변경
### 알림: Slack (빌드 시작/성공/실패)

---

## 9. 배포 환경 요약

| 환경 | 도메인 | IP | 배포 방식 |
|------|--------|----|----------|
| 로컬 | *.sam.kr | localhost | Docker Compose |
| 개발 | codebridge-x.com | 114.203.209.83 | Jenkins (react only) |
| 스테이지 | TBD | 211.117.60.189 | Jenkins (api, mng, react) |
| 운영 | TBD | 211.117.60.189 | Jenkins (승인 필요, 비활성) |

---

## 10. 디렉토리 구조

```
docker/
├── docker-compose.yml         전체 서비스 정의
├── .env                       프로젝트명 설정
├── nginx/
│   ├── nginx.conf             메인 설정 (7개 virtual host)
│   └── ssl/                   SSL 인증서
├── api/
│   ├── Dockerfile
│   ├── nginx.conf
│   ├── supervisord.conf
│   ├── entrypoint.sh
│   └── uploads.ini
├── mng/
│   ├── Dockerfile
│   ├── nginx.conf
│   ├── supervisord.conf
│   ├── entrypoint.sh
│   └── uploads.ini
├── react/
│   ├── Dockerfile
│   └── entrypoint.sh
├── design/
│   ├── Dockerfile
│   └── entrypoint.sh
├── 5130/
│   ├── Dockerfile
│   ├── nginx.conf
│   ├── supervisord.conf
│   ├── entrypoint.sh
│   └── uploads.ini
└── mysql/
    ├── init.sql
    ├── my.cnf
    └── database.sql
```