Najvažnije iz članka
- Docker Compose omogućava jednostavnu orkestraciju višestrukih servisa (aplikacije, baze podataka) u izoliranim kontejnerima za lokalni razvoj.
- Nginx reverse proxy koristi se za usmjeravanje prometa na različite Docker servise putem domena/subdomena i omogućuje HTTPS, simulirajući produkcijsko okruženje.
- Postavljanje uključuje generiranje samopotpisanih SSL certifikata, konfiguraciju Nginx virtualnih hostova, definiciju svih servisa u `docker-compose.yml` i ažuriranje `hosts` datoteke.
- Ovo okruženje pruža konzistentnost, izolaciju, hot-reloading (uz pravilnu konfiguraciju volumena) i olakšava testiranje aplikacija s HTTPS-om, smanjujući probleme "radi kod mene".
Sadržaj članka
- Uvod: Moć Dockera i lokalnog razvoja
- Prednosti korištenja Docker Compose i Nginx za lokalni razvoj
- Preduvjeti
- Projektna struktura
- Korak 1: Kreiranje samopotpisanih SSL certifikata
- Korak 2: Konfiguracija Nginx proxyja
- nginx/nginx.conf
- nginx/conf.d/myapp.conf
- Korak 3: Postavljanje Hosts datoteke
- Korak 4: Definiranje Docker Compose datoteke (docker-compose.yml)
- Primjer app/html/index.html (za app servis)
- Primjer api/html/index.html (za api servis)
- Primjer database/init.sql (za db servis)
- Korak 5: Pokretanje okruženja
- Korak 6: Testiranje aplikacije
- Napredni savjeti i daljnji koraci
- Hot-reloading za razvoj
- Korištenje .env datoteke za varijable okruženja
- Više aplikacija/subdomena
- Debugging
- Zaključak
Uvod: Moć Dockera i lokalnog razvoja
U svijetu modernog razvoja softvera, efikasnost i konzistentnost su ključne. Tradicionalni pristupi postavljanju razvojnih okruženja često su bili opterećeni problemima poput "radi kod mene" situacija, nekompatibilnosti ovisnosti i dugotrajnog konfiguriranja. Docker je transformirao ovaj pejzaž, omogućujući developerima da pakiraju aplikacije i sve njihove ovisnosti u prenosive, izolirane kontejnere. Docker Compose, nadogradnja na Docker, dodatno pojednostavljuje orkestraciju više kontejnera, čineći ga idealnim alatom za definiranje i pokretanje mikroservisnih arhitektura na lokalnom stroju.
Ovaj tutorial će vas provesti kroz proces postavljanja cjelovitog lokalnog razvojnog okruženja koristeći Docker Compose za orkestraciju više servisa, Nginx reverse proxy za usmjeravanje prometa i HTTPS za sigurnu komunikaciju. Naučit ćete kako konfigurirati baze podataka, aplikacijske servise i kako ih povezati u koherentan sustav koji imitira produkcijsko okruženje. Cilj je postići fleksibilnost, reproducibilnost i smanjiti “razlika između razvoja i produkcije.”
Prednosti korištenja Docker Compose i Nginx za lokalni razvoj
Kombinacija Docker Compose i Nginx reverse proxyja nudi brojne prednosti za lokalni razvoj:
- Izolacija okruženja: Svaki servis (baza podataka, backend API, frontend aplikacija) izvršava se u vlastitom kontejneru, sprječavajući konflikte ovisnosti i osiguravajući čisto okruženje.
- Konzistentnost: Razvojno okruženje je identično za sve developere i blisko produkcijskom, smanjujući probleme pri implementaciji.
- Jednostavna orkestracija: Docker Compose datoteka (
docker-compose.yml) definira sve servise, mreže i volumene, omogućujući pokretanje cijelog sustava s jednom naredbom. - Upravljanje više aplikacija/servisa: Nginx reverse proxy omogućuje hostanje više različitih aplikacija ili verzija aplikacija na istom portu (npr. 80/443) putem različitih domena/subdomena, olakšavajući rad na više projekata istovremeno.
- HTTPS podrška: Konfiguriranje Nginxa s SSL/TLS certifikatima (čak i samopotpisanim za lokalni razvoj) omogućuje testiranje aplikacija s HTTPS-om, što je ključno za moderne web aplikacije.
- Pojednostavljena konfiguracija mreže: Docker Compose automatski stvara internu mrežu za kontejnere, a Nginx služi kao ulazna točka.
- Brzo postavljanje i uništavanje: Cijelo okruženje može se podići ili srušiti u sekundi, štedeći vrijeme i resurse.
Preduvjeti
Prije nego što započnemo, provjerite imate li instalirano sljedeće:
- Docker Desktop: Uključuje Docker Engine, Docker CLI i Docker Compose. Dostupno za Windows, macOS i Linux. Preuzmite s docker.com.
- Osnovno razumijevanje Dockera: Poznavanje koncepata poput slika (images), kontejnera (containers), volumena (volumes) i mreža (networks) je korisno.
- Osnovno razumijevanje Nginxa: Poznavanje osnovne konfiguracije Nginxa je prednost, ali nije nužno jer ćemo detaljno proći kroz konfiguraciju.
- Terminal/Bash: Za izvođenje naredbi.
Projektna struktura
Za ovaj tutorial, kreirat ćemo sljedeću strukturu direktorija:
my-dev-env/
├── docker-compose.yml
├── nginx/
│ ├── nginx.conf
│ ├── conf.d/
│ │ ├── default.conf
│ │ └── myapp.conf
│ └── certs/
│ ├── myapp.local.crt
│ └── myapp.local.key
├── app/
│ ├── Dockerfile (za frontend ili backend)
│ └── ... (kod aplikacije)
├── api/
│ ├── Dockerfile (za backend API)
│ └── ... (kod API-ja)
└── database/
└── ... (skripte za inicijalizaciju baze podataka)
Korak 1: Kreiranje samopotpisanih SSL certifikata
Za lokalni razvoj, koristit ćemo samopotpisane certifikate. To nam omogućuje testiranje HTTPS-a bez potrebe za pravim certifikatom. Vaš preglednik će prikazati upozorenje, ali to je očekivano za lokalni razvoj.
Stvorite direktorij nginx/certs unutar korijenskog direktorija projekta (my-dev-env).
Generirajte certifikate koristeći OpenSSL:
cd my-dev-env/nginx/certs
openssl req -x509 -nodes -newkey rsa:2048 -keyout myapp.local.key -out myapp.local.crt -days 3650 -subj "/CN=myapp.local"
Ova naredba će generirati myapp.local.key (privatni ključ) i myapp.local.crt (certifikat) koji vrijede 10 godina za domenu myapp.local.
Važna napomena za Windows/macOS: Da bi preglednik prihvatio ovaj certifikat kao "pouzdani" za lokalni rad, morat ćete ga ručno dodati u "Trust Store" (skladište pouzdanih certifikata) vašeg operativnog sustava. Pretražite "Add trusted certificate [your OS]" za detaljne upute.
Korak 2: Konfiguracija Nginx proxyja
Nginx će služiti kao ulazna točka za sve naše aplikacije, usmjeravajući promet na odgovarajuće Docker kontejnere. Stvorite direktorij nginx/conf.d i datoteke nginx/nginx.conf i nginx/conf.d/myapp.conf.
nginx/nginx.conf
Ovo je glavna Nginx konfiguracijska datoteka. Izbjegavajte mijenjanje ove datoteke osim ako niste napredni korisnik. Koristit ćemo je za uključivanje svih virtualnih hostova iz conf.d direktorija.
worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream app_backend {
server app:80;
}
upstream api_backend {
server api:80;
}
include /etc/nginx/conf.d/*.conf;
}
Objašnjenje:
worker_processes auto;: Nginx će automatski odrediti broj radnih procesa.upstream app_backend: Definira upstream grupu za našu glavnu aplikaciju.app:80se odnosi naappservis definiran udocker-compose.ymlna portu 80 unutar Docker mreže.upstream api_backend: Slično za API servis.include /etc/nginx/conf.d/*.conf;: Nginx će uključiti sve.confdatoteke izconf.ddirektorija. Tu ćemo definirati naše virtualne hostove.
nginx/conf.d/myapp.conf
Ovo je konfiguracija za našu specifičnu aplikaciju. Stvorit ćemo dva server bloka: jedan za HTTP redirekciju na HTTPS i drugi za HTTPS promet.
server {
listen 80;
server_name myapp.local www.myapp.local;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name myapp.local www.myapp.local;
ssl_certificate /etc/nginx/certs/myapp.local.crt;
ssl_certificate_key /etc/nginx/certs/myapp.local.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
location / {
proxy_pass http://app_backend;
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;
}
location /api/ {
proxy_pass http://api_backend/api/;
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;
}
}
Objašnjenje:
- Prvi
serverblok: Sluša na portu 80 (HTTP) za domenemyapp.localiwww.myapp.locali preusmjerava sav promet na HTTPS. - Drugi
serverblok:listen 443 ssl;: Sluša na portu 443 (HTTPS).ssl_certificateissl_certificate_key: Putanje do naših samopotpisanih certifikata unutar kontejnera.- Ostale
ssl_*direktive: Sigurnosne smjernice za SSL/TLS konfiguraciju. location / {}: Proslijeđuje sav promet koji dolazi na korijen (/) naapp_backend(naš frontend ili glavnu aplikaciju).location /api/ {}: Proslijeđuje sav promet koji počinje s/api/naapi_backend(naš backend API). Obratite pažnju na/api/na krajuproxy_passURL-a kako bi se putanja ispravno preveli.
Korak 3: Postavljanje Hosts datoteke
Da bi vaš operativni sustav mogao razriješiti myapp.local na vaš lokalni stroj, morate dodati unos u svoju hosts datoteku.
- Linux/macOS:
/etc/hosts - Windows:
C:\Windows\System32\drivers\etc\hosts
Dodajte sljedeći redak:
127.0.0.1 myapp.local www.myapp.local
Spremite promjene. Možda ćete trebati administratorske privilegije za to.
Korak 4: Definiranje Docker Compose datoteke (docker-compose.yml)
Sada ćemo definirati sve naše servise u docker-compose.yml datoteci u korijenskom direktoriju my-dev-env.
Za potrebe ovog tutoriala, koristit ćemo tri glavna servisa:
nginx: Naš Nginx reverse proxy.app: Primjer jednostavne Nginx web stranice (možete je zamijeniti vašim frontendom).api: Primjer jednostavne Nginx web stranice (možete je zamijeniti vašim backend API-jem).db: PostgreSQL baza podataka (ili drugi izbor).
version: '3.8'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/certs:/etc/nginx/certs:ro
depends_on:
- app
- api
networks:
- app_network
app:
# image: my-frontend-app:latest # Ako imate vlastiti Dockerfile
# build:
# context: ./app
# Dockerfile: Dockerfile
image: nginx:alpine # Za primjer, koristimo jednostavan Nginx
container_name: my-app
volumes:
- ./app/html:/usr/share/nginx/html:ro # Primjer: statični sadržaj
networks:
- app_network
api:
# image: my-backend-api:latest # Ako imate vlastiti Dockerfile
# build:
# context: ./api
# Dockerfile: Dockerfile
image: nginx:alpine # Za primjer, koristimo jednostavan Nginx
container_name: my-api
volumes:
- ./api/html:/usr/share/nginx/html:ro # Primjer: statični sadržaj
networks:
- app_network
db:
image: postgres:13
container_name: postgres_db
environment:
POSTGRES_DB: mydatabase
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- db_data:/var/lib/postgresql/data
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql # Opcionalno: za inicijalizaciju baze
networks:
- app_network
volumes:
db_data:
driver: local
networks:
app_network:
driver: bridge
Objašnjenje:
nginxservis:image: nginx:latest: Koristi službenu Nginx sliku.ports: Mapira portove 80 i 443 s hosta na kontejnere.volumes: Montira naše konfiguracijske datoteke i certifikate unutar Nginx kontejnera.depends_on: Osigurava daappiapiservisi budu pokrenuti prije Nginxa.networks: Povezuje Nginx naapp_network.
appservis:image: nginx:alpine: Za demonstraciju, koristimo lagani Nginx. U stvarnom slučaju, ovdje biste imali svoju frontend aplikaciju.build: Ako imate vlastiti Dockerfile za frontend (npr. React, Vue, Angular), koristili bistebuildsekciju icontextkoji pokazuje na direktorij vaše aplikacije.volumes: Montira vaš kôd (npr.app/htmlza statični Nginx sadržaj) u kontejner. Ovo je ključno za hot-reloading tijekom razvoja.
apiservis:- Slično
appservisu, samo za backend API (npr. Node.js, Python Flask/Django, Java Spring Boot).
- Slično
dbservis:image: postgres:13: Koristi PostgreSQL bazu podataka.environment: Postavlja varijable okruženja za konfiguraciju baze podataka (ime, korisnik, lozinka).volumes: Perzistentni volumen za podatke baze i opcionalnu skriptu za inicijalizaciju (init.sql).
volumessekcija: Definiradb_datavolumen za perzistenciju podataka baze.networkssekcija: Definira zajedničkuapp_networkkako bi se svi servisi mogli međusobno komunicirati pomoću imena servisa (npr.app,api,db).
Primjer app/html/index.html (za app servis)
<!DOCTYPE html>
<html>
<head>
<title>MyApp Frontend</title>
</head>
<body>
<h1>Dobrodošli na lokalni MyApp Frontend!</h1>
<p>Ovo je frontend aplikacija.</p>
<p>Pokušajte pristupiti API-ju na <a href=""/api/">/api/</a></p>"
</body>
</html>
Primjer api/html/index.html (za api servis)
<!DOCTYPE html>
<html>
<head>
<title>MyApp API</title>
</head>
<body>
<h1>Dobrodošli na lokalni MyApp API!</h1>
<p>Ovo je API servis.</p>
</body>
</html>
Primjer database/init.sql (za db servis)
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL
);
INSERT INTO users (name, email) VALUES ('Janko Horvat', 'janko.horvat@example.com') ON CONFLICT (email) DO NOTHING;
INSERT INTO users (name, email) VALUES ('Ana Anić', 'ana.anic@example.com') ON CONFLICT (email) DO NOTHING;
Korak 5: Pokretanje okruženja
Sada kada smo sve konfigurirali, pokrenimo naše Docker Compose okruženje.
Navigirajte u korijenski direktorij vašeg projekta (my-dev-env) u terminalu i izvršite sljedeću naredbu:
docker compose up -d
up: Podiže servise definirane udocker-compose.yml.-d: Pokreće kontejnere u "detached" modu (u pozadini).
Prvi put kada pokrenete ovu naredbu, Docker će preuzeti potrebne slike i izgraditi vaše aplikacije (ako ste koristili build sekciju). To može potrajati nekoliko minuta.
Ako želite vidjeti logove svih servisa, koristite:
docker compose logs -f
Za zaustavljanje i uklanjanje svih kontejnera, mreža i volumena (osim perzistentnih volumena ako nisu eksplicitno navedeni), koristite:
docker compose down
Za zaustavljanje i uklanjanje svih Docker resursa vezanih uz projekt (uključujući db_data volumen), koristite:
docker compose down -v
Korak 6: Testiranje aplikacije
Otvorite svoj web preglednik i navigirajte na:
https://myapp.local/https://myapp.local/api/
Trebali biste vidjeti sadržaj index.html datoteka koje smo postavili za app i api servise. Ako ste ispravno dodali samopotpisani certifikat u "Trust Store" vašeg OS-a, preglednik ne bi trebao prikazivati upozorenja.
Ako dođe do problema, provjerite sljedeće:
- Docker kontejneri se pokreću:
docker compose psbi trebao pokazati da su svi servisi u statusuUp. - Nginx logovi:
docker compose logs nginxmože otkriti konfiguracijske greške. - Hosts datoteka: Provjerite je li
myapp.localispravno mapiran na127.0.0.1. - Firewall: Provjerite blokira li vaš firewall portove 80 ili 443.
Napredni savjeti i daljnji koraci
Hot-reloading za razvoj
Za moderne frontend (React, Vue, Angular) i backend (Node.js, Python Flask/Django) aplikacije, ključno je imati hot-reloading (ili barem automatsko ponovno pokretanje servisa pri promjeni koda).
Umjesto image: nginx:alpine za app i api, koristili biste build instrukciju koja referencira Dockerfile vaše aplikacije, a zatim montirali vaš lokalni kod u kontejner kao volumen.
Primjer za Node.js backend:
api:
build:
context: ./api # direktorij gdje je Dockerfile i kod API-ja
dockerfile: Dockerfile
volumes:
- ./api:/app # Montira lokalni /api direktorij u /app unutar kontejnera
- /app/node_modules # Isključuje node_modules iz montiranja, koristeći one unutar kontejnera
environment:
NODE_ENV: development
PORT: 80 # Aplikacija sluša na portu 80 unutar kontejnera
# command: npm run dev # Ako vaša aplikacija ima naredbu za razvoj s hot-reloadingom
networks:
- app_network
Unutar api/Dockerfile bi imali:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 80
CMD ["node", "server.js"]
Kod frontenda, slično. Često frontend dev serveri imaju vlastiti mehanizam za hot-reloading koji funkcionira s proxy_pass zbog Websocketsa.
Korištenje .env datoteke za varijable okruženja
Za osjetljive podatke (baze podataka, API ključevi) ili promjenjive konfiguracije, koristite .env datoteku u istom direktoriju kao docker-compose.yml.
.env datoteka:
POSTGRES_DB=mydb
POSTGRES_USER=myuser
POSTGRES_PASSWORD=mypassword
docker-compose.yml:
db:
image: postgres:13
container_name: postgres_db
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
# ... ostalo
Više aplikacija/subdomena
Za hostanje više aplikacija, jednostavno dodajte nove .conf datoteke u nginx/conf.d (npr. myotherapp.conf) i dodajte odgovarajuće unose u hosts datoteku (npr. myotherapp.local). Također dodajte servise u docker-compose.yml i eventualno upstream blokove u nginx.conf.
Debugging
- Provjerite Docker logove:
docker compose logs [ime_servisa] - Uđite u kontejner:
docker compose exec [ime_servisa] bash(ilishza Alpine slike) za provjeru datoteka, konfiguracije, mrežne povezanosti. - Inspekcija Docker mreže:
docker network inspect app_networkmože pomoći u razumijevanju kako su servisi povezani.
Zaključak
Postavljanje lokalnog razvojnog okruženja s Docker Compose i Nginx reverse proxyjem značajan je korak prema profesionalnijem i učinkovitijem razvoju. Ova konfiguracija pruža izolaciju, konzistentnost i fleksibilnost potrebnu za rad na složenim, višeservisnim aplikacijama. Iako početno postavljanje može zahtijevati malo truda, dugoročne prednosti u smislu smanjenja problema s okruženjem i ubrzanja razvoja su neprocjenjive. Slijedeći ovaj tutorial, imate čvrstu osnovu za izgradnju vlastitih naprednih razvojnih okruženja koja će vas pripremiti za produkciju.
Eksperimentirajte s različitim servisima, bazama podataka i konfiguracijama. Docker i Docker Compose su moćni alati, a ovladavanje njima ključno je za svakog modernog developera.
Komentari