
Mala produkcijska arhitektura ne mora oponašati platformu gigantskih razmjera, ali mora imati jasne granice. Korisna polazna točka sastoji se od Nginx reverznog proxyja na javnom sučelju, aplikacijskih i pozadinskih servisa koji se izvode kao kontejneri na privatnoj mreži te Terraforma koji opisuje poslužitelj, DNS, vatrozid i druge vanjske resurse. Svaki alat ima usku zadaću: Nginx obrađuje dolazni HTTP promet, Docker pakira i povezuje radna opterećenja, a Terraform bilježi kako infrastruktura treba izgledati.
Ta podjela olakšava razumijevanje sustava. Također sprječava uobičajenu pogrešku: tretiranje Compose-a kao alata za uvođenje resursa u oblak ili Terraforma kao sustava za primjenu aplikacija. Oni mogu raditi zajedno, ali ne smiju tiho preuzimati vlasništvo nad istim resursom.
Topologija malog stoga
Jedan poslužitelj može ugostiti Nginx, aplikacijski kontejner, pozadinski radni proces (worker) i bazu podataka za skromnije opterećenje. Izložite samo priključke 80 i 443 na glavnom poslužitelju. Aplikaciju objavite na lokalnoj petlji ili je u potpunosti zadržite na Dockerovoj privatnoj mreži, tako da Nginx uvijek pregledava javnu putanju zahtjeva.
Internet -> Nginx (80/443) -> web:8000
-> api:8080
-> worker (nema javnog priključka)
|
baza podataka
Compose kreira zadanu premoštenu mrežu i dodjeljuje servisima DNS nazive koji odgovaraju njihovim ključevima servisa. Aplikacija bi se trebala povezivati na database:5432, a ne na IP adresu kontejnera jer se IP adrese mogu promijeniti kada se servis ponovno kreira. Definirajte drugu, izričito imenovanu mrežu kada trebate odvojiti javni proxy od internih servisa i nemojte objavljivati priključak baze podataka osim ako to operativni zahtjev izričito opravdava.
Učinite Nginx granicu eksplicitnom
Sljedeći blok poslužitelja namjerno je konzervativan. Naziv uzvodnog poslužitelja (upstream) može se razriješiti u Compose servis kada se Nginx izvodi u istoj Docker mreži ili može biti slušatelj na lokalnoj petlji kada se Nginx izvodi na glavnom poslužitelju.
upstream app {
server web:8000;
keepalive 16;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/tls/fullchain.pem;
ssl_certificate_key /etc/nginx/tls/privkey.pem;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
}
}
Varijabla $proxy_add_x_forwarded_for čuva lanac adresa koji je Nginx zabilježio; nemojte naslijepo vjerovati proizvoljnim zaglavljima prosljeđivanja od nepouzdanog javnog klijenta. Potvrdite da aplikacija razumije postavke sheme i domaćina svjesne proxyja prije nego što omogućite sigurnu logiku kolačića ili preusmjeravanja. Razlika između proxy_pass http://app; i proxy_pass http://app/; također je važna: dodavanje URI-ja može zamijeniti prefiks lokacije i promijeniti putanju primljenu na uzvodnoj strani. Testirajte reprezentativnu API putanju nakon svake promjene proxyja.
Pokrenite nginx -t prije ponovnog učitavanja i učinite ponovno učitavanje vidljivim. Konfiguracija koja je sintaksno ispravna još uvijek može usmjeravati na pogrešan servis, izložiti zdravstvenu krajnju točku (health endpoint) ili vratiti petlju preusmjeravanja. Čuvajte zapise pristupa i pogrešaka (access i error logove) dovoljno dugo da možete povezati vanjski 502 s zdravljem kontejnera i zapisima aplikacije.
Docker i Compose: pakirajte izvođenje, a ne pravila
Koristite fiksnu oznaku slike ili sažetak (digest), izgradnju u više koraka (multi-stage build), korisnika izvođenja bez korijenskih ovlasti (non-root) i provjeru ispravnosti koja testira smislenu granicu ovisnosti. Pravilo restart: unless-stopped može se oporaviti od izlaza procesa, ali to nije nadzor i ne može popraviti lošu migraciju ili iscrpljen disk. Pohranite podatke baze podataka u imenovani volumen i sigurnosno ih kopirajte neovisno o životnom ciklusu kontejnera.
Mali Compose ulomak može izgledati ovako:
services:
web:
image: registry.example.com/shop-web:2026.08.25
expose:
- "8000"
networks: [edge, internal]
secrets:
- database_password
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 3s
retries: 3
database:
image: postgres:16
networks: [internal]
volumes:
- postgres_data:/var/lib/postgresql/data
secrets:
- database_password
networks:
edge:
internal:
internal: true
volumes:
postgres_data:
secrets:
database_password:
file: ./secrets/database_password.txt
Ovaj primjer prikazuje namjeru, a ne potpunu produkcijsku politiku. Docker Compose odobrava tajnu samo servisima koji je izričito zatraže i montira je pod /run/secrets/; to je sigurnije nego stavljanje vjerodajnica u sliku ili njihovo ležerno umetanje u zapisnike. Zaštitite izvornu datoteku, izuzmite je iz Gita, rotirajte je i razmislite o upravljanom spremištu tajni kada više od jednog poslužitelja ili okruženja treba tu vrijednost. Nikada ne tretirajte base64 kodiranje kao enkripciju.
Terraform resursi i stanje (state)
Terraform je prikladan za resurse izvan životnog ciklusa aplikacije: poslužitelj, mrežna pravila, DNS zapise, spremnike objektne pohrane i elemente nadzora. Držite te deklaracije u korijenskom modulu s malim višekratno iskoristivim modulima samo tamo gdje postoji stvarno ponavljanje. Koristite varijable za unose specifične za okruženje i izlaze za vrijednosti koje sustav za primjenu mora koristiti. Pregledajte plan prije njegove primjene; nepripremljeno uništenje ili zamjena operativni je događaj, a ne rutinska naredba.
terraform {
required_version = ">= 1.6.0"
backend "s3" {
bucket = "example-terraform-state"
key = "small-stack/prod.tfstate"
region = "eu-central-1"
dynamodb_table = "example-terraform-locks"
encrypt = true
}
}
resource "example_firewall_rule" "https" {
name = "allow-https"
port = 443
cidrs = ["0.0.0.0/0"]
}
output "public_address" {
value = example_server.app.public_address
}
Resurs specifičan za davatelja usluga je ilustrativan, ali pravilo stanja nije: Terraform koristi stanje za mapiranje deklariranih instanci resursa na stvarne objekte. Lokalnu datoteku terraform.tfstate lako je započeti, ali je i lako izgubiti ili izložiti. Koristite udaljenu pozadinu s kontrolom pristupa, enkripcijom i zaključavanjem za dijeljena ili važna okruženja te držite stanje izvan kontrole verzija jer može sadržavati osjetljive vrijednosti. Nemojte ručno uređivati JSON; koristite Terraformove naredbe za stanje kada je potrebno pregledati ili premjestiti vezu.
Izbori primjene i načini kvarova
Jedan poslužitelj i Compose jednostavni su za rad, jeftini i laki za pregled putem SSH-a. Oni također stvaraju domenu kvara: ažuriranje jezgre, popunjeni disk ili ispad poslužitelja ruše svaku uslugu. Premještanje baze podataka na upravljanu uslugu može poboljšati mogućnosti sigurnosnog kopiranja i prebacivanja u slučaju kvara, ali dodaje mrežnu ovisnost i trošak. Kubernetes može donijeti pogodnosti raspoređivanja i usklađivanja u većem mjerilu, ali uvodi kontrolnu ravninu i operativnu površinu koju usluga s dva kontejnera možda ne treba.
Bez obzira koju granicu odabrali, vježbajte kvarove koji su važni: isteklu potvrdu (certifikat), neuspjelo preuzimanje slike, volumen baze podataka bez slobodnog prostora, kontejner koji izvještava da je zdrav dok mu je ovisnost prekinuta, DNS zapis koji upućuje na stari poslužitelj i zaključavanje Terraform stanja koje je ostalo nakon prekinutog izvođenja. Čuvajte slike za povratak (rollback), testirane sigurnosne kopije, provjeru konfiguracije i kratak priručnik za oporavak. Stog je mali samo onda kada je njegovo ponašanje u slučaju kvara shvaćeno.
Izvori: Dokumentacija Nginx proxy modula, Docker Compose umrežavanje, Docker Compose tajne, Terraform stanje i OWASP vodič za upravljanje tajnama.
Povezana područja
Savjetodavna područja vezana uz ovu temu
Ova su područja rada usklađena s temom članka i daju čišći prijelaz od edukativnog sadržaja do konkretne implementacije.
Nastavite čitati
Povezani članci
Prvo po zajedničkim kategorijama, a zatim po najjačem preklapanju u tagovima.


