Dockerfile Nasıl Yazılır ? Docker Dersleri 2

Dockerfile image oluşturmak için kullanılan template dosyalarıdır.

Docker Nedir bilmiyorsanız ilk dersimize bakabilirsiniz. Docker Nedir ?

Uygulamamız için docker file yazarken başka Image’leri kullanacağız ve onların üstüne layer(katman) ekleyeceğiz.

Dockerfile yazdığımız her komut istisnalar hariç layer olarak image’e eklenir. Hadi gelin dockerfile nasıl yazılır öğrenelim.

Sadece print işlemi olan python script’i için basit bir Dockerfile yazalım.

Dockerfile yazmak istediğimiz script aşağıdaki gibidir

#example.py
print("Our first docker image")

Öncelikle Python’a ihtiyacımız var. Python ihtiyacımızı aşağıdaki gibi FROM komutu ile sağlayabiliriz. FROM komutu verilen ad ve Tag’deki Image’i Docker Hub’dan çeker. Daha sonra yazacağımız komutlar bu image üzerine katman olarak eklenecek.

FROM python:3

İki noktadan sonraki kısım tag olarak adlandırılır. Python 3 kullanacağımızı belirtiyoruz. Eğer siz isterseniz daha spesifik bir versiyon verebilirsiniz. (3.9.4, 3.10 vb.) gibi

Not: Spesifik versiyon vermek yeni versiyon ile gelebilecek hataları engelleyeceğinden Best practice (Kullanılması önerilen) olarak gösterilir.

FROM python:3

WORKDIR /app

COPY . .

WORKDIR ile container içerisinde app klasörünü çalışma alanımız olarak gösteriyoruz.

COPY komutu Dockerfile’ın bulunduğu yerdeki tüm dosyaları /app klasörü içerisine kopyalıyor. WORKDIR belirttiğimiz için “.” ile belirtilen alan orası oluyor.

Bu işlemi WORKDIR kullanmadan asagıdaki gibi yapabilirdik.

FROM python:3

COPY .  ./app
FROM python:3

WORKDIR /app

COPY . .

CMD ["python", "example.py"]

CMD ile başlatacağımız dosyamızı veriyoruz ve basit bir şekilde ilk Dockerfile’ımızı yazmış oluyoruz.

Dockerfile Build

docker build .

docker build komutu ile dockerfile’ımızı image’e dönüştürüyoruz.

sha256:’dan sonraki kısım bizim image ‘imiz oluyor bu kısmı docker run komutuna verdiğimizde uygulamamız çalıştırılacak.

Dockerfile Örnekleri ve Best Pacticeler

1.Django Projesi

Django projelerimden birisinin dockerfile ‘ini inceleyelim. Proje için tıklayınız.

FROM python:3.8
ENV PYTHONBUFFERED 1

RUN mkdir /app
WORKDIR /app

EXPOSE 9000

COPY requirments.txt /app/
RUN pip install -r requirments.txt
COPY . /app/

CMD [ "python", "start.py" ]
  • Base image olarak python 3.8 kullandık.
  • ENV ile ortam değişkeni ekledik.
  • RUN komut ile container içerisinde komut çalıştırabiliyoruz. Burada RUN komutu ile app klasörü oluşturduk.
  • WORKDIR ile çalışma klasörü belirledik. Burada WORKDIR zaten app adında bir klasör oluşturuyor. Bir önceki RUN komutu Bad practice(Kullanılmaması gereken).
  • EXPOSE komutu ile portu dışarıya açtık. Her container birbirinden ve ana bilgisayardan izole bir şekilde çalıştığı için uygulamamıza erişmek istediğimizde port açmamız lazım.
COPY requirments.txt /app/
RUN pip install -r requirments.txt
COPY . /app/

Burada görüldüğü gibi 2 adet copy işlemi var bunun neden böyle yapıldığını soruyor olabilirsiniz.

Yazının başında da dediğim gibi her yazdığımız komut image üzerine layer(katman) olarak konur. Dockerfile ‘da değişmeyen katmanlar tekrar derlenmez yani örnek verecek olursak bir kere python:3.8 indirdiğimiz de bir dahaki dockerfile derlememizde bu kısım hızlı bir şekilde atlayacak. Bizde Django uygulamamızı geliştirirken kodda değişiklik yapacağız fakat requirments.txt içerisinde nadiren bir şeyler değişecektir bu yüzden bu satırların tekrar derlenmesini beklememiz gerekmeyecek direk 3.satırdan katman üretmeye başlayacak ondan öncesini olduğu gibi alacaktır.

RUN komutu pip ile requirmentları(modülleri) indiriyor. Bu satır da requirments.txt değişmediği sürece çalışmayacak.

Best Practice: Bağımlılık(kütüphane, modül listesi) dosyalarını daha önce atıp. İlk bağımlılıkları indirmek Best Practicedir Python uygulamaları için requirments.txt Node uygulamaları için package.json.

CMD [ "python", "start.py" ]

Bu satırda bir python script’i çalıştırıyoruz. Normalde django çalıştırma şekli python manage.py runserver şeklinde peki biz burada niye bu şekilde çalıştırmadık gelin inceleyelim.

Start.py dosyası start.sh dosyasını çağırıyor bu dosya içeriğini inceleyeceğiz.

python manage.py makemigrations --noinput
python manage.py migrate
python manage.py runserver 0.0.0.0:9000

Start.sh içeriğinden gördüğümüz gibi django çalıştırmadan önce database için migrationları yapıyoruz.

Best Practice: Eğer uygulamanız çalışmadan önce bir kaç işlem yapılması gerekiyorsa o işlemleri bu şekilde bir dosya ile çalıştırmalısınız.

2.VueJS Projesi (Herhangi bir JS Framework)

Vuejs projemin dockerfile kodlarını inceleyelim. Projeye ulaşmak için tıklayınız. Proje Django projesi ile birlikte kullanılmaktadır.

FROM node:lts-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# production stage
FROM nginx:stable-alpine as production
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Bu dockerfile’ı incelediğimizde 2 adet From kullanıldıgını göreceksiniz. Buradaki ilk kısım projenin derlenmesi ikinci kısım ise kullanıcıya sunulması için yazılmıştır.

COPY package*.json ./
RUN npm install
COPY . .

Js frameworklerı için de aynı Best practice ‘in kullanılabildiğini görüyoruz. Bağımlı bulunduğu kütüphaneler daha önce indirilerek o kısımda değişiklik olmadığı sürece o katmanlar aynı şekilde kullanılıyor.

İlk kısımda build alındığında(derlendiğinde) dosyalar dist adlı klasör altına çıkıyor.

FROM node:lts-alpine as build
.
.
.

FROM nginx:stable-alpine as production
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

İkinci kısımda (6.satır ile başlayan) build ile taglenmiş layer(katman)’dan dosyalar alınıp nginx katmanına kopyalanıyor.

Expose ile port dışa veriliyor. CMD ile nginx ayağa kaldırılıyor.

Docker build . ve docker run komutları ile uygulamamızı çalıştırmış oluruz. Denemek isterseniz projeyi klonlayıp dockerfile üzerinde değişiklikler yaparak Best practiceleri deneyimleyebilirsiniz.

Add a Comment

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir