-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
147 lines (138 loc) · 3.78 KB
/
Copy pathdocker-compose.yml
File metadata and controls
147 lines (138 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
version: '3.8'
# Lab 08: Secure Multi-Tier Architecture with Docker Compose
# This demonstrates production-ready network segmentation
networks:
# Public network - Exposed to internet
frontend:
driver: bridge
# Application network - Internal communication
backend:
driver: bridge
# Database network - Completely isolated
database:
driver: bridge
internal: true # No external gateway
services:
# Web Tier - Public facing
web:
image: nginx:alpine
container_name: web
networks:
- frontend
- backend # Can reach app tier
ports:
- "8080:80"
volumes:
- ./configs/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- app
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
interval: 30s
timeout: 3s
retries: 3
labels:
- "com.docker.security.tier=frontend"
- "com.docker.security.exposure=public"
# Application Tier - Gateway between web and database
app:
build:
context: ./app
dockerfile: Dockerfile
container_name: app
networks:
- backend # Receives requests from web
- database # Can reach database
environment:
- DATABASE_URL=postgresql://postgres:secret@db:5432/appdb
- PORT=5000
- SERVICE_NAME=api
depends_on:
- db
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:5000/health"]
interval: 30s
timeout: 3s
retries: 3
labels:
- "com.docker.security.tier=application"
- "com.docker.security.exposure=internal"
# Security: Run as non-root user
user: "1000:1000"
# Security: Read-only root filesystem
read_only: true
tmpfs:
- /tmp
- /app/.cache
# Database Tier - Completely isolated
db:
image: postgres:15-alpine
container_name: db
networks:
- database # Internal network only
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=appdb
- POSTGRES_USER=postgres
volumes:
- db-data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 30s
timeout: 5s
retries: 5
labels:
- "com.docker.security.tier=database"
- "com.docker.security.exposure=none"
# Security: Run as postgres user (non-root)
user: "postgres"
# Security: Limit resources
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
volumes:
db-data:
driver: local
# Security Notes:
#
# 1. Network Segmentation:
# - Web tier: Can reach app tier only
# - App tier: Gateway with access to both web and db
# - DB tier: On internal network, cannot be reached from outside
#
# 2. Port Exposure:
# - Only port 8080 exposed to host (web tier)
# - App tier: No ports exposed (internal only)
# - DB tier: No ports exposed, internal network prevents exposure
#
# 3. Defense in Depth:
# - Network isolation (multiple networks)
# - Internal network for database (no external gateway)
# - Health checks for automatic recovery
# - Resource limits to prevent DoS
# - Non-root users
# - Read-only filesystems where possible
#
# 4. Monitoring:
# - Labels for easy filtering
# - Health checks for status
# - Restart policies for availability
#
# Usage:
# docker-compose up -d
# docker-compose ps
# docker-compose logs -f app
# docker-compose down
#
# Verify Security:
# docker network inspect 08-network-security_database
# docker exec web nc -zv db 5432 # Should fail (no route)
# docker exec app nc -zv db 5432 # Should succeed (authorized)