🐳 Šta je Docker?
Softverski inženjer često napravi aplikaciju i kada je želi pustiti u produkciju ili ustupiti kolegi, javi se klasični problem: "Kod mene na laptopu aplikacija radi savršeno!" Razlog padova na drugim sistemima su različiti operativni sistemi, pogrešne verzije instaliranog softvera (.NET 6 vs .NET 8), nedostatak sistemskih varijabli i slično.
Docker je platforma koja rješava ovaj problem koristeći kontejnerizaciju. Slično kao što teretni brodovi koriste univerzalne brodske kontejnere bez obzira šta je u njima (televizori, igračke ili auti), Docker vam omogućava da "upakujete" vašu aplikaciju i apsolutno sve njene zavisnosti u jedan standardizirani Docker Kontejner koji će raditi identično na svakom kompjuteru na planeti.
⚖️ Virtualne Mašine (VM) protiv Dokera
U prošlosti smo ovaj problem rješavali tako što bismo stvorili cijeli lažni kompjuter ("Virtualnu Mašinu") unutar našeg pravog kompjutera. To je bilo preskupo i presporo.
Tradicionalne Virtualne Mašine
+ RAM (4GB)
+ RAM (4GB)
Svaka aplikacija nosi ogroman teret (i licencu) cijelog lažnog operativnog sistema (Guest OS). Pokretanje traje minutama i proždire RAM memoriju.
Docker Kontejneri
Kontejneri nemaju Guest OS! Oni "posuđuju" jezgro matičnog OS-a putem Docker Engine-a. Pokreću se za samo nekoliko milisekundi i zauzimaju jedva par megabajta.
💻 Rječnik i Osnovne Komande
- Image (Slika): Read-only nacrt (klasa) sistema. Kao instalacioni CD koji ne možete mijenjati. Iz njega se kreiraju kontejneri.
- Container (Kontejner): Pokrenuta instanca iz Image-a (objekat). Potpuno izolovan proces.
- Docker Hub: Globalna prodavnica besplatnih gotovih Image-a (zamisli AppStore, ali za SQL Servere, Linuxe i Nginxe).
# 1. Prikazuje sve preuzete "Instalacione CDove" na kompjuteru
docker images
# 2. Skini službeni Nginx server Image s interneta
docker pull nginx
# 3. Upali ga u pozadini! (Nginx sada vrti kao Kontejner)
docker run --name moj_web -d -p 8080:80 nginx
# 4. Prikazuje LISTU SVIH AKTIVNIH kontejnera (Traži njegov ID ovdje!)
docker ps
# 5. Zaustavi i Trajno obriši taj kontejner iz memorije i života
docker stop moj_web
docker rm moj_web
Sjeciranje docker run komande
Svaki put kada palimo server, koristimo magičnu "run" komandu sa dva ključna parametra bez kojih bi sve bilo zaključano u crnoj kutiji:
-d(Detached mode): Pokreće kontejner "u pozadini" (u mraku). Da nismo stavili-d, PowerShell terminal bi se zaključao ispisujući Nginx logove zauvijek, i ne bi mogli kucati druge komande dok ga ne ugasimo sa uCtrl+C. Kucanjem-d, Docker nam samo vrati ID kontejnera i terminal je opet naš.-p 8080:80(Port Mapping - Skretnica): Kontejner je kao sef na dnu okeana. Čak i ako web server unutra sluša na portu 80, on je zaključan i ljevak i desni od zida Windowsa. Komanda-p MOJ_VANJSKI_PORT : NJEGOV_UNUTRASNJI_PORTdoslovno probuši rupu kroz Docker zid i kaže: "Kada moj lokalni Chrome posjetilocalhost:8080, proslijedi taj upit direktno u kontejner na njegov port80". Dva Nginxa mogu raditi unutra na portu 80, ali ih vani mapiramo na8081:80i8082:80.
🌐 Praktični primjer: Nginx Web Server
Nginx je jedan od najpopularnijih web servera na svijetu. Umjesto da instalirate IIS ili Apache na vaš Windows, možete pokrenuti kompletni Nginx web server jednom komandom i poslužiti vaše HTML/CSS/JS fajlove direktno iz lokalnog foldera.
docker run --name moj-nginx-test -p 8085:80 -v C:\projekti\web:/usr/share/nginx/html:ro -d nginx
Objašnjenje svakog dijela komande
--name moj-nginx-test– Daje kontejneru čitljivo ime umjesto nasumičnog Docker ID-a. Koristi se zadocker stop,docker rmitd.-p 8085:80– Mapira port 8085 na vašem PC-ju na port 80 unutar kontejnera. Otvoritelocalhost:8085u browseru i vidjet ćete vaš sajt.-v C:\projekti\web:/usr/share/nginx/html:ro– Bind Mount: Vaš lokalni folderC:\projekti\webse mapira u Nginx-ov interni folder za HTML fajlove. Sufiks:ro(read-only) znači da kontejner može samo čitati fajlove, ali ih ne može mijenjati – dodatna sigurnost!-d– Detached mode, pokreće kontejner u pozadini.nginx– Ime Image-a sa Docker Hub-a. Docker automatski skida najnoviju verziju ako već nije preuzeta.
Rezultat: Svaka promjena u C:\projekti\web\index.html se odmah vidi u
browseru na localhost:8085 bez restartanja kontejnera!
📄 Nginx kroz Docker Compose
Umjesto da pamtite dugih komandi, isto možete definisati kroz docker-compose.yml fajl u root
folderu vašeg web projekta:
version: '3.8'
services:
moj-web-server: # Proizvoljno ime servisa
image: nginx:latest # Koristi najnoviji Nginx Image
container_name: nginx-lokalni-test # Fiksno ime kontejnera
ports:
- "8080:80" # Mapiranje porta (localhost:8080 → kontejner:80)
volumes:
- ./:/usr/share/nginx/html:ro # Trenutni folder (./) se mapira u Nginx HTML root
restart: always # Automatski restartuj ako padne
Šta znači ./ u volumes?
Oznaka ./ znači "trenutni direktorij" – dakle folder u kojem se nalazi vaš
docker-compose.yml fajl.
Ako je vaš docker-compose.yml u folderu C:\projekti\web\, onda Docker
mapira
C:\projekti\web\ u Nginx-ov HTML folder. Sve vaše HTML, CSS i JS datoteke automatski
postaju dostupne na web serveru!
⌨️ Docker Compose: Pregled ključnih komandi
Kada imate spreman docker-compose.yml, otvorite terminal u istom folderu i koristite
sljedeće komande:
| Komanda | Šta zapravo radi? |
|---|---|
docker compose up
|
Čita .yml
fajl, kreira mrežu, volumene i pokreće kontejnere. Ako slika (image) nije na računaru, prvo
će uraditi pull. |
docker compose up -d
|
Isto kao gore, ali u pozadini (detached). Terminal vam ostaje slobodan za druge komande. |
docker compose up -d --build
|
Ponovo izgradi Image-e iz Dockerfile-a prije pokretanja. Koristite nakon promjene koda. |
docker compose stop
|
Samo zaustavlja rad kontejnera. Kontejner i dalje postoji u memoriji, portovi su i dalje rezervisani, ali procesi ne rade. |
docker compose start
|
Ponovo pokreće
prethodno zaustavljene kontejnere (one koji su stopani kroz stop). |
docker compose restart
|
Restartuje sve servise
bez brisanja. Ekvivalent stop + start. |
docker compose down
|
Uništava sve: zaustavlja kontejnere, briše ih i briše internu mrežu. Ne briše vaše fajlove na disku (HTML, kod), ali briše privremene podatke unutar kontejnera. Volume diskovi ostaju netaknuti. |
docker compose down -v
|
⚠️
OPREZ: Isto kao down, ali dodatno briše i Volume diskove. Svi
podaci u bazi se nepovratno gube! Koristite samo kada svjesno želite
resetovati sve od nule. |
docker compose ps
|
Lista sve servise
definirane u vašem .yml fajlu i pokazuje da li su Up (rade)
ili Exit (ugašeni). |
docker compose logs |
Prikazuje logove svih pokrenutih servisa. Korisno za debugging kada nešto ne radi. |
🏗️ Dockerfile: Kako "ispeći" vlastiti kod
U profesionalnom svijetu mi nećemo samo vući gotove Nginx servere. Naš posao je da Microsoftov ili Node.js kod pretvorimo u novi Custom Image! To radimo kroz tekstualni fajl bez ekstenzije zvani Dockerfile. U njemu dajemo Dockeru upute (recepte) korak-po-korak.
# FAZA 1: Kompajliranje koda ("Build" platforma - ogromna)
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
WORKDIR /App
# Kopiraj samo cs-proj (da Docker kešira ovisnosti i ubrza stvar) i instaliraj pakete (NuGet)
COPY *.csproj ./
RUN dotnet restore
# Sada iskopiraj ostatak svih C# kodova i KOMPAJLIRAJ API (publish)
COPY . ./
RUN dotnet publish -c Release -o out
# FAZA 2: Produkcijsko Pokretanje (Ekstremno sitna i laka platforma)
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /App
# Preuzmi samo pre-kompajlirane .dll fajlove iz ogromne prve faze
COPY --from=build-env /App/out .
# Kada se kontejner upali, komanduj Windows/Linux serveru da pokrene taj API
ENTRYPOINT ["dotnet", "MojaAplikacija.dll"]
Sada kucamo build (ispeci Image) i run (upali ga!).
docker build -t moja_aplikacija .
docker run -d -p 5000:8080 moja_aplikacija
🗄️ Trajnost Podataka: Volumes
U Dockeru postoji jedno neumoljivo pravilo: Sve što se napravi ili promijeni unutar kontejnera
se trajno briše onog trenutka kada se kontejner ugasi (Stateless arhitektura).
Ovo je katastrofalno ako vrtimo SQL Server kontejner. Ako se takav kontejner resetuje – svi podaci
korisnika
nestaju zauvijek!
Ovo se sprječava koristeći Volumene (Volumes) – trajne dijelove diska koji su "povezani" sa kontejnerom. Kontejner misli da zapisuje po svojim internim folderima, ali Docker te foldere transparentno mapira na vaš lokalni hard-disk!
📦 Dva tipa Volume mapiranja
- Named Volume (npr.
-v MojVolumen:/var/opt/mssql): Docker automatski kreira i upravlja ovim volumenom. Podaci se čuvaju duboko unutar Docker Engine-a na lokaciji koju Docker sam odabere (na Windowsu obično unutar WSL Linux distribucije:\\wsl$\docker-desktop-data\data\docker\volumes\MojVolumen\_data). Vi ne birate lokaciju – Docker to radi za vas. - Bind Mount (npr.
-v X:/db_backup:/var/opt/mssql/backup): Vi eksplicitno birate folder na PC-ju (lijeva strana) i vezujete ga za folder unutar kontejnera (desna strana). Sve što kontejner upiše u/var/opt/mssql/backup, odmah je vidljivo uX:\db_backupna vašem Windows Exploreru!
SQL Server Primjer u Dockeru
Nema instalacije i 40 minuta registry muke! Jedna komanda diže potpuno funkcionalan MS SQL Server uz
mapiranje porta (1433) lokalno, postavljanje lozinke za SuperAdmina (-e),
i
trajno čuvanje podataka kroz volume (-v)!
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=NasaLozinka!2026" --name moj_sql_server -p 1433:1433 -v sql_server_podaci:/var/opt/mssql -d mcr.microsoft.com/mssql/server:2022-latest
Gdje su moji .mdf i .ldf fajlovi?
Kada se koristi Named Volume (kao gore: sql_server_podaci), SQL Server
interno čuva .mdf i .ldf fajlove
na Linux putanji /var/opt/mssql/data/ unutar kontejnera. Docker te fajlove automatski
sprema na vaš disk,
ali na lokaciji koja nije jednostavno dostupna kroz Windows Explorer.
Ako želite direktan pristup tim fajlovima sa svog PC-ja, koristite Bind Mount umjesto Named Volume-a:
docker run ... -v C:/MojiSQLPodaci:/var/opt/mssql -d mcr.microsoft.com/mssql/server:2022-latest
Sada otvarate C:\MojiSQLPodaci\data\ u Windows Exploreru i
tamo vidite .mdf i .ldf fajlove kao da je SQL Server instaliran lokalno!
💾 Backup i Restore baze kroz SSMS
Jedan od najčešćih scenarija: imate SQL Server u kontejneru, koristite SQL Server Management
Studio (SSMS) sa svog
Windows PC-ja, i želite napraviti backup baze ili restore postojećeg
.bak fajla.
Problem je što SSMS komunicira sa SQL Serverom unutar kontejnera, pa sve putanje za backup/restore moraju biti Linux putanje unutar kontejnera, a ne Windows putanje vašeg PC-ja!
Rješenje: Bind Mount za Backup folder
Prilikom pokretanja SQL kontejnera, dodajte još jedan -v parametar koji mapira lokalni
Windows folder
na backup folder unutar kontejnera:
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=NasaLozinka!2026" --name moj_sql_server -p 1433:1433 -v sql_server_podaci:/var/opt/mssql -v X:/db_backup:/var/opt/mssql/backup -d mcr.microsoft.com/mssql/server:2022-latest
Backup baze iz SSMS-a: Otvorite SSMS, spojite se na localhost,1433, desni
klik na bazu → Tasks → Back Up...
i za Destination upišite: /var/opt/mssql/backup/MojaBaza.bak. Fajl će se pojaviti u
X:\db_backup\MojaBaza.bak na vašem PC-ju!
Restore baze iz SSMS-a: Kopirajte vaš .bak fajl u folder
X:\db_backup\ na PC-ju.
U SSMS-u kliknite Restore Database, i za Source → From device upišite:
/var/opt/mssql/backup/MojaBaza.bak.
SQL Server unutar kontejnera automatski vidi taj fajl jer je folder mapiran!
🔄 Životni ciklus volumena
Volumeni žive nezavisno od kontejnera. To znači:
docker compose down– briše kontejnere i mrežu, ali volumeni ostaju netaknuti. Vaši podaci u SQL bazi preživljavaju!docker compose down -v– briše kontejnere, mrežu i volumene. Svi podaci se nepovratno gube!docker compose up -d(ponovo) – Docker pronalazi postojeće volumene po imenu i automatski ih ponovo priključuje na nove kontejnere. Baza je opet tu sa svim podacima!
Kako vidjeti sve volumene na računaru?
Koristite komandu docker volume ls da vidite listu svih volumena. Za brisanje jednog
volumena: docker volume rm ime_volumena. Za brisanje svih nekorištenih volumena:
docker volume prune.
📋 Definisanje volumena u Docker Compose
U docker-compose.yml fajlu volumeni se definišu na dva mjesta:
services:
moj-servis:
image: mcr.microsoft.com/mssql/server:2022-latest
volumes:
# 1. Named Volume (Docker upravlja lokacijom)
- baza_podaci:/var/opt/mssql
# 2. Bind Mount (vi birate Windows folder)
- C:/backup:/var/opt/mssql/backup
# Svi Named Volumeni MORAJU biti registrovani ovdje na dnu:
volumes:
baza_podaci: # Docker kreira i čuva ovaj volumen automatski
🔗 Dijeljenje volumena između dva kontejnera
Jedan od najmoćnijih koncepata: isti volumen može biti priključen na više kontejnera istovremeno. Ovo omogućava scenarije poput: ASP.NET API piše logove u folder, a drugi kontejner (npr. servis za monitoring) čita te iste logove u realnom vremenu.
version: '3.8'
services:
# Kontejner 1: .NET API koji PIŠE logove
api-aplikacija:
build: ./MojaAplikacija
container_name: dotnet_api
ports:
- "5000:8080"
volumes:
- app_logovi:/app/logs # Piše log fajlove u /app/logs
# Kontejner 2: Servis koji ČITA logove (npr. monitoring, analitika)
log-reader:
image: alpine:latest
container_name: citac_logova
volumes:
- app_logovi:/data/logs:ro # Čita ISTE logove, :ro = samo čitanje!
command: tail -f /data/logs/*.log
volumes:
app_logovi: # Oba kontejnera dijele ovaj volumen!
Kako ovo funkcioniše?
Docker kreira jedan jedini Named Volume app_logovi na disku. Kada
api-aplikacija upiše fajl u
/app/logs/app-2026-03-15.log, taj fajl je istog trenutka vidljiv u
kontejneru log-reader
na putanji /data/logs/app-2026-03-15.log. Oba kontejnera gledaju u isti fizički folder
na disku!
📝 Pristup logovima .NET aplikacije sa PC-ja
Ako želite vidjeti logove vaše ASP.NET aplikacije direktno u Windows Exploreru (bez ulaska u kontejner), koristite Bind Mount:
# Logovi se pišu u C:\projekti\logovi na vašem Windowsu
docker run -d -p 5000:8080 -v C:\projekti\logovi:/app/logs moja_aplikacija
Sada otvorite C:\projekti\logovi\ u Windows Exploreru i vidjet ćete sve .log
fajlove koje vaša
.NET aplikacija generira unutar kontejnera. Promjene se vide u realnom vremenu!
Konfiguracija logiranja u .NET-u
Da bi .NET aplikacija pisala logove u folder /app/logs unutar kontejnera, potrebno je
konfigurirati
Serilog ili NLog u vašem appsettings.json da koristi putanju
/app/logs/ kao destinaciju.
Docker će automatski proslijediti sve upisane fajlove na vaš lokalni Windows folder kroz Bind Mount!
🌐 Umrežavanje Kontejnera (Docker Networks)
Imamo upaljen SQL Server u jednom kontejneru (nazvanom moj_sql_server). Sada želimo podići
i naš C# API kontejner koji će čitati podatke iz njega.
Ovdje dolazimo do najveće zamke za početnike!
⚠️ OPREZ: localhost ne znači isto unutar kontejnera!
Kontejneri su potpuno izolirani procesi. Vaš ASP.NET API kontejner nema pristup
localhostu vašeg Windows PC-ja.
Ako u appsettings.json stavite Server=localhost;Database=..., API će
tražiti bazu na svom vlastitom internom localhostu unutar svog kontejnera. Tamo baze
naravno nema i aplikacija će pasti!
Rješenje je stvoriti Docker Mrežu (Network) – zamišljeni LAN kabal (switch) u koji ćemo uključiti oba kontejnera kako bi se međusobno vidjela po dodijeljenom imenu kontejnera.
# 1. Kreirajmo virtuelni switch (mrežu)
docker network create backend_mreza
# 2. Ugasimo prethodni SQL Server i pokrenemo ga ponovo, ali sada priključen na našu mrežu
docker rm -f moj_sql_server
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=NasaLozinka!2026" --name moj_sql_server --network backend_mreza -d mcr.microsoft.com/mssql/server:2022-latest
# 3. Sada palimo i naš API, i on se također priključuje na 'backend_mreza'
# Umjesto localhost u Connection Stringu koristi se "moj_sql_server" (ime prvog kontejnera)!
docker run -d -p 5000:8080 --name moja_aplikacija --network backend_mreza -e "ConnectionStrings__DefaultConnection=Server=moj_sql_server;Database=Porezi;User Id=sa;Password=NasaLozinka!2026;TrustServerCertificate=True" moja_aplikacija
Sada Docker igra ulogu DNS servera – kada C# kod zovne Server=moj_sql_server, Docker prevodi
to u pravu internu IP adresu baze u mreži backend_mreza i naš API uspješno čita podatke!
🎼 Orkestracija: Docker Compose
Kucanje PowerShell komandi sličnih onoj iznad svaki put je put u ludilo, naročito ako vaša aplikacija
zahtijeva 1 SQL bazu, 1 Redis Keš server, i 3 Mikroservisa (API-ja) da rade istovremeno!
Docker Compose vadi stvar tako što vam dopušta da cijelu infrastrukturu opišete u
jednoj yaml datoteci, te upalite cijeli ekosistem odjednom!
version: '3.8' # Verzija standarda compose dokumenta
services: # Ovdje definišemo šta sve 'podižemo'
baza-poreske-uprave: # Naš proizvoljan naziv servisa (kontejnera)
image: mcr.microsoft.com/mssql/server:2022-latest # Odakle skidamo sistem
container_name: sql_server_poreska # Fiksno ime kontejnera kada se upali
environment:
- ACCEPT_EULA=Y # Microsoftov EULA pristanak
- MSSQL_SA_PASSWORD=NasaLozinka!2026 # Šifra za 'sa' korisnika
ports:
- "2433:1433" # Mapiranje porta (Host:Kontejner)
volumes:
- poreska_baza_podaci:/var/opt/mssql # Trajno čuvanje same baze (VOLUME)
- X:/db_backup:/var/opt/mssql/backup # Fizički folder za bekap
restart: always # Pravilo: Ako padne kontejner ili se PC restarta, upali ga sam!
volumes: # Definisani volumeni ('Virtualni tvrdi diskovi') moraju biti ovdje pobrojani
poreska_baza_podaci:
Objašnjenje svake linije
version: '3.8'– Verzija Docker Compose specifikacije. Novije verzije podržavaju više funkcionalnosti.services:– Sekcija u kojoj nabrajamo svaki kontejner (servis) koji želimo pokrenuti.baza-poreske-uprave:– Proizvoljno ime servisa. Docker Compose koristi ovo ime kao interni DNS naziv za mrežnu komunikaciju sa drugim kontejnerima.image:– Određuje koji Image se skida sa Docker Hub-a. Ovo je oficial Microsoft SQL Server 2022.container_name:– Fiksno ime kontejnera vidljivo udocker ps. Bez ovoga Docker generira nasumično ime.environment:– Varijable okoline koje se proslijeđuju u kontejner pri pokretanju (EULA pristanak i lozinka).ports: "2433:1433"– Mapiranje porta. Vaš SSMS se spaja nalocalhost,2433, a Docker prosljeđuje na interni port1433unutar kontejnera.volumes: poreska_baza_podaci:/var/opt/mssql– Named Volume koji trajno čuva .mdf/.ldf fajlove baze čak i nakon brisanja kontejnera.volumes: X:/db_backup:/var/opt/mssql/backup– Bind Mount koji mapira fizički Windows folderX:\db_backupu kontejnerov/var/opt/mssql/backup. SSMS backup sa putanjom/var/opt/mssql/backup/MojaBaza.bakautomatski sprema fajl na vaš PC!restart: always– Ako kontejner padne ili se računar restartuje, Docker ga automatski ponovo pokreće.volumes:(na dnu) – Volumeni navedeni unutar servisa moraju biti registrovani na dnu fajla.
Da biste upalili cijeli sistem iz docker-compose.yml fajla, u folderu kucate:
docker compose up -d
Za gašenje i brisanje kontejnera: docker compose down (Volume diskovi ostaju netaknuti!).
Za potpunu listu svih Compose komandi pogledajte sekciju ⌨️ Docker Compose:
Pregled ključnih komandi iznad.
🏁 Zaključak kursa
Ovladavanje Docker konceptom je bitno. Ako vaša arhitektura radi preko Compose fajla kod vas na laptopu – ona mora raditi identično i na produkcionom serveru bilo kojeg klijenta. To se zove Uvezana isporuka (CI/CD) i sa tim prestaje mit o "Radi kod mene!".