Angular

Angular Docker ile Nasıl Deploy Edilir? Nginx Rehberi

Herkese Merhabalar arkadaşlar! Bugün hepimizin er ya da geç karşılaştığı bir konuya, Angular Docker ile deployment işlemine değineceğiz. Eski usül “build alıp dosyaları sunucuya FTP ile atma” döngüsünden bunaldıysanız ve her şeyi dockerize etmeye karar verdiyseniz tam olarak doğru yerdesiniz. Docker ilk başta korkutucu gelebilir, ancak söz veriyorum bu yazının sonunda Node ve Nginx image’lerini kullanarak yazacağımız tek bir Dockerfile ile uygulamanızı kolayca yayına alabilir hale geleceksiniz.

Peki neden Angular Docker yolculuğuna çıkmalıyız?

CI/CD süreci geliştirme ortamında artık bir standart haline geldi. Bununla birlikte kariyer hedefleri olan bir geliştirici olarak Docker teknolojisini öğrenmek gittikçe bir zorunluluk haline geliyor. Bu yüzden aşağıda size sadece kopyala-yapıştır yapacağınız bir Dockerfile bırakıp kapatmayacağım. Bunun yerine bütün adımları tek tek, neden o satırı yazdığımızı açıklayarak ilerleyeceğiz; sağlam bir Angular Docker imajının nasıl üretildiğini anlamanız için. Tabii ki tüm basamakların hemen altında tamamlanmış Dockerfile örneğini de paylaşacağım.

Burada kullanacağımız yaklaşıma multi-stage build deniyor. Mantığı aslında çok basit: bir aşamada Node kullanıp uygulamayı build ediyoruz, sonra sadece o build’in çıktısını alıp minik bir Nginx image’ine taşıyoruz. Böylece son imajımızın içinde node_modules gibi yüzlerce megabaytlık gereksiz yük taşımıyoruz. Detaylarını Docker’ın resmi multi-stage dokümantasyonunda da bulabilirsiniz.

1. Build Image Oluşturulması ve Uygulamanın Build Edilmesi

Bu bölümde uygulamamızı, içerisinde Node.js bulunan bir container kullanarak build alacağız.

FROM node:20-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
  1. FROM node:20-alpine AS build — Docker Hub üzerinde bulunan node:20-alpine image’ini kullanarak bir container oluşturuyoruz ve buna build adını veriyoruz. Önemli bir not: versiyon seçerken kullandığınız Angular sürümünü göz önünde bulundurmanız gerekiyor. Hangi Angular sürümü için hangi Node sürümünü tercih etmeniz gerektiğini Angular’ın resmi versiyon uyumluluk tablosunda bulabilirsiniz.
  2. WORKDIR /app — İşlemlerimizi gerçekleştireceğimiz dizini container içerisinde oluşturuyoruz.
  3. COPY package.json package-lock.json ./ — Bağımlılık dosyalarımızı önce kopyalıyoruz. Burada küçük ama kritik bir numara var: bütün projeyi değil de sadece bu iki dosyayı önce kopyalarsak, kodumuz değiştiğinde Docker npm ci katmanını cache’ten okuyabilir ve build sürelerimiz uçar gider.
  4. RUN npm ci — Kopyaladığımız package-lock.json içindeki bağımlılıkları indiriyoruz. Burada bilerek npm install yerine npm ci kullanıyorum; lock dosyasına birebir sadık kaldığı için CI/CD ortamlarında çok daha güvenilir ve tekrarlanabilir sonuç verir.
  5. COPY . . — Uygulamamızın geri kalan tüm kodunu app dizinine taşıyoruz.
  6. RUN npm run build — Ve son olarak production build’imizi alıyoruz.

2. Uygulamanın Nginx Üzerinden Servis Edilmesi

Bu bölümde ise az önce build aldığımız Angular uygulamasını Nginx kullanarak servis edeceğiz, yani yayına alacağız.

FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /app/dist/application/browser /usr/share/nginx/html
EXPOSE 80
  1. FROM nginx:1.27-alpine — Docker Hub üzerindeki hafif Nginx image’ini kullanıyoruz.
  2. COPY nginx.conf … — Aşağıda paylaştığım nginx.conf dosyasını projenizin ana dizinine eklemeniz gerekiyor. Bu yazıda Nginx üzerinde fazla durmayacağız, ancak ayarların tüm detayını merak ediyorsanız Nginx’in resmi başlangıç rehberine göz atabilirsiniz.
  3. COPY –from=build … — İşte multi-stage build’in büyüsü tam burada devreye giriyor: birinci aşamada oluşturduğumuz build container’ı içindeki dist çıktısını alıp Nginx’in servis edeceği dizine taşıyoruz. Burada küçük ama önemli bir güncel detay var: Angular 17 ve sonrasında yeni application builder çıktıyı dist/<app-adı>/browser altına koyuyor. Daha eski sürümlerde ise yol sadece dist/<app-adı> şeklindeydi, dolayısıyla kendi angular.json ayarınıza göre bu yolu kontrol etmenizi tavsiye ederim. (Angular 17 ile gelen diğer yeniliklere Angular 17 ile Bizi Neler Bekliyor yazımdan ulaşabilirsiniz.)
  4. EXPOSE 80 — HTTP isteklerinin erişilebilir olması için 80 portunu dışarı açıyoruz.

Önbellek tuzağından kurtaran nginx.conf

Varsayılan Nginx ayarları ile minik bir oynama yapıyoruz ve index.html dosyasının tarayıcı tarafından önbelleğe alınmasını engelliyoruz. Bu sayede ileride çıkacağımız yeni versiyonlarda kullanıcıların ekranında eski bir uygulamayla karşılaşması gibi can sıkıcı önbellek sorunlarından kurtulmuş oluyoruz. Ayrıca try_files satırı, Angular gibi bir SPA’da sayfa yenilendiğinde 404 hatası almamanız için şart.

events {}

http {
  include /etc/nginx/mime.types;
  server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    location / {
      if ($uri = '/index.html') {
        add_header Cache-Control "no-store" always;
      }
      try_files $uri $uri/ /index.html;
    }
  }
}

Tamamlanmış Angular Docker dosyası

Ve Dockerfile dosyamız kullanıma hazır. Aşağıda tam halini paylaşıyorum. Ancak tavsiyem yukarıdaki adımları okumanız, kopyala-yapıştır yapıp geçmemeniz 🙂 Çünkü yetkin bir yazılımcı olarak Docker bilmeniz gerekenler listesinin başlarında yer alıyor ve kariyer yolculuğunuzda bir noktada bu tecrübe mutlaka sizden istenecektir.

FROM node:20-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build:prod

FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /app/dist/application/browser /usr/share/nginx/html
EXPOSE 80

İmajı build edip çalıştırmak ise oldukça basit:

docker build -t angular-app .
docker run -p 8080:80 angular-app

Artık tarayıcınızdan http://localhost:8080 adresine giderek dockerize ettiğiniz uygulamanızı görebilirsiniz. Gördüğünüz gibi Angular Docker kombinasyonu ilk bakışta göründüğü kadar karmaşık değilmiş.

Söyleyeceklerim şimdilik bu kadar. Eğer Angular dünyasını daha derinlemesine keşfetmek isterseniz Angular vs React ve Angular’ın Dependency Injection yazılarıma da göz atabilirsiniz. Aklınıza takılan başka bir husus varsa sormaktan çekinmeyin, herkese iyi çalışmalar dilerim 🙂

teoman.me

Recent Posts

Angular Signals Nedir ve Neden Kullanmalıyız?

Angular Signals nedir, Zone.js tabanlı change detection'ın neden yerini alıyor ve signal(), computed(), effect() kavramlarını…

1 day ago

How to Implement Model Context Protocol (MCP) in Your AI Projects

Building AI applications without a clear context management system is like coding without version control.…

1 year ago

What is Model Context Protocol (MCP) in LLM Systems?

In the world of AI and Large Language Models (LLMs), one thing has become very…

1 year ago

Angular 17 ile Bizi Neler Bekliyor ?

Herkese Merhabalar. Bildiğiniz üzere bu ay Angular 17 yepyeni bir imaj çalışması ile birlikte yayına…

3 years ago

OpenLayers Nasıl Kullanılır ?

Herkese merhaba arkadaşlar. Önceki yazımızda openlayers nedir ve neden kullanmalıyız sorunu yanıtlamıştık. Popüler harita kütüphanelerinden…

3 years ago

Openlayers Nedir ? Neden Tercih Etmeliyiz ?

Merhaba arkadaşlar. Eğer CBS (Coğrafi Bilgi Sistemleri) dünyasına yeni yeni adımlar atıyorsanız adını sık sık…

3 years ago